diff --git a/plugins/ua_log_stdout.c b/plugins/ua_log_stdout.c index 176a51d36..1921b6216 100644 --- a/plugins/ua_log_stdout.c +++ b/plugins/ua_log_stdout.c @@ -40,12 +40,21 @@ const char *logCategoryNames[UA_LOGCATEGORIES] = {"network", "channel", "session", "server", "client", "userland", "securitypolicy", "eventloop", "pubsub", "discovery"}; -typedef struct { - UA_LogLevel minlevel; +/* Protect crosstalk during logging via global lock. + * Use a spinlock on non-POSIX as we cannot statically initialize a global lock. */ #if UA_MULTITHREADING >= 100 - UA_Lock lock; +# ifdef UA_ARCHITECTURE_POSIX +UA_Lock logLock = UA_LOCK_STATIC_INIT; +# else +void * volatile logSpinLock = NULL; +static UA_INLINE void spinLock(void) { + while(UA_atomic_cmpxchg(&logSpinLock, NULL, (void*)0x1) != NULL) {} +} +static UA_INLINE void spinUnLock(void) { + UA_atomic_xchg(&logSpinLock, NULL); +} +# endif #endif -} LogContext; #ifdef __clang__ __attribute__((__format__(__printf__, 4 , 0))) @@ -53,12 +62,10 @@ __attribute__((__format__(__printf__, 4 , 0))) static void UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category, const char *msg, va_list args) { - LogContext *logContext = (LogContext*)context; - if(logContext) { - if(logContext->minlevel > level) - return; - UA_LOCK(&logContext->lock); - } + /* MinLevel encoded in the context pointer */ + UA_LogLevel minLevel = (UA_LogLevel)(uintptr_t)context; + if(minLevel > level) + return; UA_Int64 tOffset = UA_DateTime_localTimeUtcOffset(); UA_DateTimeStruct dts = UA_DateTime_toStruct(UA_DateTime_now() + tOffset); @@ -67,6 +74,16 @@ UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category, if(logLevelSlot < 0 || logLevelSlot > 5) logLevelSlot = 5; /* Set to fatal if the level is outside the range */ + /* Lock */ +#if UA_MULTITHREADING >= 100 +# ifdef UA_ARCHITECTURE_POSIX + UA_LOCK(&logLock); +# else + spinLock(); +# endif +#endif + + /* Log */ printf("[%04u-%02u-%02u %02u:%02u:%02u.%03u (UTC%+05d)] %s/%s" ANSI_COLOR_RESET "\t", dts.year, dts.month, dts.day, dts.hour, dts.min, dts.sec, dts.milliSec, (int)(tOffset / UA_DATETIME_SEC / 36), logLevelNames[logLevelSlot], @@ -75,30 +92,25 @@ UA_Log_Stdout_log(void *context, UA_LogLevel level, UA_LogCategory category, printf("\n"); fflush(stdout); - if(logContext) { - UA_UNLOCK(&logContext->lock); - } + /* Unlock */ +#if UA_MULTITHREADING >= 100 +# ifdef UA_ARCHITECTURE_POSIX + UA_UNLOCK(&logLock); +# else + spinUnLock(); +# endif +#endif } static void -UA_Log_Stdout_clear(void *context) { - if(!context) - return; - UA_LOCK_DESTROY(&((LogContext*)context)->lock); - UA_free(context); -} +UA_Log_Stdout_clear(void *context) {} const UA_Logger UA_Log_Stdout_ = {UA_Log_Stdout_log, NULL, UA_Log_Stdout_clear}; const UA_Logger *UA_Log_Stdout = &UA_Log_Stdout_; UA_Logger UA_Log_Stdout_withLevel(UA_LogLevel minlevel) { - LogContext *context = (LogContext*)UA_calloc(1, sizeof(LogContext)); - if(context) { - UA_LOCK_INIT(&context->lock); - context->minlevel = minlevel; - } - - UA_Logger logger = {UA_Log_Stdout_log, (void*)context, UA_Log_Stdout_clear}; + UA_Logger logger = + {UA_Log_Stdout_log, (void*)(uintptr_t)minlevel, UA_Log_Stdout_clear}; return logger; }