static unsigned __stdcall worker_thread_entry(void *param) { work_thread_info *thread = param; osd_work_queue *queue = thread->queue; // loop until we exit for ( ;; ) { // block waiting for work or exit DWORD result = WAIT_OBJECT_0; // bail on exit, and only wait if there are no pending items in queue if (!queue->exiting && queue->list == NULL) { begin_timing(thread->waittime); result = WaitForSingleObject(thread->wakeevent, INFINITE); end_timing(thread->waittime); } if (queue->exiting) break; // indicate that we are live interlocked_exchange32(&thread->active, TRUE); interlocked_increment(&queue->livethreads); // process work items for ( ;; ) { osd_ticks_t stopspin; // process as much as we can worker_thread_process(queue, thread); // if we're a high frequency queue, spin for a while before giving up if (queue->flags & WORK_QUEUE_FLAG_HIGH_FREQ) { // spin for a while looking for more work begin_timing(thread->spintime); stopspin = osd_ticks() + SPIN_LOOP_TIME; while (queue->list == NULL && osd_ticks() < stopspin) YieldProcessor(); end_timing(thread->spintime); } // if nothing more, release the processor if (queue->list == NULL) break; add_to_stat(&queue->spinloops, 1); } // decrement the live thread count interlocked_exchange32(&thread->active, FALSE); interlocked_decrement(&queue->livethreads); } return 0; }
IOCPConnection::~IOCPConnection() { delete m_pWaitQueue; delete m_pSendQueue; delete m_pRecvQueue; delete [] m_pRecvOverlapped->pBuf; assert( m_pAllocator != NULL ); { //THREAD_SYNC( m_pAllocator ); } interlocked_decrement( &g_connectionCount ); }
static void worker_thread_process(osd_work_queue *queue, work_thread_info *thread) { int threadid = thread - queue->thread; begin_timing(thread->runtime); // loop until everything is processed while (queue->list != NULL) { osd_work_item *item; INT32 lockslot; // use a critical section to synchronize the removal of items lockslot = scalable_lock_acquire(&queue->lock); { // pull the item from the queue item = (osd_work_item *)queue->list; if (item != NULL) { queue->list = item->next; if (queue->list == NULL) queue->tailptr = (osd_work_item **)&queue->list; } } scalable_lock_release(&queue->lock, lockslot); // process non-NULL items if (item != NULL) { // call the callback and stash the result begin_timing(thread->actruntime); item->result = (*item->callback)(item->param, threadid); end_timing(thread->actruntime); // decrement the item count after we are done interlocked_decrement(&queue->items); interlocked_exchange32(&item->done, TRUE); add_to_stat(&thread->itemsdone, 1); // if it's an auto-release item, release it if (item->flags & WORK_ITEM_FLAG_AUTO_RELEASE) osd_work_item_release(item); // set the result and signal the event else if (item->event != NULL) { SetEvent(item->event); add_to_stat(&item->queue->setevents, 1); } // if we removed an item and there's still work to do, bump the stats if (queue->list != NULL) add_to_stat(&queue->extraitems, 1); } } // we don't need to set the doneevent for multi queues because they spin if (queue->waiting) { SetEvent(queue->doneevent); add_to_stat(&queue->setevents, 1); } end_timing(thread->runtime); }