/* * ======== GIO_reclaim ======== */ Int GIO_reclaim(GIO_Object *obj, Ptr *pBuf, SizeT *pSize, UArg *pArg) { IOM_Packet *packet; Queue_Handle doneList; Queue_Handle freeList; UInt key; Int status; Error_Block eb; doneList = GIO_Instance_State_doneList(obj); freeList = GIO_Instance_State_freeList(obj); Error_init(&eb); while (obj->doneCount == 0) { if (Sync_wait(obj->sync, obj->timeout, &eb) == Sync_WaitStatus_TIMEOUT) { return (IOM_ETIMEOUT); } } key = Hwi_disable(); obj->doneCount--; packet = Queue_dequeue(doneList); Hwi_restore(key); if (pArg != NULL) { *pArg = packet->arg; } /* pBuf is set to NULL by GIO_read() and GIO_write() */ if (pBuf != NULL) { *pBuf = packet->addr; } if (pSize != NULL) { *pSize = packet->size; } status = packet->status; /* * re-signal if more buffers are ready * This is required in the case of ISyncEvent and ISyncSwi to allow * clients to reclaim a single buffer and not force them to bleed the * stream. */ if (obj->doneCount > 0) { Sync_signal(obj->sync); } /* recycle packet back onto free list */ key = Hwi_disable(); obj->freeCount++; Queue_enqueue(freeList, (Queue_Elem *)packet); Hwi_restore(key); return (status); }
/* * ======== callback ======== * This function is called by the underlying IOM driver. */ static Void callback(Ptr cbArg, IOM_Packet *packet) { GIO_Handle obj = (GIO_Handle)cbArg; GIO_AppCallback *appCallback = (GIO_AppCallback *)packet->misc; Int status; Ptr addr; SizeT size; Queue_Handle list; UInt key; key = Hwi_disable(); obj->submitCount--; Hwi_restore(key); if (appCallback == NULL) { Sync_signal(obj->sync); } else { if (obj->model == GIO_Model_ISSUERECLAIM) { /* put packet on doneList where GIO_reclaim() will find it */ list = GIO_Instance_State_doneList(obj); key = Hwi_disable(); obj->doneCount++; Queue_enqueue(list, (Queue_Elem *)packet); Hwi_restore(key); Sync_signal(obj->sync); } else { list = GIO_Instance_State_freeList(obj); status = packet->status; addr = packet->addr; size = packet->size; key = Hwi_disable(); obj->freeCount++; Queue_enqueue(list, (Queue_Elem *)packet); Hwi_restore(key); (*appCallback->fxn)(appCallback->arg, status, addr, size); } } }
/* * ======== Stream_internalCallback ======== * This function is called by the underlying IConverter when IO completes. */ Void Stream_internalCallback(UArg cbArg) { Stream_Handle obj = (Stream_Handle)cbArg; /* * Increment of ready not atomic because the callback is in the * context of an ISR and reclaim cannot preempt. reclaim can only be called * within the context the the same isr or by a single swi or task. */ obj->ready++; Sync_signal(obj->complete); }
/* * ======== Stream_reclaim ======== */ SizeT Stream_reclaim(Stream_Object *obj, Ptr *bufp, UInt timeout, UArg *arg, Error_Block *eb) { DriverTypes_Packet *packet = NULL; List_Handle freeList; UInt key; if (obj->issued == 0) { Error_raise(eb, Stream_E_noBuffersIssued, 0, 0); return (0); } while (obj->ready == 0) { if (!Sync_wait(obj->complete, timeout, eb)) { if (timeout != 0) { Error_raise(eb, Stream_E_timeout, timeout, 0); } return (0); } }; IConverter_reclaim(obj->convHandle, &packet, eb); if (arg != NULL) { *arg = packet->arg; } /* bufp is NULL in Stream_read and Stream_write. */ if (bufp != NULL) { *bufp = packet->addr; } key = Hwi_disable(); obj->ready--; Hwi_restore(key); obj->issued--; /* * re-signal if more buffers are ready * This is required in the case of ISyncEvent and ISyncSwi to allow * clients to reclaim a single buffer and not force them to bleed the * Stream. In the case of ISyncSem , this re-signal is an overhead */ if (obj->ready > 0) { Sync_signal(obj->complete); } freeList = Stream_Instance_State_freeList(obj); /* recycle packet back onto free list */ List_put(freeList, (List_Elem *)packet); if ((packet->error != NULL) && (packet->error != DriverTypes_EABORTED)) { Error_raise(eb, packet->error, packet->status, 0); return (0); } else { return (packet->size); } }