void SemaphoreDown( struct SEMAPHORE * lock, struct LOCKING_CONTEXT * context ) {//LOCK LockingStart(); if ( lock->Count == 0 ) {//block the thread union LINK * link = LockingBlock( NULL, context ); LinkedListEnqueue( &link->LinkedListLink, &lock->WaitingThreads); } else { lock->Count--; LockingAcquire( context ); } LockingEnd(); }
void WorkerThreadMain( void * arg ) { struct WORKER_QUEUE * queue; struct THREAD * thread; struct SEMAPHORE * lock; struct LINKED_LIST * list; struct WORKER_ITEM * item; enum WORKER_RETURN result; //Get the Work Thread Context queue = arg; thread = & queue->Thread; lock = & queue->Lock; list = & queue->List; //Loop consuming work items. while(TRUE) { //Fetch a handler item = WorkerGetItem( queue ); ASSERT(! item->Finished ); //there is a item, so execute it. result = item->Foo(item); //Determine what to do with work item. switch( result ) { case WORKER_FINISHED: //the item is done, mark so caller knows. item->Finished = TRUE; break; case WORKER_BLOCKED: //the work item is blocked on a lock, the lock will //re-queue the work item when the lock has been acquired. break; case WORKER_PENDED: //the item needs more processing. //add back into queue. CritInterruptDisable(); LinkedListEnqueue( &item->Link.LinkedListLink, list ); CritInterruptEnable(); break; }// end switch }// end while(TRUE). }
void Add( int value ) { struct ELEMENT * queueNode = malloc( sizeof( struct ELEMENT ) ); struct ELEMENT * stackNode = malloc( sizeof( struct ELEMENT ) ); struct ELEMENT * atomicNode = malloc( sizeof( struct ELEMENT ) ); struct ELEMENT * heapNode = malloc( sizeof( struct ELEMENT ) ); queueNode->Data = value; stackNode->Data = value; atomicNode->Data = value; heapNode->Data = value; LinkedListPush( &stackNode->Link.LinkedListLink, &stackList ); LinkedListEnqueue( &queueNode->Link.LinkedListLink, &queueList ); AtomicListPush( &atomicNode->Link.AtomicListLink, &atomicList ); HeapAdd(value, &heapNode->Link.WeightedLink, &heap ); }
/* * Adds a work item 'item' to the work queue 'queue'. * It is not safe to add work items to the queue which have already been * registered. Calling WorkerItemIsFinished() can solve this engima. */ void WorkerAddItem( struct WORKER_QUEUE * queue, struct WORKER_ITEM * item ) { //Make sure we are at thread level. ASSERT( !SoftInterruptIsAtomic() ); SemaphoreUp( & queue->Lock ); //We mark finished inside interrupt section so that WorkerItemIsFinished //returns accurate results. item->Queue = queue; CritInterruptDisable(); //Finished needs to be updated with critical sections disabled. item->Finished = FALSE; //Adding to the queue needs to be done with Critinterrupts Disabled. LinkedListEnqueue( &item->Link.LinkedListLink, & queue->List ); CritInterruptEnable(); }