RmBuffer *rm_buffer_get(RmBufferPool *pool) { RmBuffer *buffer = NULL; g_mutex_lock(&pool->lock); { while(!buffer) { buffer = rm_util_slist_pop(&pool->stack, NULL); if (!buffer && pool->avail_buffers > 0) { buffer = rm_buffer_new(pool); } if (!buffer) { if(!pool->mem_warned) { rm_log_warning_line( "read buffer limit reached - waiting for " "processing to catch up"); pool->mem_warned = true; } g_cond_wait(&pool->change, &pool->lock); } } pool->avail_buffers--; } g_mutex_unlock(&pool->lock); rm_assert_gentle(buffer); return buffer; }
/** @brief RmMDSDevice worker thread **/ static void rm_mds_factory(RmMDSDevice *device, RmMDS *mds) { /* rm_mds_factory processes tasks from device->task_list. * After completing one pass of the device, returns self to the * mds->pool threadpool. */ gint processed = 0; g_mutex_lock(&device->lock); { /* check for empty queues - if so then wait a little while before giving up */ if(!device->sorted_tasks && !device->unsorted_tasks && device->ref_count > 0) { /* timed wait for signal from rm_mds_push_task_impl() */ gint64 end_time = g_get_monotonic_time() + MDS_EMPTYQUEUE_SLEEP_US; g_cond_wait_until(&device->cond, &device->lock, end_time); } /* sort and merge task lists */ if(device->unsorted_tasks) { if(mds->prioritiser) { device->sorted_tasks = g_slist_concat( g_slist_sort_with_data(device->unsorted_tasks, (GCompareDataFunc)rm_mds_compare, (RmMDSSortFunc)mds->prioritiser), device->sorted_tasks); } else { device->sorted_tasks = g_slist_concat(device->unsorted_tasks, device->sorted_tasks); } device->unsorted_tasks = NULL; } } g_mutex_unlock(&device->lock); /* process tasks from device->sorted_tasks */ RmMDSTask *task = NULL; while(processed < mds->pass_quota && (task = rm_util_slist_pop(&device->sorted_tasks, &device->lock))) { if(mds->func(task->task_data, mds->user_data)) { /* task succeeded; update counters */ ++processed; } rm_mds_task_free(task); } if(rm_mds_device_ref(device, 0) > 0) { /* return self to pool for further processing */ if(processed == 0) { /* stalled queue; chill for a bit */ g_usleep(1000); } rm_util_thread_pool_push(mds->pool, device); } else if(g_atomic_int_dec_and_test(&device->threads)) { /* free self and signal to rm_mds_free() */ g_mutex_lock(&mds->lock); { rm_log_debug_line("Freeing device %" LLU " (pointer %p)", (RmOff)device->disk, device); g_hash_table_remove(mds->disks, GINT_TO_POINTER(device->disk)); rm_mds_device_free(device); g_cond_signal(&mds->cond); } g_mutex_unlock(&mds->lock); } }