📄 netbuflib.c
字号:
reTry: level = intLock(); /* lock interrupts very briefly */ if ((pClBlk = pNetPool->pClBlkHead) != NULL) { pNetPool->pClBlkHead = pClBlk->clNode.pClBlkNext; intUnlock (level); /* unlock interrupts */ pClBlk->clNode.pClBuf = NULL; pClBlk->pClFreeRtn = NULL; pClBlk->clRefCnt = 0; pClBlk->pNetPool = pNetPool; /* netPool originator */ } else /* if (canWait != M_ISR) */ { if (canWait == M_WAIT) { if (_pNetBufCollect) { intUnlock (level); /* unlock interrupts */ (*_pNetBufCollect) (pNetPool->pPoolStat); canWait = M_DONTWAIT; goto reTry; } } intUnlock (level); errnoSet (S_netBufLib_NO_POOL_MEMORY); } return (pClBlk); }/********************************************************************************* _clusterGet - get a new cluster of a given cluster pool.** This function returns a cluster given a pool pointer. The reference count* for the cluster is incremented.** RETURNS: pointer to a cluster or NULL** NOMANUAL*/LOCAL char * _clusterGet ( NET_POOL_ID pNetPool, /* pointer to the net pool */ CL_POOL_ID pClPool /* ptr to the cluster pool */ ) { int level; /* level of interrupt */ CL_BUF_ID pClBuf; /* ptr to the cluster buffer */ level = intLock (); /* lock interrupts briefly */ if (pClPool->pClHead == NULL) /* return if no buffers */ { intUnlock (level); return (NULL); } pClBuf = pClPool->pClHead; /* update the head */ if ((pClPool->pClHead = pClBuf->pClNext) == NULL) { /* update the pool Mask */ pNetPool->clMask &= ~(CL_LOG2_TO_CL_SIZE(pClPool->clLg2)); } pClPool->clNumFree--; /* decrement the free count */ pClPool->clUsage++; /* increment the usage count */ intUnlock (level); return ((char *)pClBuf); }/********************************************************************************* mClGet - get a new mBlk/cluster pair.** This function gets a free cluster from the NET_POOL and joins it with* the mBlk passed to it. An mBlk must be pre allocated and passed to this* function.** RETURNS: OK or ERROR.** NOMANUAL*/LOCAL STATUS _mClGet ( NET_POOL_ID pNetPool, /* pointer to the net pool */ M_BLK_ID pMblk, /* mBlk to embed the cluster in */ int bufSize, /* size of the buffer to get */ int canWait, /* wait or dontwait */ BOOL bestFit /* TRUE/FALSE */ ) { int log2Size; /* size of cluster to the base 2 */ CL_POOL_ID pClPool; /* pointer to the cluster pool */ CL_BUF_ID pClBuf = NULL; /* pointer to the cluster buffer */ CL_BLK_ID pClBlk = NULL; /* pointer to the cluster blk */ FAST int ms; /* integer for level */ /* check pMblk */ if ((pMblk == NULL) || ((pClBlk = _clBlkGet (pNetPool, canWait)) == NULL)) goto mClGetError; /* check the boundary conditions */ if (bufSize > pNetPool->clSizeMax) { if (bestFit) { errno = S_netBufLib_CLSIZE_INVALID; goto mClGetError; } else log2Size = pNetPool->clLg2Max; } else if (bufSize < pNetPool->clSizeMin) log2Size = pNetPool->clLg2Min; else { log2Size = SIZE_TO_LOG2(bufSize); if (bufSize > CL_LOG2_TO_CL_SIZE(log2Size)) log2Size++; } /* get the appropriate pool pointer */ if ((pClPool = pNetPool->clTbl [CL_LOG2_TO_CL_INDEX (log2Size)]) == NULL) {#ifdef NETBUF_DEBUG logMsg ("mClGet: Invalid cluster type\n", 0, 0, 0, 0, 0, 0);#endif /* NETBUF_DEBUG */ errno = S_netBufLib_CLSIZE_INVALID; goto mClGetError; } reTry: ms = intLock(); /* lock interrupts briefly */ if (pClPool->pClHead == NULL) { /* pool has max clusters, find best fit or close fit */ if (pNetPool->clMask >= CL_LOG2_TO_CL_SIZE(pClPool->clLg2)) { /* first fetch a cluster with a closest bigger size */ bufSize = CL_LOG2_TO_CL_SIZE(pClPool->clLg2); log2Size = pClPool->clLg2; while (bufSize <= CL_SIZE_MAX) { if (pNetPool->clMask & bufSize) { pClPool = pNetPool->clTbl [CL_LOG2_TO_CL_INDEX (log2Size)]; break; } bufSize <<= 1; log2Size ++; } } /* if close fit then find closest lower size */ else if (!bestFit && pNetPool->clMask) { pClPool = pNetPool->clTbl [CL_SIZE_TO_CL_INDEX(pNetPool->clMask)]; } else if (canWait == M_WAIT) /* want for buffers */ { if (_pNetBufCollect) { intUnlock (ms); (*_pNetBufCollect) (pNetPool->pPoolStat); canWait = M_DONTWAIT; goto reTry; } } } if ((pClBuf = pClPool->pClHead)) { /* if this is the last cluster available set the mask */ if ((pClPool->pClHead = pClBuf->pClNext) == NULL) { pNetPool->clMask &= ~(CL_LOG2_TO_CL_SIZE(pClPool->clLg2)); } pClPool->clNumFree--; pClPool->clUsage++; intUnlock (ms); } else { pNetPool->pPoolStat->mDrops++; /* no. times failed to find space */ intUnlock (ms); errnoSet (S_netBufLib_NO_POOL_MEMORY); goto mClGetError; } pMblk->mBlkHdr.mData = (caddr_t) pClBuf; pMblk->mBlkHdr.mFlags |= M_EXT; pClBlk->clNode.pClBuf = (caddr_t) pClBuf; pClBlk->clSize = pClPool->clSize; pClBlk->pClFreeRtn = NULL; pClBlk->clRefCnt = 1; pMblk->pClBlk = pClBlk; return (OK); /* return OK */ mClGetError: if (pClBlk != NULL) _clBlkFree (pClBlk); return (ERROR); /* return ERROR */ }/********************************************************************************* clPoolIdGet - return a pool Id for a given cluster Size** This function returns a poolID for a given cluster Size.* If this returns NULL then the corresponding pool has not been initialized.** RETURNS: CL_POOL_ID or NULL.** NOMANUAL*/LOCAL CL_POOL_ID _clPoolIdGet ( NET_POOL_ID pNetPool, /* pointer to the net pool */ int bufSize, /* size of the buffer */ BOOL bestFit /* TRUE/FALSE */ ) { int log2Size; if (bufSize > pNetPool->clSizeMax) { log2Size = pNetPool->clLg2Max; if (bestFit) return (NULL); } else if (bufSize < pNetPool->clSizeMin) { log2Size = pNetPool->clLg2Min; } else { log2Size = SIZE_TO_LOG2(bufSize); if (bufSize > CL_LOG2_TO_CL_SIZE(log2Size)) log2Size++; } return (pNetPool->clTbl [CL_LOG2_TO_CL_INDEX(log2Size)]); }/********************************************************************************* netBufLibInit - initialize netBufLib** This routine executes during system startup if INCLUDE_NETWORK is defined* when the image is built. It links the network buffer library into the image.** RETURNS: OK or ERROR.**/STATUS netBufLibInit (void) { return (OK); }/********************************************************************************* netPoolInit - initialize a netBufLib-managed memory pool** Call this routine to set up a netBufLib-managed memory* pool. Within this pool, netPoolInit() organizes several sub-pools: one* for `mBlk' structures, one for `clBlk' structures, and as many cluster* sub-pools are there are cluster sizes. As input, this routine expects* the following parameters:* .IP <pNetPool> 15* Expects a NET_POOL_ID that points to a previously allocated NET_POOL* structure. You need not initialize any values in this structure. That* is handled by netPoolInit().* .IP <pMclBlkConfig>* Expects a pointer to a previously allocated and initialized M_CL_CONFIG* structure. Within this structure, you must provide four* values: 'mBlkNum', a count of `mBlk' structures; 'clBlkNum', a count* of `clBlk' structures; 'memArea', a pointer to an area of memory* that can contain all the `mBlk' and `clBlk' structures; and 'memSize', * the size of that memory area. For example, you can set up an M_CL_CONFIG * structure as follows:* .CS* M_CL_CONFIG mClBlkConfig = /@ mBlk, clBlk configuration table @/* {* mBlkNum clBlkNum memArea memSize* ---------- ---- ------- -------* 400, 245, 0xfe000000, 21260* };* .CE* You can * calculate the 'memArea' and 'memSize' values. Such code could first * define a table as shown above, but set both 'memArea' and 'memSize' * as follows:* .CS* mClBlkConfig.memSize = (mClBlkConfig.mBlkNum * (M_BLK_SZ + sizeof(long))) +* (mClBlkConfig.clBlkNum * CL_BLK_SZ);* .CE* You can set the memArea value to a pointer to private memory, or you can* reserve the memory with a call to malloc(). For example:* .CS* mClBlkConfig.memArea = malloc(mClBlkConfig.memSize);* .CE** The netBufLib.h file defines M_BLK_SZ as:* .CS* sizeof(struct mBlk)* .CE* Currently, this evaluates to 32 bytes. Likewise, this file * defines CL_BLK_SZ as:* .CS * sizeof(struct clBlk)* .CE* Currently, this evaluates to 32 bytes. ** When choosing values for 'mBlkNum' and 'clBlkNum', remember that you need * as many `clBlk' structures as you have clusters (data buffers). You also * need at least as many `mBlk' structures as you have `clBlk' structures, but * you will most likely need more. * That is because netBufLib shares buffers by letting multiple `mBlk' * structures join to the same `clBlk' and thus to its underlying cluster. * The `clBlk' keeps a count of the number of `mBlk' structures that * reference it. ** .IP <pClDescTbl>* Expects a pointer to a table of previously allocated and initialized CL_DESC* structures. Each structure in this table describes a single cluster pool.* You need a dedicated cluster pool for each cluster size you want to support.* Within each CL_DESC structure, you must provide four values: 'clusterSize',* the size of a cluster in this cluster pool; 'num', the number of clusters * in this cluster pool; 'memArea', a pointer to an area of memory that can * contain all the clusters; and 'memSize', the size of that memory area.* * Thus, if you need to support six different cluster sizes, this parameter* must point to a table containing six CL_DESC structures. For example,* consider the following:* .CS* CL_DESC clDescTbl [] = /@ cluster descriptor table @/* {* /@* clusterSize num memArea memSize* ---------- ---- ------- -------* @/* {64, 100, 0x10000, 6800},* {128, 50, 0x20000, 6600},* {256, 50, 0x30000, 13000},* {512, 25, 0x40000, 12900},* {1024, 10, 0x50000, 10280},* {2048, 10, 0x60000, 20520}* };* .CE* As with the 'memArea' and 'memSize' members in the M_CL_CONFIG structure,* you can set these members of the CL_DESC structures by calculation after* you create the table. The formula would be as follows:* .CS* clDescTbl[n].memSize = * (clDescTbl[n].num * (clDescTbl[n].clusterSize + sizeof(long)));* .CE* The 'memArea' member can point to a private memory area that you know to be * available for storing clusters, or you can use malloc().* .CS* clDescTbl[n].memArea = malloc( clDescTbl[n].memSize ); * .CE** Valid cluster sizes range from 64 bytes to 65536 bytes. If there are * multiple cluster pools, valid sizes are further restricted to powers of* two (for example, 64, 128, 256, and so on). If there is only one cluster * pool (as is often the case for the memory pool specific to a single * device driver), there is no power of two restriction. Thus, the cluster * can be of any size between 64 bytes and 65536 bytes on 4-byte alignment. A * typical buffer size for Ethernet devices is 1514 bytes. However, because* a cluster size requires a 4-byte alignment, the cluster size for this * Ethernet buffer would have to be increased to at least 1516 bytes.* * .IP <clDescTblNumEnt>* Expects a count of the elements in the CL_DESC table referenced by * the <pClDescTbl> parameter. This is a count of the number of cluster* pools. You can get this value using the NELEMENTS macro defined * in vxWorks.h. For example:* .CS* int clDescTblNumEnt = (NELEMENTS(clDescTbl));* .CE* .IP <pFuncTbl>* Expects a NULL or a pointer to a function table. This table contains * pointers to the functions used to manage the buffers in this memory pool. * Using a NULL for this parameter tells netBufLib to use its default function * table. If you opt for the default function table, every `mBlk' and * every cluster is prepended by a 4-byte header (which is why the size * calculations above for clusters and `mBlk' structures contained an * extra 'sizeof(long)'). However, users need not concern themselves * with this header when accessing these buffers. The returned pointers * from functions such as netClusterGet() return pointers to the start of* data, which is just after the header. * .LP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -