📄 zbuflib.c
字号:
if ((zbufBlockNew = (ZBUF_BLOCK_ID) KHEAP_ALLOC((sizeof(struct zbufBlockId) + (segSize * segNum)))) == NULL) /* allocate hdr and seg block */ goto release; blockStart = (caddr_t) (zbufBlockNew + 1);/* set start of seg block */ } else /* use supplied user memory */ { /* calc the number of segments that can be obtained from user mem */ if ((segNum = blockLen / segSize) == 0) /* must be at least one */ goto release; if ((zbufBlockNew = (ZBUF_BLOCK_ID) KHEAP_ALLOC (sizeof(struct zbufBlockId))) == NULL)/* allocate block hdr only */ goto release; } zbufBlockNew->length = segSize; /* block is for "segSize" */ zbufBlockNew->zbufPoolId = zbufPoolId; /* for _zbufSegPoolFree() */ zbufBlockNew->segFree = (void *) blockStart;/* first seg in block is free */ /* * Go through block, and divide up into segNum number of segments. * The first location of each segment points to the next free segment, * with the last segment pointing to NULL. In this way, a sll of free * segments is kept, with the pointer in the segment memory itself. */ for (ix = 1; ix < segNum; ix++, blockStart += segSize) *((void **) blockStart) = (void *) (blockStart + segSize); *((void **) blockStart) = NULL; /* find the proper location in the pool to insert the new seg block */ if ((zbufPoolId->blockHead != NULL) && (zbufPoolId->blockHead->length < segSize)) { zbufBlock = zbufPoolId->blockHead; for (; zbufBlock->blockNext != NULL; zbufBlock = zbufBlock->blockNext) if (zbufBlock->blockNext->length >= segSize) break; } if (zbufBlock == NULL) /* insert new block at start */ { zbufBlockNew->blockNext = zbufPoolId->blockHead;/* new to first */ zbufPoolId->blockHead = zbufBlockNew; /* head to new */ } else /* insert in middle or end */ { zbufBlockNew->blockNext = zbufBlock->blockNext; /* new to next */ zbufBlock->blockNext = zbufBlockNew; /* prev to new */ } status = OK; /* done! */release: /* error encountered */ semGive (zbufPoolId->poolSem); /* give up access */ return (status); }/********************************************************************************* _zbufSegPoolFree - return a zbuf segment to a zbuf segment pool** This routine returns a zbuf segment to a zbuf segment pool.* To return <buf> to the zbuf segment block that it was originally allocated* from, place the segment <buf> at the start of the segment block associated* with <zbufBlockId>. If <zbufBlockId> is NULL, the segment <buf> was* allocated from system memory, and should be returned with free().** RETURNS: N/A.** NOMANUAL*/void _zbufSegPoolFree ( caddr_t buf, /* zbuf segment to return */ ZBUF_BLOCK_ID zbufBlockId /* seg block to return <buf> to */ ) { ZBUF_POOL_ID zbufPoolId; /* back pointer to pool ID */ if (zbufBlockId == NULL) /* if originally malloc'ed */ KHEAP_FREE(buf); else /* else return to pool */ { zbufPoolId = zbufBlockId->zbufPoolId; /* obtain back pointer to ID */ /* obtain exclusive access to zbuf segment pool structures */ if ((semTake (zbufPoolId->poolSem, WAIT_FOREVER)) == ERROR) return; *((void **) buf) = zbufBlockId->segFree;/* hook my next to first */ zbufBlockId->segFree = (void *) buf; /* hook head to me */ zbufPoolId->use--; /* check it in */ semFlush (zbufPoolId->waitSem); /* free those waiting for seg */ semGive (zbufPoolId->poolSem); /* give up access */ } }/********************************************************************************* zbufInsertPool - obtain a segment and insert into a zbuf** This routine obtains a zbuf segment from <zbufPoolId> and* inserts it into zbuf <zbufId> at the specified location. The requested* segment is not initialized (that is, it is not zeroed out) by this routine.* * This routine searches <zbufPoolId> looking for a suitably sized free* segment. The smallest free segment that is at least <len> bytes in length* is obtained and inserted into <zbufId>. If no free segments are found,* this routine will pend for <timeout> ticks waiting for a zbuf segment to be* released from another zbuf. As segments are released from other zbufs,* they are examined to see if they are at least <len> bytes. If they are* not suitable, the timeout is reset to <timeout> ticks, and this routine* will pend again waiting for a segment to be released.** If <zbufPoolId> is NULL, the system memory pool is used to allocate a* segment of <len> bytes. Upon release of this segment from the zbuf, it* will returned to the system memory pool.** The location of insertion is specified by <zbufSeg> and <offset>. See* the zbufLib manual page for more information on specifying* a byte location within a zbuf. In particular, insertion within* a zbuf occurs before the byte location specified by <zbufSeg> and <offset>.* Additionally, <zbufSeg> and <offset> must be NULL and 0,* respectively, when inserting into an empty zbuf.** RETURNS:* The zbuf segment ID of the inserted segment,* or NULL if the operation fails.** NOMANUAL*/ZBUF_SEG zbufInsertPool ( ZBUF_POOL_ID zbufPoolId, /* pool to obtain zbuf segment from */ ZBUF_ID zbufId, /* zbuf to insert segment into */ ZBUF_SEG zbufSeg, /* zbuf segment base for <offset> */ int offset, /* relative byte offset */ int len, /* requested segment length in bytes */ int timeout /* timeout in ticks */ ) { ZBUF_BLOCK_ID zbufBlock = NULL; /* segment block header */ caddr_t buf = NULL; /* requested segment buf */ int lenLast = NULL; /* last seg block length seen */ if (zbufPoolId == NULL) /* alloc from system mem */ if ((buf = KHEAP_ALLOC(len)) == NULL) return (NULL); /* if not allocating from system memory, try to obtain from seg pool */ while (buf == NULL) { /* obtain exclusive access to zbuf segment pool structures */ if ((semTake (zbufPoolId->poolSem, timeout)) == ERROR) return (NULL); /* * Search the pool's seg blocks headers for a suitable size (first fit) * and that has free segments attached to it. An over-sized segment * will be taken if no more suitably sized segments are available. * No fragmentation is performed. A segment remains whole. * If no segments are available (right-fit or oversized), pend on * waitSem for segment to come in from _zbufSegPoolFree(). */ zbufBlock = zbufPoolId->blockHead; for (; zbufBlock != NULL; zbufBlock = zbufBlock->blockNext) if (((lenLast = zbufBlock->length) >= len) && (zbufBlock->segFree != NULL)) break; if (zbufBlock == NULL) { /* going to pend or exit, so give up access */ semGive (zbufPoolId->poolSem); /* check that there are seg blocks large enough for len */ if ((lenLast == NULL) || (lenLast < len)) return (NULL); /* wait for segments to come back in... */ if ((semTake (zbufPoolId->waitSem, timeout)) == ERROR) return (NULL); } else /* found suitable segment */ { buf = (caddr_t) zbufBlock->segFree; /* segment is first */ zbufBlock->segFree = *((void **) buf); /* first is next */ zbufPoolId->use++; /* check it out */ semGive (zbufPoolId->poolSem); /* give up access */ } } /* insert the new segment into zbufId at the specified location */ if ((zbufSeg = zbufInsertBuf (zbufId, zbufSeg, offset, buf, len, _zbufSegPoolFree, (int) zbufBlock)) == NULL) _zbufSegPoolFree (buf, zbufBlock); /* free seg on failure */ return (zbufSeg); }#endif /* FALSE *//********************************************************************************* zbufCreate - create an empty zbuf** This routine creates a zbuf, which remains empty (that is, it contains* no data) until segments are added by the zbuf insertion routines.* Operations performed on zbufs require a zbuf ID, which is returned by* this routine.** VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call this function from within the kernel * protection domain only. In addition, the returned ID is valid within * the kernel protection domain only. This restriction does not apply * under non-AE versions of VxWorks. ** RETURNS:* A zbuf ID, or NULL if a zbuf cannot be created.** SEE ALSO: zbufDelete()*/ZBUF_ID zbufCreate (void) { return ((pZbufFunc->createRtn == NULL) ? NULL : (ZBUF_ID) (pZbufFunc->createRtn) ()); }/********************************************************************************* zbufDelete - delete a zbuf** This routine deletes any zbuf segments in the specified zbuf, then* deletes the zbuf ID itself. <zbufId> must not be used after this routine* executes successfully.** For any data buffers that were not in use by any other zbuf, zbufDelete()* calls the associated free routine (callback).** VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call this function from within the kernel * protection domain only. In addition, all arguments to this function can * reference only that data which is valid in the kernel protection domain. * This restriction does not apply under non-AE versions of VxWorks. ** RETURNS:* OK, or ERROR if the zbuf cannot be deleted.** SEE ALSO: zbufCreate(), zbufInsertBuf()*/STATUS zbufDelete ( ZBUF_ID zbufId /* zbuf to be deleted */ ) { return ((pZbufFunc->deleteRtn == NULL) ? ERROR : (pZbufFunc->deleteRtn) (zbufId)); }/********************************************************************************* zbufInsert - insert a zbuf into another zbuf** This routine inserts all <zbufId2> zbuf segments into <zbufId1> at the* specified byte location.** The location of insertion is specified by <zbufSeg> and <offset>. See* the zbufLib manual page for more information on specifying* a byte location within a zbuf. In particular, insertion within* a zbuf occurs before the byte location specified by <zbufSeg> and <offset>.* Additionally, <zbufSeg> and <offset> must be NULL and 0,* respectively, when inserting into an empty zbuf.** After all the <zbufId2> segments are inserted into <zbufId1>, the zbuf ID* <zbufId2> is deleted. <zbufId2> must not be used after this routine* executes successfully.** VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call this function from within the kernel * protection domain only. In addition, all arguments to this function can * reference only that data which is valid in the kernel protection domain. * Likewise, the returned ZBUF_SEG is valid within the kernel protection * domain only. This restriction does not apply under non-AE versions of * VxWorks. ** RETURNS:* The zbuf segment ID for the first inserted segment,* or NULL if the operation fails.*/ZBUF_SEG zbufInsert ( ZBUF_ID zbufId1, /* zbuf to insert <zbufId2> into */ ZBUF_SEG zbufSeg, /* zbuf segment base for <offset> */ int offset, /* relative byte offset */ ZBUF_ID zbufId2 /* zbuf to insert into <zbufId1> */ ) { return ((pZbufFunc->insertRtn == NULL) ? NULL : (ZBUF_SEG) (pZbufFunc->insertRtn) (zbufId1, zbufSeg, offset, zbufId2)); }/********************************************************************************* zbufInsertBuf - create a zbuf segment from a buffer and insert into a zbuf** This routine creates a zbuf segment from the application buffer <buf>* and inserts it at the specified byte location in <zbufId>.** The location of insertion is specified by <zbufSeg> and <offset>. See* the zbufLib manual page for more information on specifying* a byte location within a zbuf. In particular, insertion within* a zbuf occurs before the byte location specified by <zbufSeg> and <offset>.* Additionally, <zbufSeg> and <offset> must be NULL and 0,* respectively, when inserting into an empty zbuf.** The parameter <freeRtn> specifies a free-routine callback that runs when* the data buffer <buf> is no longer referenced by any zbuf segments. If* <freeRtn> is NULL, the zbuf functions normally, except that the* application is not notified when no more zbufs segments reference <buf>.* The free-routine callback runs from the context of the task that last* deletes reference to the buffer. Declare the <freeRtn> callback as* follows (using whatever routine name suits your application):* .CS* void freeCallback* (* caddr_t buf, /@ pointer to application buffer @/* int freeArg /@ argument to free routine @/* )* .CE** VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call this function from within the kernel * protection domain only. In addition, all arguments to this function can * reference only that data which is valid in the kernel protection domain. * This restriction does not apply under non-AE versions of VxWorks. ** RETURNS:* The zbuf segment ID of the inserted segment,* or NULL if the operation fails.*/ZBUF_SEG zbufInsertBuf ( ZBUF_ID zbufId, /* zbuf in which buffer is inserted */ ZBUF_SEG zbufSeg, /* zbuf segment base for <offset> */ int offset, /* relative byte offset */ caddr_t buf, /* application buffer for segment */ int len, /* number of bytes to insert */ VOIDFUNCPTR freeRtn, /* free-routine callback */ int freeArg /* argument to free routine */ ) { return ((pZbufFunc->insertBufRtn == NULL) ? NULL : (ZBUF_SEG) (pZbufFunc->insertBufRtn) (zbufId, zbufSeg, offset, buf, len, freeRtn, freeArg)); }/********************************************************************************* zbufInsertCopy - copy buffer data into a zbuf** This routine copies <len> bytes of data from the application buffer <buf>* and inserts it at the specified byte location in <zbufId>. The* application buffer is in no way tied to the zbuf after this operation;* a separate copy of the data is made.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -