int pa_shmasyncq_push(pa_shmasyncq*l, void *p, int wait) { int idx; pa_atomic_ptr_t *cells; pa_assert(l); pa_assert(p); cells = PA_SHMASYNCQ_CELLS(l); _Y; idx = reduce(l, l->write_idx); if (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) { if (!wait) return -1; /* pa_log("sleeping on push"); */ do { pa_fdsem_wait(l->read_fdsem); } while (!pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)); } _Y; l->write_idx++; pa_fdsem_post(l->write_fdsem); return 0; }
void* pa_flist_pop(pa_flist*l) { unsigned idx, n; pa_atomic_ptr_t *cells; #ifdef PROFILE unsigned len; #endif pa_assert(l); cells = PA_FLIST_CELLS(l); n = (unsigned) pa_atomic_load(&l->length) + N_EXTRA_SCAN; #ifdef PROFILE len = n; #endif _Y; idx = reduce(l, (unsigned) pa_atomic_load(&l->read_idx)); for (; n > 0 ; n--) { void *p; _Y; p = pa_atomic_ptr_load(&cells[idx]); if (p) { _Y; if (!pa_atomic_ptr_cmpxchg(&cells[idx], p, NULL)) continue; _Y; pa_atomic_inc(&l->read_idx); _Y; pa_atomic_dec(&l->length); return p; } _Y; idx = reduce(l, idx+1); } #ifdef PROFILE if (len > N_EXTRA_SCAN) pa_log_warn("Didn't find used cell after %u iterations.", len); #endif return NULL; }
int pa_flist_push(pa_flist*l, void *p) { unsigned idx, n; pa_atomic_ptr_t*cells; #ifdef PROFILE unsigned len; #endif pa_assert(l); pa_assert(p); cells = PA_FLIST_CELLS(l); n = l->size + N_EXTRA_SCAN - (unsigned) pa_atomic_load(&l->length); #ifdef PROFILE len = n; #endif _Y; idx = reduce(l, (unsigned) pa_atomic_load(&l->write_idx)); for (; n > 0 ; n--) { _Y; if (pa_atomic_ptr_cmpxchg(&cells[idx], NULL, p)) { _Y; pa_atomic_inc(&l->write_idx); _Y; pa_atomic_inc(&l->length); return 0; } _Y; idx = reduce(l, idx + 1); } #ifdef PROFILE if (len > N_EXTRA_SCAN) pa_log_warn("Didn't find free cell after %u iterations.", len); #endif return -1; }
/* This is a copy of the function in mutex-posix.c */ pa_mutex* pa_static_mutex_get(pa_static_mutex *s, bool recursive, bool inherit_priority) { pa_mutex *m; pa_assert(s); /* First, check if already initialized and short cut */ if ((m = pa_atomic_ptr_load(&s->ptr))) return m; /* OK, not initialized, so let's allocate, and fill in */ m = pa_mutex_new(recursive, inherit_priority); if ((pa_atomic_ptr_cmpxchg(&s->ptr, NULL, m))) return m; pa_mutex_free(m); /* Him, filling in failed, so someone else must have filled in * already */ pa_assert_se(m = pa_atomic_ptr_load(&s->ptr)); return m; }
void* pa_shmasyncq_pop(pa_shmasyncq*l, int wait) { int idx; void *ret; pa_atomic_ptr_t *cells; pa_assert(l); cells = PA_SHMASYNCQ_CELLS(l); _Y; idx = reduce(l, l->read_idx); if (!(ret = pa_atomic_ptr_load(&cells[idx]))) { if (!wait) return NULL; /* pa_log("sleeping on pop"); */ do { pa_fdsem_wait(l->write_fdsem); } while (!(ret = pa_atomic_ptr_load(&cells[idx]))); } pa_assert(ret); /* Guaranteed to succeed if we only have a single reader */ pa_assert_se(pa_atomic_ptr_cmpxchg(&cells[idx], ret, NULL)); _Y; l->read_idx++; pa_fdsem_post(l->read_fdsem); return ret; }