msach@24: /* msach@24: * Copyright 2009 OpenSourceStewardshipFoundation.org msach@24: * Licensed under GNU General Public License version 2 msach@24: * msach@24: * Author: seanhalle@yahoo.com msach@24: */ msach@24: msach@24: msach@24: #include msach@24: #include msach@24: #include msach@24: #include msach@24: msach@24: #include "PrivateQueue.h" msach@24: #include "VMS_Implementations/VMS_impl/vmalloc.h" msach@24: msach@24: msach@24: msach@24: //=========================================================================== msach@24: msach@24: /*This kind of queue is private to a single core at a time -- has no msach@24: * synchronizations msach@24: */ msach@24: msach@24: PrivQueueStruc* makePrivQ() msach@24: { msach@24: PrivQueueStruc *retQ; msach@24: retQ = VMS_int__malloc( sizeof( PrivQueueStruc ) ); msach@24: retQ->startOfData = (void*)VMS_int__malloc( 1024 * sizeof(void *) ); msach@24: memset( retQ->startOfData, 0, 1024 ); msach@24: msach@24: retQ->extractPos = &(retQ->startOfData[0]); //side by side == empty msach@24: retQ->insertPos = &(retQ->startOfData[1]); // so start pos's have to be msach@24: retQ->endOfData = &(retQ->startOfData[1023]); msach@24: msach@24: return retQ; msach@24: } msach@24: msach@24: msach@24: void msach@24: enlargePrivQ( PrivQueueStruc *Q ) msach@24: { size_t oldSize, newSize; msach@24: void **oldStartOfData; msach@24: msach@24: oldSize = Q->endOfData - Q->startOfData + 1; msach@24: newSize = 2 * oldSize; msach@24: oldStartOfData = Q->startOfData; msach@24: Q->startOfData = VMS_int__malloc( newSize * sizeof(void*)); msach@24: //copy second half msach@24: size_t secondHalfSize = Q->endOfData - Q->extractPos + 1; msach@24: memcpy(Q->startOfData,Q->extractPos, secondHalfSize * sizeof(void*)); msach@24: //copy first half msach@24: memcpy(Q->startOfData + secondHalfSize, oldStartOfData, msach@24: (oldSize-secondHalfSize) * sizeof(void*)); msach@24: VMS_int__free(oldStartOfData); msach@24: msach@24: Q->extractPos = Q->startOfData; msach@24: Q->insertPos = Q->startOfData + oldSize - 1; msach@24: Q->endOfData = &(Q->startOfData[newSize - 1]); msach@24: } msach@24: msach@24: msach@24: /*Returns NULL when queue is empty msach@24: */ msach@24: void* readPrivQ( PrivQueueStruc* Q ) msach@24: { void *out = 0; msach@24: void **startOfData = Q->startOfData; msach@24: void **endOfData = Q->endOfData; msach@24: msach@24: void **insertPos = Q->insertPos; msach@24: void **extractPos = Q->extractPos; msach@24: msach@24: //if not empty -- (extract is just below insert when empty) msach@24: if( insertPos - extractPos != 1 && msach@24: !(extractPos == endOfData && insertPos == startOfData)) msach@24: { //move before read msach@24: if( extractPos == endOfData ) //write new pos exactly once, correctly msach@24: { Q->extractPos = startOfData; //can't overrun then fix it 'cause msach@24: } // other thread might read bad pos msach@24: else msach@24: { Q->extractPos++; msach@24: } msach@24: out = *(Q->extractPos); msach@24: return out; msach@24: } msach@24: //Q is empty msach@24: return NULL; msach@24: } msach@24: msach@24: int32 msach@24: numInPrivQ( PrivQueueStruc *Q ) msach@24: { int32 size, numIn; msach@24: msach@24: if( Q->insertPos < Q->extractPos ) msach@24: { //insert has wrapped around so numIn is: msach@24: // insertPos + size - extractPos -- Consider, is empty when msach@24: // extractPos = endOfData and insert = start -- correctly get zero msach@24: size = Q->endOfData - Q->startOfData; msach@24: numIn = Q->insertPos + size - Q->extractPos; msach@24: } msach@24: else msach@24: { msach@24: numIn = Q->insertPos - Q->extractPos -1;//-1 bec empty @ side-by-side msach@24: } msach@24: return numIn; msach@24: } msach@24: msach@24: msach@24: /*Expands the queue size automatically when it's full msach@24: */ msach@24: void msach@24: writePrivQ( void * in, PrivQueueStruc* Q ) msach@24: { msach@24: while(1){ msach@24: void **startOfData = Q->startOfData; msach@24: void **endOfData = Q->endOfData; msach@24: msach@24: void **insertPos = Q->insertPos; msach@24: void **extractPos = Q->extractPos; msach@24: msach@24: //Full? (insert is just below extract when full) msach@24: if( extractPos - insertPos != 1 && msach@24: !(insertPos == endOfData && extractPos == startOfData)) msach@24: { *(Q->insertPos) = in; //insert before move msach@24: if( insertPos == endOfData ) //write new pos exactly once, correctly msach@24: { Q->insertPos = startOfData; msach@24: } msach@24: else msach@24: { Q->insertPos++; msach@24: } msach@24: return; msach@24: } msach@24: //Q is full msach@24: enlargePrivQ( Q ); msach@24: } msach@24: } msach@24: msach@24: msach@24: /*Returns false when the queue was full. msach@24: * have option of calling make_larger_PrivQ to make more room, then try again msach@24: */ msach@24: int writeIfSpacePrivQ( void * in, PrivQueueStruc* Q ) msach@24: { msach@24: void **startOfData = Q->startOfData; msach@24: void **endOfData = Q->endOfData; msach@24: msach@24: void **insertPos = Q->insertPos; msach@24: void **extractPos = Q->extractPos; msach@24: msach@24: if( extractPos - insertPos != 1 && msach@24: !(insertPos == endOfData && extractPos == startOfData)) msach@24: { *(Q->insertPos) = in; //insert before move msach@24: if( insertPos == endOfData ) //write new pos exactly once, correctly msach@24: { Q->insertPos = startOfData; msach@24: } msach@24: else msach@24: { Q->insertPos++; msach@24: } msach@24: return TRUE; msach@24: } msach@24: //Q is full msach@24: return FALSE; msach@24: } msach@24: msach@24: /*Treats queue as a stack -- no matter contents, if read done right after msach@24: * a push, then the pushed item is what comes out. msach@24: * Expands the queue size automatically when it's full. msach@24: */ msach@24: void msach@24: pushPrivQ( void * in, PrivQueueStruc* Q ) msach@24: { msach@24: while(1){ msach@24: void **startOfData = Q->startOfData; msach@24: void **endOfData = Q->endOfData; msach@24: msach@24: void **insertPos = Q->insertPos; msach@24: void **extractPos = Q->extractPos; msach@24: msach@24: //Full? (insert is just below extract when full) msach@24: if( extractPos - insertPos != 1 && msach@24: !(insertPos == endOfData && extractPos == startOfData)) msach@24: { //insert -- but go backwards, inserting at read position then msach@24: // move read pos backwards msach@24: *(Q->extractPos) = in; msach@24: if( extractPos == startOfData ) //write new pos exactly once, correctly msach@24: { Q->extractPos = endOfData; //can't overrun then fix it 'cause msach@24: } // other thread might read bad pos msach@24: else msach@24: { Q->extractPos--; msach@24: } msach@24: return; msach@24: } msach@24: //Q is full msach@24: enlargePrivQ( Q ); msach@24: } msach@24: } msach@24: msach@24: void msach@24: freePrivQ( PrivQueueStruc *Q ) msach@24: { msach@24: VMS_int__free( Q->startOfData ); msach@24: VMS_int__free( Q ); Me@9: }