Me@0: /* Me@0: * Copyright 2009 OpenSourceCodeStewardshipFoundation.org Me@0: * Licensed under GNU General Public License version 2 Me@0: * Me@0: * NOTE: this version of SRSW correct as of April 25, 2010 Me@0: * Me@0: * Author: seanhalle@yahoo.com Me@0: */ Me@0: Me@0: Me@0: #include Me@0: #include Me@0: #include Me@0: #include Me@0: Me@0: #include "PrivateQueue.h" Me@0: Me@0: Me@0: Me@0: //=========================================================================== Me@0: Me@0: /*This kind of queue is private to a single core at a time -- has no Me@0: * synchronizations Me@0: */ Me@0: Me@0: PrivQueueStruc* makePrivQ() Me@0: { Me@0: PrivQueueStruc* retQ; Me@0: retQ = (PrivQueueStruc *) malloc( sizeof( PrivQueueStruc ) ); Me@0: Me@0: retQ->startOfData = malloc( 1024 * sizeof(void *) ); Me@0: Me@0: retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty Me@0: retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be Me@0: retQ->endOfData = &(retQ->startOfData[1023]); Me@0: Me@0: return retQ; Me@0: } Me@0: Me@0: PrivQueueStruc* make_larger_PrivQ( PrivQueueStruc *Q ) Me@0: { int oldSize, newSize; Me@0: void **oldStartOfData; Me@0: Me@0: oldSize = Q->endOfData - Q->startOfData; Me@0: newSize = 2 * oldSize; Me@0: Q->startOfData = malloc( newSize * sizeof(void *) ); Me@0: memcpy(Q->startOfData, oldStartOfData, oldSize * sizeof(void *)); Me@0: free(oldStartOfData); Me@0: Me@0: Q->extractPos = &(Q->startOfData[0]); //side by side == empty Me@0: Q->insertPos = &(Q->startOfData[1]); // so start pos's have to be Me@0: Q->endOfData = &(Q->startOfData[newSize - 1]); Me@0: Me@0: return Q; Me@0: } Me@0: Me@0: Me@0: /*Returns NULL when queue is empty Me@0: */ Me@0: void* readPrivQ( PrivQueueStruc* Q ) Me@0: { void *out = 0; Me@0: int startOfData = Q->startOfData; Me@0: int endOfData = Q->endOfData; Me@0: Me@0: volatile int insertPos = Q->insertPos; Me@0: volatile int extractPos = Q->extractPos; Me@0: Me@0: //if not empty -- extract just below insert when empty Me@0: if( insertPos - extractPos != 1 && Me@0: !(extractPos == endOfData && insertPos == startOfData)) Me@0: { //move before read Me@0: if( extractPos == endOfData ) //write new pos exactly once, correctly Me@0: { Q->extractPos = startOfData; //can't overrun then fix it 'cause Me@0: } // other thread might read bad pos Me@0: else Me@0: { Q->extractPos++; Me@0: } Me@0: out = *(Q->extractPos); Me@0: return out; Me@0: } Me@0: //Q is empty Me@0: return NULL; Me@0: } Me@0: Me@0: /*Returns false when the queue was full. Me@0: * have option of calling make_larger_PrivQ to make more room, then try again Me@0: */ Me@0: bool8 writePrivQ( void * in, PrivQueueStruc* Q ) Me@0: { Me@0: int startOfData = Q->startOfData; Me@0: int endOfData = Q->endOfData; Me@0: Me@0: volatile int insertPos = Q->insertPos; Me@0: volatile int extractPos = Q->extractPos; Me@0: Me@0: if( extractPos - insertPos != 1 && Me@0: !(insertPos == endOfData && extractPos == startOfData)) Me@0: { *(insertPos) = in; //insert before move Me@0: if( insertPos == endOfData ) //write new pos exactly once, correctly Me@0: { Q->insertPos = startOfData; Me@0: } Me@0: else Me@0: { Q->insertPos++; Me@0: } Me@0: return TRUE; Me@0: } Me@0: //Q is full Me@0: return FALSE; Me@0: } Me@0: