/****************************************************************************** * Function: jpeg_queue_abort * Description: Aborts the queue object * Input parameters: * p_queue - The pointer to queue object to be aborted. * Return values: * JPEGERR_SUCCESS * JPEGERR_ENULLPTR * Notes: none *****************************************************************************/ int jpeg_queue_abort(jpeg_queue_t *p_queue) { jpeg_q_t *p_q; if(!p_queue) { JPEG_DBG_ERROR("jpeg_queue_abort: failed with empty queue pointer\n"); return JPEGERR_ENULLPTR; } p_q = (jpeg_q_t *)(*p_queue); if (!p_q) { JPEG_DBG_ERROR("jpeg_queue_abort: failed with empty queue\n"); return JPEGERR_ENULLPTR; } // Abort os_mutex_lock(&(p_q->mutex)); if (p_q->state == QUEUE_STATE_TIMEWAIT) { // Change queue state p_q->state = QUEUE_STATE_ABORT; // Signal the dequeue function os_cond_signal(&(p_q->get_cond)); while (QUEUE_STATE_ABORT == p_q->state) { // Wait unitil abort can be unblocked os_cond_wait(&(p_q->abort_cond), &(p_q->mutex)); } } p_q->state = QUEUE_STATE_ABORTED; os_mutex_unlock(&(p_q->mutex)); return JPEGERR_SUCCESS; }
/****************************************************************************** * Function: jpege_queue_enqueue * Description: Enqueue a sequence of entry. It accepts the double pointer to the * entry to be enqueued and the number of entries in the * array, appends the entries sequentially to the tail of queue. * The number of entries to be enqueued is checked against * the valid slots of the queue, and * return fail if it is larger than the valid size. * Input parameters: * queue - The queue object. * pp_enqueue_buf - The double pointer to enqueued entry(s) . * enqueue_entry_cnt - The number of enqueued entry(s). * Return values: * JPEGERR_SUCCESS * JPEGERR_EFAILED * JPEGERR_ENULLPTR * (See jpegerr.h for description of error values.) * Notes: none *****************************************************************************/ int jpeg_queue_enqueue( jpeg_queue_t queue, void **pp_enqueue_entry, uint32_t enqueue_entry_cnt) { uint32_t i, q_index; jpeg_q_t *p_q; // Input parameter validation if ((!pp_enqueue_entry) || (!enqueue_entry_cnt)) { JPEG_DBG_ERROR("jpeg_queue_enqueue: failed with input parameter check\n"); return JPEGERR_EBADPARM; } p_q = (jpeg_q_t *)queue; if (!p_q) { JPEG_DBG_ERROR("jpeg_queue_enqueue: failed with empty queue pointer\n"); return JPEGERR_ENULLPTR; } // Enqueue entry(s) to the queue os_mutex_lock(&(p_q->mutex)); // Reject if the enqueued entry(s) are greater than valid slots left: // queue_cnt is current number of entries in queue, // it plus the number of entry to be enqueued can not exceed the // number of entries allowed inside queue. if ((p_q->queue_cnt + enqueue_entry_cnt) > MAX_QUEUE_NUM) { JPEG_DBG_ERROR("jpeg_queue_enqueue: enqueuing more entries than valid queue slots\n"); os_mutex_unlock(&(p_q->mutex)); return JPEGERR_EFAILED; } // Enqueue the entry for (i = 0; i < enqueue_entry_cnt; i++) { // Appends the entries sequentially to the tail of queue. q_index = QUEUE_MOD(p_q->queue_tail + i); p_q->queue_pool[q_index].p_data = *(pp_enqueue_entry + i); } // Update the tail of queue and entries number p_q->queue_tail = QUEUE_MOD(p_q->queue_tail + enqueue_entry_cnt); p_q->queue_cnt += enqueue_entry_cnt; // Signal that enqueuing entries is done os_cond_signal(&(p_q->get_cond)); os_mutex_unlock(&(p_q->mutex)); return JPEGERR_SUCCESS; }
// returns 0 on success or GenesisErrorNoMem int __attribute__((warn_unused_result)) push(T item) { OsMutexLocker locker(_mutex); int err = ensure_capacity(_length + 1); if (err) return err; _length += 1; _items[_end] = item; _end = (_end + 1) % _capacity; os_cond_signal(_cond, _mutex); return 0; }
static void run_write(void *userdata) { OrderedMapFile *omf = (OrderedMapFile *)userdata; for (;;) { OrderedMapFileBatch *batch = nullptr; omf->queue.shift(&batch); if (!batch || !omf->running) break; // compute transaction size int transaction_size = get_transaction_size(batch); omf->write_buffer.resize(transaction_size); uint8_t *transaction_ptr = (uint8_t*)omf->write_buffer.raw(); write_uint32be(&transaction_ptr[4], transaction_size); write_uint32be(&transaction_ptr[8], batch->puts.length()); write_uint32be(&transaction_ptr[12], batch->dels.length()); int offset = TRANSACTION_METADATA_SIZE; for (int i = 0; i < batch->puts.length(); i += 1) { OrderedMapFilePut *put = &batch->puts.at(i); write_uint32be(&transaction_ptr[offset], put->key->size); offset += 4; write_uint32be(&transaction_ptr[offset], put->value->size); offset += 4; memcpy(&transaction_ptr[offset], put->key->data, put->key->size); offset += put->key->size; memcpy(&transaction_ptr[offset], put->value->data, put->value->size); offset += put->value->size; } for (int i = 0; i < batch->dels.length(); i += 1) { OrderedMapFileDel *del = &batch->dels.at(i); write_uint32be(&transaction_ptr[offset], del->key->size); offset += 4; memcpy(&transaction_ptr[offset], del->key->data, del->key->size); offset += del->key->size; } assert(offset == transaction_size); ordered_map_file_batch_destroy(batch); // compute crc32 write_uint32be(&transaction_ptr[0], crc32(0, &transaction_ptr[4], transaction_size - 4)); // append to file size_t amt_written = fwrite(transaction_ptr, 1, transaction_size, omf->file); if (amt_written != (size_t)transaction_size) panic("write to disk failed"); os_mutex_lock(omf->mutex); os_cond_signal(omf->cond, omf->mutex); os_mutex_unlock(omf->mutex); } }
static void * test_worker(void *arg) { /* check before pool is closed, then let main continue */ UT_ASSERTne(obj_direct(thread_oid), NULL); os_mutex_lock(&lock1); cond1 = 1; os_cond_signal(&sync_cond1); os_mutex_unlock(&lock1); /* wait for main thread to free & close, then check */ os_mutex_lock(&lock2); while (!cond2) os_cond_wait(&sync_cond2, &lock2); os_mutex_unlock(&lock2); UT_ASSERTeq(obj_direct(thread_oid), NULL); return NULL; }
static void render_node_run(struct GenesisNode *node) { const struct GenesisNodeDescriptor *node_descriptor = genesis_node_descriptor(node); struct AudioGraph *ag = (struct AudioGraph *)genesis_node_descriptor_userdata(node_descriptor); struct GenesisPort *audio_in_port = genesis_node_port(node, 0); int input_frame_count = genesis_audio_in_port_fill_count(audio_in_port); float *in_buf = genesis_audio_in_port_read_ptr(audio_in_port); GenesisAudioFileStream *afs = ag->render_stream; int frames_left = ag->render_frame_count - ag->render_frame_index; int write_count = min(input_frame_count, frames_left); if (write_count > 0) { int err; if ((err = genesis_audio_file_stream_write(afs, in_buf, write_count))) { panic("TODO handle this error"); } long new_index = ag->render_frame_index.load() + write_count; assert(new_index <= ag->render_frame_count); bool done = new_index == ag->render_frame_count; if (done) { if ((err = genesis_audio_file_stream_close(afs))) { panic("TODO handle this error"); } } ag->render_frame_index.store(new_index); ag->play_head_changed_flag.clear(); if (done) { os_cond_signal(ag->render_cond, nullptr); } genesis_audio_in_port_advance_read_ptr(audio_in_port, write_count); } }
int main(int argc, char *argv[]) { START(argc, argv, "obj_direct"); if (argc != 3) UT_FATAL("usage: %s [directory] [# of pools]", argv[0]); unsigned npools = ATOU(argv[2]); const char *dir = argv[1]; int r; os_mutex_init(&lock1); os_mutex_init(&lock2); os_cond_init(&sync_cond1); os_cond_init(&sync_cond2); cond1 = cond2 = 0; PMEMobjpool **pops = MALLOC(npools * sizeof(PMEMobjpool *)); UT_ASSERTne(pops, NULL); size_t length = strlen(dir) + MAX_PATH_LEN; char *path = MALLOC(length); for (unsigned i = 0; i < npools; ++i) { int ret = snprintf(path, length, "%s"OS_DIR_SEP_STR"testfile%d", dir, i); if (ret < 0 || ret >= length) UT_FATAL("!snprintf"); pops[i] = pmemobj_create(path, LAYOUT_NAME, PMEMOBJ_MIN_POOL, S_IWUSR | S_IRUSR); if (pops[i] == NULL) UT_FATAL("!pmemobj_create"); } PMEMoid *oids = MALLOC(npools * sizeof(PMEMoid)); UT_ASSERTne(oids, NULL); PMEMoid *tmpoids = MALLOC(npools * sizeof(PMEMoid)); UT_ASSERTne(tmpoids, NULL); oids[0] = OID_NULL; UT_ASSERTeq(obj_direct(oids[0]), NULL); for (unsigned i = 0; i < npools; ++i) { oids[i] = (PMEMoid) {pops[i]->uuid_lo, 0}; UT_ASSERTeq(obj_direct(oids[i]), NULL); uint64_t off = pops[i]->heap_offset; oids[i] = (PMEMoid) {pops[i]->uuid_lo, off}; UT_ASSERTeq((char *)obj_direct(oids[i]) - off, (char *)pops[i]); r = pmemobj_alloc(pops[i], &tmpoids[i], 100, 1, NULL, NULL); UT_ASSERTeq(r, 0); } r = pmemobj_alloc(pops[0], &thread_oid, 100, 2, NULL, NULL); UT_ASSERTeq(r, 0); UT_ASSERTne(obj_direct(thread_oid), NULL); os_thread_t t; PTHREAD_CREATE(&t, NULL, test_worker, NULL); /* wait for the worker thread to perform the first check */ os_mutex_lock(&lock1); while (!cond1) os_cond_wait(&sync_cond1, &lock1); os_mutex_unlock(&lock1); for (unsigned i = 0; i < npools; ++i) { UT_ASSERTne(obj_direct(tmpoids[i]), NULL); pmemobj_free(&tmpoids[i]); UT_ASSERTeq(obj_direct(tmpoids[i]), NULL); pmemobj_close(pops[i]); UT_ASSERTeq(obj_direct(oids[i]), NULL); } /* signal the worker that we're free and closed */ os_mutex_lock(&lock2); cond2 = 1; os_cond_signal(&sync_cond2); os_mutex_unlock(&lock2); PTHREAD_JOIN(&t, NULL); os_cond_destroy(&sync_cond1); os_cond_destroy(&sync_cond2); os_mutex_destroy(&lock1); os_mutex_destroy(&lock2); FREE(pops); FREE(tmpoids); FREE(oids); DONE(NULL); }
void wakeup_all() { OsMutexLocker locker(_mutex); _shutdown = true; os_cond_signal(_cond, _mutex); }
/****************************************************************************** * Function: jpeg_queue_dequeue * Description: Dequeue a entry from the queue. It returns the double pointer * to the entry to be denqueued from the head of queue, * and accepts the number of time in mini-seconds that it conditional . * waits if the queue if empty. * Input parameters: * queue - The queue object. * pp_dequeue_buffer - The double pointer to dequeued entry. * ms - The time out in minisecond * Return values: * JPEGERR_SUCCESS * JPEGERR_EFAILED * JPEGERR_ENULLPTR * JPEGERR_ETIMEDOUT * Notes: none *****************************************************************************/ int jpeg_queue_dequeue( jpeg_queue_t queue, void **pp_dequeue_entry, uint32_t time_out_ms) { uint32_t q_index; jpeg_q_t *p_q; int rc; // Input parameter validation if (!pp_dequeue_entry) { JPEG_DBG_ERROR("jpeg_queue_dequeue: failed with input parameter check\n"); return JPEGERR_EBADPARM; } p_q = (jpeg_q_t *)queue; if (!p_q) { JPEG_DBG_ERROR("jpeg_queue_dequeue: failed with empty queue pointer\n"); return JPEGERR_ENULLPTR; } os_mutex_lock(&(p_q->mutex)); if (p_q->state == QUEUE_STATE_ABORTED) { os_mutex_unlock(&(p_q->mutex)); JPEG_DBG_ERROR("jpeg_queue_dequeue: Aborted \n"); return JPEGERR_EFAILED; } // Check if queue is empty: // queue_cnt is current number of entries in queue. while (p_q->queue_cnt <= 0 && QUEUE_STATE_ABORT != p_q->state) { p_q->state = QUEUE_STATE_TIMEWAIT; // fails after conditional waiting time_out_ms in milli-seconds rc = os_cond_timedwait(&(p_q->get_cond), &(p_q->mutex), time_out_ms); if (JPEG_FAILED(rc)) { JPEG_DBG_ERROR("jpeg_queue_dequeue: failed with empty queue\n"); if (QUEUE_STATE_ABORT == p_q->state) { p_q->state = QUEUE_STATE_ABORTED; os_cond_signal(&(p_q->abort_cond)); } p_q->state = QUEUE_STATE_IDLE; os_mutex_unlock(&(p_q->mutex)); return rc; } } if (QUEUE_STATE_ABORT == p_q->state) { p_q->state = QUEUE_STATE_IDLE; // signal abort cond os_cond_signal(&(p_q->abort_cond)); os_mutex_unlock(&(p_q->mutex)); JPEG_DBG_ERROR("jpeg_queue_dequeue: failed with abort\n"); return JPEGERR_EFAILED; } // Dequeue an entry from queue q_index = p_q->queue_head; // Dequeue the entry from the head of queue *pp_dequeue_entry = p_q->queue_pool[q_index].p_data; // Update the head of queue and entries number p_q->queue_head = QUEUE_MOD(p_q->queue_head + 1); p_q->queue_cnt -= 1; p_q->state = QUEUE_STATE_IDLE; os_mutex_unlock(&(p_q->mutex)); return JPEGERR_SUCCESS; }