int main(void) { /* Test Set 1: * Test newQueue() and deleteQueue() */ struct Queue* test1 = QUE_newQueue(); assert(test1 != NULL); assert(test1->m_items == 0); assert(test1->m_list != NULL); assert(test1->m_list->numNodes == 0); assert(test1->m_list->head == NULL); assert(test1->m_list->tail == NULL); QUE_deleteQueue(test1); printf("Test Set 1 successful.\n"); /* Test Set 2: * Test push(), pop(), front(), back(), * size(), and empty() */ /* Some test items */ char testItems[] = "Hello World--again!"; int testSize = (int)strlen(testItems); struct Queue* test2 = QUE_newQueue(); for (int i = 0; i < testSize; i++) { if (i == 0) { assert(QUE_empty(test2) == 1); } else { assert(QUE_empty(test2) == 0); } QUE_push(test2, &testItems[i]); assert(QUE_size(test2) == (i + 1)); assert(QUE_back(test2) == &testItems[i]); } for (int j = 0; j < testSize; j++) { QUE_pop(test2); assert(QUE_size(test2) == (testSize - (j + 1))); if (j == (testSize - 1)) { assert(QUE_empty(test2) == 1); } } QUE_deleteQueue(test2); printf("Test Set 2 successful.\n"); return 0; }
Bool bfqAllocBuffer ( BufferQueue_Handle queue, Ptr * buffer, Uns timeout ) { BufferQueue_Frame * frame; // wait until an empty buffer is available, timeout // if necessary. if (! SEM_pend(&(queue->semEmptyBuffers), timeout) ) { return FALSE; } // double check if ( QUE_empty(&(queue->queEmptyBuffers)) ) return FALSE; // Get the frame from the queue and double check it frame = QUE_get((Ptr)&(queue->queEmptyBuffers)); if ((Ptr)frame == (Ptr)&(queue->queEmptyBuffers)) return FALSE; // Copy the pointer *buffer = frame->Buffer; // put the frame to the empty frames queue QUE_put( &(queue->queEmptyFrames), frame); return TRUE; }
/* * ======== DOV_close ======== */ static Int DOV_close(DEV_Handle device) { DOV_CopyObj *copy = (DOV_CopyObj *)device->object; DEV_Frame *frame; /* close underlying device(s) */ DEV_close(&(copy->dobj)); /* move frames _up_ from downstream device */ while (!QUE_empty(copy->dobj.todevice)) { frame = QUE_get(copy->dobj.todevice); frame->size = frame->size + copy->size; frame->addr = (Char *)frame->addr - copy->size; QUE_put(device->todevice, frame); } QUE_delete(copy->dobj.todevice); QUE_delete(copy->dobj.fromdevice); /* free overlap buffer */ MEM_free(0, copy->overlap, copy->size); /* recycle copy object */ MEM_free(0, copy, sizeof(DOV_CopyObj)); return (SYS_OK); }
/* * ======== DIO_tskReady ======== */ Bool DIO_tskReady(DEV_Handle device, SEM_Handle sem) { DIO_Handle dio = (DIO_Handle)device->object; dio->context.sems.ready = sem; return (!(QUE_empty(device->fromdevice))); }
/* * ======== DPI_ready ======== * called by SIO_select(), returns TRUE if device is ready. */ Static Bool DPI_ready(DEV_Handle dev, SEM_Handle sem) { PipeObj *pipe = (PipeObj *)dev->object; pipe->sPipe->readySem[dev->mode] = sem; return !(QUE_empty(dev->fromdevice)); }
int main(void) { struct Queue* myQueue = QUE_newQueue(); int* myInt = (int*)malloc(sizeof(int)); *myInt = 42; QUE_push(myQueue, &myInt); int* testPtr = QUE_front(myQueue); int* anotherPtr = QUE_back(myQueue); int testSize = QUE_size(myQueue); int anotherSize = QUE_empty(myQueue); QUE_pop(myQueue); testSize = QUE_size(myQueue); anotherSize = QUE_empty(myQueue); QUE_deleteQueue(myQueue); free(myInt); testPtr = NULL; anotherPtr = NULL; return 0; }
Bool bfqGetBuffer ( BufferQueue_Handle queue, Ptr * buffer, Uns timeout ) { BufferQueue_Frame * frame; // wait until a full buffer is available, timeout // if necessary. if (! SEM_pend(&(queue->semFullBuffers), timeout) ) { return FALSE; } // Get the frame from the queue and double check it assertLog(! QUE_empty(&(queue->queFullBuffers))); frame = QUE_get(&(queue->queFullBuffers)); assertLog((Ptr)frame != (Ptr)&(queue->queFullBuffers)); // put the frame to the empty frames queue QUE_put( &(queue->queEmptyFrames), frame); // Copy the pointer *buffer = frame->Buffer; return TRUE; }
/* * ======== DOV_open ======== */ static Int DOV_open(DEV_Handle device, String name) { DOV_CopyObj *copy; DEV_Device *entry; Int status = SYS_EALLOC; DEV_Frame *frame; size_t size; if (device->mode != DEV_INPUT) { return (SYS_EINVAL); } /* * If devid is nonzero, it holds the 'size' of the overlap buffer. */ if (device->devid > 0) { size = device->devid; } else { size = atoi(name); /* * Skip the numeric characters to get to the underlying * device's name. */ while (isdigit(*name)) { name++; } } if (size <= 0 || size >= device->bufsize) { return (SYS_EINVAL); } /* * find underlying device in device table */ name = DEV_match(name, &entry); if (entry == NULL) { return (SYS_ENODEV); } /* allocate copy object */ if ((copy = MEM_alloc(0, sizeof(DOV_CopyObj), 0)) == MEM_ILLEGAL) { return (SYS_EALLOC); } copy->size = size; /* allocate and initialize overlap buffer */ if ((copy->overlap = MEM_valloc(0, size, 0, DOV->INITIAL)) == MEM_ILLEGAL) { goto e1; } copy->dobj = *device; /* copy descriptor fields */ copy->dobj.fxns = *(DEV_Fxns *)(entry->fxns); copy->dobj.devid = entry->devid; copy->dobj.params = entry->params; /* size of underlying buffers */ copy->dobj.bufsize = device->bufsize - size; /* * create queues and frames for underlying device. */ if ((copy->dobj.todevice = QUE_create(NULL)) == NULL) { goto e2; } if ((copy->dobj.fromdevice = QUE_create(NULL)) == NULL) { goto e3; } /* * adjust frame size and address according to the overlap size before * copying frames to underlying device's 'todevice' queue */ while (!QUE_empty(device->todevice)) { frame = QUE_get(device->todevice); frame->size = frame->size - size; frame->addr = (Char *)frame->addr + size; QUE_put(copy->dobj.todevice, frame); } /* open underlying device */ if ((status = DEV_open((©->dobj), name)) != SYS_OK) { goto e4; } device->object = (Ptr)copy; return (SYS_OK); /* all is well */ /* free memory and return error code */ e4: QUE_delete(copy->dobj.fromdevice); e3: QUE_delete(copy->dobj.todevice); e2: MEM_free(0, copy->overlap, copy->size); e1: MEM_free(0, copy, sizeof(DOV_CopyObj)); return (status); }
/* * ======== DIO_cbReady ======== */ Bool DIO_cbReady(DEV_Handle device, SEM_Handle sem) { return (!(QUE_empty(device->fromdevice))); }
/* * ======== DPI_open ======== */ Static Int DPI_open(DEV_Handle dev, String name) { PipeObj *pipe; SPipeObj *sPipe, *tmpPipe; /* decode and validate devid */ if (dev->devid < 0) { dev->devid = atoi(name); } SEM_pend(mutex, SYS_FOREVER); /* search pipe list for previously opened pipe with same id */ sPipe = MEM_ILLEGAL; if (!QUE_empty(sPipeList)) { tmpPipe = (SPipeObj *)QUE_head(sPipeList); do { if (tmpPipe->id == dev->devid) { sPipe = tmpPipe; break; } tmpPipe = (SPipeObj *)QUE_next((&tmpPipe->link)); } while (tmpPipe != (SPipeObj *)sPipeList); } if (sPipe == MEM_ILLEGAL) { /* * Allocate and initialize SPipeObj on first open. */ sPipe = mkSPipe(dev); if (sPipe == MEM_ILLEGAL) { SEM_post(mutex); return SYS_EALLOC; } QUE_put(sPipeList, &sPipe->link); } else { /* sPipe found on list */ if (sPipe->device[dev->mode] != NULL) { /* * Only one input and one output allowed */ SEM_post(mutex); return SYS_EBUSY; } } sPipe->device[dev->mode] = dev; SEM_post(mutex); pipe = MEM_alloc(0, sizeof (PipeObj), 0); if (pipe == MEM_ILLEGAL) { /* * We need to undo work done by mkSPipe() if first open. * Also need to undo changes to sPipeList queue. */ QUE_remove(&sPipe->link); rmSPipe(sPipe); return SYS_EALLOC; } /* * Criss-cross SEM handles so both sides are referencing * the same physical objects. */ if (dev->mode == DEV_INPUT) { pipe->fromSem = sPipe->dataSem; pipe->toSem = sPipe->freeSem; } else { pipe->toSem = sPipe->dataSem; pipe->fromSem = sPipe->freeSem; } /* * Point things around. */ pipe->sPipe = sPipe; dev->object = (Ptr)pipe; return (SYS_OK); }
/* * ======== DPI_issue ======== */ Static Int DPI_issue(DEV_Handle dev) { PipeObj *pipe = (PipeObj *)dev->object; SPipeObj *sPipe = pipe->sPipe; DEV_Handle otherdev = sPipe->device[dev->mode ^ 0x1]; SEM_Handle otherReady = sPipe->readySem[dev->mode ^ 0x1]; DEV_Frame *otherframe; DEV_Frame *frame; #ifdef COPYBUFS DEV_Frame *srcframe; DEV_Frame *dstframe; #endif /* * Atomically check that each side has a frame so we can do an * exchange. We can't be sure that a frame is on the * dev->todevice queue (just put there by SIO) since a task * switch to the task on the other side might intervene and * take the frame from this side. */ TSK_disable(); if (otherdev != NULL && !QUE_empty(dev->todevice) && !QUE_empty(otherdev->todevice)) { otherframe = QUE_get(otherdev->todevice); frame = QUE_get(dev->todevice); /* done with atomic stuff */ TSK_enable(); /* * #define COPYBUFS to cause buffers to be copied through the pipe * instead of being exchanged. Doing so retains the semantics of * the ISSUERECLAIM model, but is slow. If COPYBUFS is *not* defined, * then one side reclaims buffers issued by the other side, thereby * not strictly retaining buffer ordering. */ #ifdef COPYBUFS if (dev->mode == DEV_INPUT) { dstframe = frame; srcframe = otherframe; } else { dstframe = otherframe; srcframe = frame; } memcpy(dstframe->addr, srcframe->addr, srcframe->size); dstframe->size = srcframe->size; dstframe->arg = srcframe->arg; QUE_put(dev->fromdevice, frame); QUE_put(otherdev->fromdevice, otherframe); /* * frames reclaimed from an output device must have size 0. */ if (dev->mode != DEV_INPUT) { frame->size = 0; } else { otherframe->size = 0; } #else QUE_put(dev->fromdevice, otherframe); QUE_put(otherdev->fromdevice, frame); /* * frames reclaimed from an output device must have size 0. */ if (dev->mode != DEV_INPUT) { otherframe->size = 0; } else { frame->size = 0; } #endif } else { /* done with atomic stuff */ TSK_enable(); } SEM_post(pipe->toSem); if (otherReady != NULL) { SEM_post(otherReady); } return SYS_OK; }