Type: feature
This is needed when creating pthreads in client applications,
they need a way to set __os_thread_index per thread
that does not conflict with the binary API thread index.
If __os_thread_index is left to 0 in two client pthreads and
they call vl_msg_api_alloc and vec_resize at the same time
it can fail due to them sharing (and push/poping) the same
clib_per_cpu_mheaps slot.
Change-Id: I85d4248a39b641a4d3ad5a1c1bd6e0db5875fab6
Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
svm_queue_t *q;
memory_client_main_t *mm = &memory_client_main;
api_main_t *am = &api_main;
svm_queue_t *q;
memory_client_main_t *mm = &memory_client_main;
api_main_t *am = &api_main;
if (setjmp (mm->rx_thread_jmpbuf) == 0)
{
mm->rx_thread_jmpbuf_valid = 1;
if (setjmp (mm->rx_thread_jmpbuf) == 0)
{
mm->rx_thread_jmpbuf_valid = 1;
- /*
- * Find an unused slot in the per-cpu-mheaps array,
- * and grab it for this thread. We need to be able to
- * push/pop the thread heap without affecting other thread(s).
- */
- if (__os_thread_index == 0)
- {
- for (i = 0; i < ARRAY_LEN (clib_per_cpu_mheaps); i++)
- {
- if (clib_per_cpu_mheaps[i] == 0)
- {
- /* Copy the main thread mheap pointer */
- clib_per_cpu_mheaps[i] = clib_per_cpu_mheaps[0];
- __os_thread_index = i;
- break;
- }
- }
- ASSERT (__os_thread_index > 0);
- }
+ clib_mem_set_thread_index ();
while (1)
vl_msg_api_queue_handler (q);
}
while (1)
vl_msg_api_queue_handler (q);
}
/* Per CPU heaps. */
extern void *clib_per_cpu_mheaps[CLIB_MAX_MHEAPS];
/* Per CPU heaps. */
extern void *clib_per_cpu_mheaps[CLIB_MAX_MHEAPS];
+always_inline void
+clib_mem_set_thread_index (void)
+{
+ /*
+ * Find an unused slot in the per-cpu-mheaps array,
+ * and grab it for this thread. We need to be able to
+ * push/pop the thread heap without affecting other thread(s).
+ */
+ int i;
+ if (__os_thread_index != 0)
+ return;
+ for (i = 0; i < ARRAY_LEN (clib_per_cpu_mheaps); i++)
+ if (clib_atomic_bool_cmp_and_swap (&clib_per_cpu_mheaps[i],
+ 0, clib_per_cpu_mheaps[0]))
+ {
+ os_set_thread_index (i);
+ break;
+ }
+ ASSERT (__os_thread_index > 0);
+}
+
always_inline void *
clib_mem_get_per_cpu_heap (void)
{
always_inline void *
clib_mem_get_per_cpu_heap (void)
{
return __os_thread_index;
}
return __os_thread_index;
}
+static_always_inline void
+os_set_thread_index (uword thread_index)
+{
+ __os_thread_index = thread_index;
+}
+
static_always_inline uword
os_get_cpu_number (void) __attribute__ ((deprecated));
static_always_inline uword
os_get_cpu_number (void) __attribute__ ((deprecated));