diff options
author | Darian Biastoch <dbiastoch@de.adit-jv.com> | 2021-08-13 14:10:37 +0200 |
---|---|---|
committer | Saya Sugiura <39760799+ssugiura@users.noreply.github.com> | 2021-10-05 11:19:26 +0900 |
commit | f7f7e84fe08c5f1ba138c070501f962b741a1f80 (patch) | |
tree | f57b9825c4e95b73ba670ec3928cbb1e3708d701 | |
parent | daf4247d8cf7570b7541e34af4bd93454e5bb550 (diff) | |
download | DLT-daemon-f7f7e84fe08c5f1ba138c070501f962b741a1f80.tar.gz |
dlt_user: Make dlt_init thread safe
This commit introduces the use of atomic_compare_exchange at beginning
of both dlt_init functions. This function checks in an atomic way, if
'dlt_user_initialised' is 'false' (first run through dlt_init) and directly
sets it 'true'. If a second thread also entered dlt-init at this point of time,
its call of atomic_compare_exchange will return false and dlt_init will be
immediately left due to that. This is only interesting for startup, because
before each call of dlt_init, there is a check on 'dlt_user_initialised' that
will fail for all later executions.
Signed-off-by: Darian Biastoch <dbiastoch@de.adit-jv.com>
-rw-r--r-- | src/lib/dlt_user.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/src/lib/dlt_user.c b/src/lib/dlt_user.c index bc9acc7..3d1c18c 100644 --- a/src/lib/dlt_user.c +++ b/src/lib/dlt_user.c @@ -55,6 +55,8 @@ #include <stdbool.h> +#include <stdatomic.h> + #if defined DLT_LIB_USE_UNIX_SOCKET_IPC || defined DLT_LIB_USE_VSOCK_IPC # include <sys/socket.h> #endif @@ -439,6 +441,16 @@ static DltReturnValue dlt_initialize_fifo_connection(void) DltReturnValue dlt_init(void) { + /* Compare 'dlt_user_initialised' to false. If equal, 'dlt_user_initialised' will be set to true. + Calls retruns true, if 'dlt_user_initialised' was false. + That way it's no problem, if two threads enter this function, because only the very first one will + pass fully. The other one will immediately return, because when it executes the atomic function + 'dlt_user_initialised' will be for sure already set to true. + */ + bool expected = false; + if (!(atomic_compare_exchange_strong(&dlt_user_initialised, &expected, true))) + return DLT_RETURN_OK; + /* check environment variables */ dlt_check_envvar(); @@ -449,10 +461,6 @@ DltReturnValue dlt_init(void) return DLT_RETURN_LOGGING_DISABLED; } - /* WARNING: multithread unsafe ! */ - /* Another thread will check that dlt_user_initialised != 0, but the lib is not initialised ! */ - dlt_user_initialised = true; - /* Initialize common part of dlt_init()/dlt_init_file() */ if (dlt_init_common() == DLT_RETURN_ERROR) { dlt_user_initialised = false; @@ -539,7 +547,15 @@ DltReturnValue dlt_init_file(const char *name) if (!name) return DLT_RETURN_WRONG_PARAMETER; - dlt_user_initialised = true; + /* Compare 'dlt_user_initialised' to false. If equal, 'dlt_user_initialised' will be set to true. + Calls retruns true, if 'dlt_user_initialised' was false. + That way it's no problem, if two threads enter this function, because only the very first one will + pass fully. The other one will immediately return, because when it executes the atomic function + 'dlt_user_initialised' will be for sure already set to true. + */ + bool expected = false; + if (!(atomic_compare_exchange_strong(&dlt_user_initialised, &expected, true))) + return DLT_RETURN_OK; /* Initialize common part of dlt_init()/dlt_init_file() */ if (dlt_init_common() == DLT_RETURN_ERROR) { |