int rb_write_to_buffer(ring_buffer *buffer, int n, ...) { if (!buffer) return -1; int write_idx = buffer->write_idx; // No need for sync in writer thread. int available = rb_available_to_write(buffer); va_list args; va_start(args, n); int i; for (i = 0; i < n; ++i) { const char* src = va_arg(args, const char*); int len = va_arg(args, int); available -= len; if (len < 0 || available < 0) return -1; if (write_idx + len <= buffer->size) { memcpy(buffer->buf_ptr + write_idx, src, len); } else { int d = buffer->size - write_idx; memcpy(buffer->buf_ptr + write_idx, src, d); memcpy(buffer->buf_ptr, src + d, len - d); } write_idx = (write_idx + len) % buffer->size; } va_end(args); SYNC_COMPARE_AND_SWAP(&(buffer->write_idx), buffer->write_idx, write_idx); // Includes memory barrier. return 0; }
int rb_read_from_buffer(ring_buffer *buffer, char *dest, int len) { if (len == 0) return 0; if (!buffer || len < 0 || len > rb_available_to_read(buffer)) return -1; // Note that rb_available_to_read also serves as a memory barrier, and so any // writes to buffer->buf_ptr that precede the update of buffer->write_idx are // visible to us now. int read_idx = buffer->read_idx; // No need for sync in reader thread. if (read_idx + len <= buffer->size) { memcpy(dest, buffer->buf_ptr + read_idx, len); } else { int d = buffer->size - read_idx; memcpy(dest, buffer->buf_ptr + read_idx, d); memcpy(dest + d, buffer->buf_ptr, len - d); } SYNC_COMPARE_AND_SWAP(&(buffer->read_idx), buffer->read_idx, (read_idx + len) % buffer->size); // Includes memory barrier. return 0; }
U_CAPI void U_EXPORT2 umtx_init(UMTX *mutex) { ICUMutex *m = NULL; void *originalValue; if (*mutex != NULL) { /* Mutex is already initialized. * Multiple umtx_init()s of a UMTX by other ICU code are explicitly permitted. */ return; } #if defined(POSIX) if (mutex == &globalUMTX) { m = &globalMutex; } #endif m = umtx_ct(m); originalValue = SYNC_COMPARE_AND_SWAP(mutex, NULL, m); if (originalValue != NULL) { umtx_dt(m); return; } m->owner = mutex; /* Hook the new mutex into the list of all ICU mutexes, so that we can find and * delete it for u_cleanup(). */ umtx_lock(NULL); m->next = mutexListHead; mutexListHead = m; umtx_unlock(NULL); return; }