summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarian Biastoch <dbiastoch@de.adit-jv.com>2021-08-13 14:10:37 +0200
committerSaya Sugiura <ssugiura@jp.adit-jv.com>2021-10-05 11:07:37 +0900
commit05459e5669c565acd05531e322349c3cbc045e8f (patch)
treef57b9825c4e95b73ba670ec3928cbb1e3708d701
parent2252cf1a6dc69b55dce925c30d8bda046560510b (diff)
downloadDLT-daemon-05459e5669c565acd05531e322349c3cbc045e8f.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.c26
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) {