- pthread_mutex_lock(&static_calloc_mutex);
- if (nmemb * size > sizeof(static_calloc_buf) - static_calloc_buf_offset) {
- pthread_mutex_unlock(&static_calloc_mutex);
- return NULL;
- }
- prev_offset = static_calloc_buf_offset;
- static_calloc_buf_offset += nmemb * size;
- pthread_mutex_unlock(&static_calloc_mutex);
+ /*
+ * Protect static_calloc_buf_offset from concurrent updates
+ * using a cmpxchg loop rather than a mutex to remove a
+ * dependency on pthread. This will minimize the risk of bad
+ * interaction between mutex and malloc instrumentation.
+ */
+ res_offset = CMM_LOAD_SHARED(static_calloc_buf_offset);
+ do {
+ prev_offset = res_offset;
+ if (nmemb * size > sizeof(static_calloc_buf) - prev_offset) {
+ return NULL;
+ }
+ new_offset = prev_offset + nmemb * size;
+ } while ((res_offset = uatomic_cmpxchg(&static_calloc_buf_offset,
+ prev_offset, new_offset)) != prev_offset);