/* * author: christopher pepe * date: 19 June 2007 * about: * This queue design allows mutexless protection of data that is used by multiple sources by * seperating the read and write operations and only allowing reads of fully written data. * The source writes its data to the next available spot and then increments the write count atomically * The destination reads the next available data and then increments the read count atomically * read and written are unsigned and fixed width * written >= read always * countInQueue = written - read * itemSize = sizeof(data block)*countInQueue * * A struct of n buffers are used to store the data where the next available buffer is * read % n -or- written % n * * Terms: * item - a member of the queue (a person in line at the bank) * dataBit - an individual number in a member of the queue (a $5 bill in the persons hand) */ #include #include #include "fifo.h" //create the fifo with 'locations' buffers, each of size 'slots' * 'dBytes' fifo* FifoInit(fifo* me, unsigned int locations, unsigned int slots, unsigned int dBytes) { unsigned int iter; unsigned int memError = 0; //alloc space for the fifo structure (not all of the data though) me = malloc( sizeof(fifo) ); if( me == 0 ) { printf("FifoInit: can't malloc space for fifo\n"); return 0; //<-- early return here } //initialize the main structure me->read = 0; me->written = 0; me->numItems = locations; me->itemSize = slots*dBytes; me->dBytes = dBytes; //allocate space for the pointers to the fifo items me->itemTable = (unsigned int*)malloc( locations * sizeof(unsigned int *) ); if( me->itemTable == 0 ) { printf("FifoInit: can't malloc space for fifo item list\n"); return 0; //<-- early return here } //allocate space for each item in the fifo //and store a pointer to it in the itemTable for(iter=0; iteritemTable = (unsigned int)malloc( me->itemSize ); //printf("me->itemSize=%d\n", me->itemSize); if( *me->itemTable == 0 ) { memError = 1; } //increment to next pointer location me->itemTable++; } if( memError == 1 ) { //TODO: is this the value of me anyway? printf("FifoInit: memError, can't allocate space for fifo item\n"); return 0; //<-- early return here } //reset data pointer to starting position me->itemTable -= locations; return me; } //return the base address of the next available buffer to write or the next buffer // waiting to be read. //if readLocation == 1 then point to the next read buffer, else point to the // next write buffer unsigned int FifoNextLocation(fifo* me, unsigned int readLocation) { if( readLocation ) { return me->read % me->numItems; } else { return me->written % me->numItems; } } //write data to the next available location in the fifo int FifoPut(fifo* me, unsigned int *rawData) { unsigned int loc; unsigned int x; unsigned int* itemArray; unsigned int dataBits; //don't allow data to be written until //older data has been read. New data is discarded if( (me->written - me->read) >= me->numItems - 1 ) { if(debug)printf("no space, discarding data samples\n"); return NOSPACE; //<-- early return here } //get the location of the next free buffer loc = FifoNextLocation(me, F_WR); //get the address of the next free buffer itemArray = (unsigned int*)me->itemTable[loc]; //figure out how many databits are in the item dataBits = (me->itemSize)/( me->dBytes ); //copy rawData to me //this isn't the most effective way to copy data //but is the most generic for(x=0;xwritten++; return 0; } //read data from the next available location in the fifo int FifoGet(fifo* me, unsigned int *rawData ) { unsigned int loc; int x, retval; unsigned int* itemArray; unsigned int dataBits; retval = 0; //something bad happened if we have read more items //more than we have written if( me->read >= me->written ) { return SOFTERROR; //<-- early return here } //notify user that they are reading wrapped data //this means there is older data still in the //queue ahead of this data. This isn't likely //what they want but they may not care either if( (me->written - me->read) > me->numItems ) { retval = WRAP; } //get the location of the next buffer to read loc = FifoNextLocation(me, F_RD); //get the address of the next buffer to read itemArray = (unsigned int*)me->itemTable[loc]; //figure out how many databits are in the item dataBits = (me->itemSize)/( me->dBytes ); //this isn't the most effective way to copy data //but is the most generic for(x=0;xread++; return retval; }