Fix: tls-compat.h exposes compiler-dependent public configuration
Exposing the storage class chosen by ax_tls.m4 in a public header is
a bad idea, because if a recent gcc is used when configuring
liburcu, thus detecting C11, it will choose _Thread_local. Then, if an
external project uses urcu/tls-compat.h with an older gcc (e.g. 4.8),
it will fail to build, because that storage class is unknown, and
__thread should be used instead.
Therefore, use a preprocessor conditional on __cplusplus to detect C++11
(and use thread_local). Else, the STDC version is used to select
_Thread_local. Else check if _MSC_VER is defined to select
__declspec(thread), or else rely on __thread as fallback.
On architectures where "char" is signed, it should be cast to unsigned
char before being passed as parameter to isdigit or isspace. Based on
their man page:
These functions check whether c, which must have the value of an
unsigned char or EOF, falls into a certain character class according to
the specified locale.
Passing a signed char as parameter is invalid if the values fall into
the negative range of the signed char.
In urcu-signal flavor, call_rcu_thread calls synchronize_rcu which
will send SIGRCU signal to all registed threads, and then loops to
wait need_mb to be cleared. However, the registed workqueue_thread
does not process the SIGRCU signal, and never clear the need_mb.
Based on above, call_rcu_thread and workqueue_thread will wait
forever for completion of the grace period: call_rcu_thread which holds
the rcu_registry_lock, waits for workqueue_thread to do cmm_smp_mb.
While workqueue thread never does cmm_smp_mb because of signal blocking,
and it will eventually wait to get rcu_registry_lock in do_resize_cb.
The phenomenon is as follows, which is easy to be triggered:
(gdb) t 2
[Switching to thread 2 (Thread 0xffff83c3b080 (LWP 27116))]
0 0x0000ffff845296c4 in poll () from /lib64/libc.so.6
(gdb) bt
0 0x0000ffff845296c4 in poll () from /lib64/libc.so.6
1 0x0000ffff8461b93c in force_mb_all_readers () at urcu.c:241
2 0x0000ffff8461c748 in smp_mb_master () at urcu.c:249
3 urcu_signal_synchronize_rcu () at urcu.c:445
4 0x0000ffff8461d004 in call_rcu_thread at urcu-call-rcu-impl.h:364
5 0x0000ffff845eb8bc in start_thread () from /lib64/libpthread.so.0
6 0x0000ffff845335cc in thread_start () from /lib64/libc.so.6
(gdb) t 3
[Switching to thread 3 (Thread 0xffff8443c080 (LWP 27191))]
0 0x0000ffff845f51c4 in __lll_lock_wait () from /lib64/libpthread.so.0
(gdb) bt
0 0x0000ffff845f51c4 in __lll_lock_wait () from /lib64/libpthread.so.0
1 0x0000ffff845ee048 in pthread_mutex_lock () from /lib64/libpthread.so.0
2 0x0000ffff8461b814 in mutex_lock ( <rcu_registry_lock>) at urcu.c:157
3 0x0000ffff8461b9e4 in urcu_signal_unregister_thread () at urcu.c:564
4 0x0000ffff8463e62c in do_resize_cb (work=0x11e2e790) at rculfhash.c:2042
5 0x0000ffff8463c940 in workqueue_thread (arg=0x11e1d260) at workqueue.c:228
6 0x0000ffff845eb8bc in start_thread () from /lib64/libpthread.so.0
7 0x0000ffff845335cc in thread_start () from /lib64/libc.so.6
So we should not block SIGRCU in workqueue thread to avoid blocking
forever in the grace period awaiting on the worker thread when using
urcu-signal flavor.
Cleanup: update code layout to fix old gcc warning
Some CI jobs show:
urcu-pointer.o
13:46:22 In file included from urcu.c:49:0:
13:46:22 urcu-wait.h:70:9: warning: missing initializer for field 'lock' of 'struct cds_wfs_stack' [-Wmissing-field-initializers]
13:46:22 struct urcu_wait_queue name = URCU_WAIT_QUEUE_HEAD_INIT(name)
13:46:22 ^
13:46:22 urcu.c:150:8: note: in expansion of macro 'DEFINE_URCU_WAIT_QUEUE'
13:46:22 static DEFINE_URCU_WAIT_QUEUE(gp_waiters);
13:46:22 ^
13:46:22 In file included from urcu-wait.h:27:0,
13:46:22 from urcu.c:49:
13:46:22 ../include/urcu/wfstack.h:92:18: note: 'lock' declared here
13:46:22 pthread_mutex_t lock;
13:46:22