📄 smpktlib.c
字号:
* This routine uses the specified test-and-set function, <tasRoutine>, to* obtain exclusive access to the linked list lock. If the lock cannot* be acquired within the number of tries specified by the smPktTasTries* global variable, this routine will return ERROR.** RETURNS: OK, or ERROR if could not acquire list lock.*/LOCAL STATUS smPktSllGet ( FAST SM_SLL_LIST *listLocalAdrs, /* local addr of packet list */ int baseAddr, /* addr conversion constant */ FUNCPTR tasRoutine, /* test-and-set routine addr */ FUNCPTR tasClearRoutine, /* test-and-set routine addr */ SM_SLL_NODE **pNodeLocalAdrs /* location to put node addr */ ) { int oldLvl; /* saved interrupt level */ FAST SM_SLL_NODE *pNode; /* pointer to node */ /* Take list lock */ if (SM_LOCK_TAKE (&(listLocalAdrs->lock), tasRoutine, smPktTasTries, &oldLvl) != OK) { errno = S_smPktLib_LOCK_TIMEOUT; return (ERROR); /* can't take lock */ } /* Get first node from list, if any */ if ((pNode = (SM_SLL_NODE *) ntohl (listLocalAdrs->head)) != NULL) /* if there really is a node */ { pNode = SM_OFFSET_TO_LOCAL ((int) pNode, baseAddr, SM_SLL_NODE *); /* convert to local address */ listLocalAdrs->head = pNode->next; /* next node (if any) is head */ listLocalAdrs->count = ntohl (listLocalAdrs->count) - 1; if (listLocalAdrs->count <= 0) /* if list now empty */ listLocalAdrs->tail = htonl (NULL); /* clear tail pointer */ listLocalAdrs->count = htonl (listLocalAdrs->count); } /* Release list lock */ SM_LOCK_GIVE (&(listLocalAdrs->lock), tasClearRoutine, oldLvl); /* Pass node address back to caller */ *pNodeLocalAdrs = pNode; /* local node addr, or NULL */ return (OK); }/********************************************************************************* smPktSllPut - add a shared memory node to a singly-linked list** This routine attempts to add a shared memory node to the specified* singly-linked list. The node to be added is identified by <nodeLocalAdrs>.* Unless the list has reached its maximum number of entries, the node* will be added at the tail of the list. The bus address of the node is* used in the list entry.** This routine uses the specified test-and-set function, <tasRoutine>, to* obtain exclusive access to the linked list lock. If the lock cannot* be acquired within the number of tries specified by the smPktTasTries* global variable, this routine will return ERROR.** If the list already contains its maximum number of node entries, this* routine will return ERROR.** If <pListWasEmpty> is non-null and the node is successfully added* to the list, this routine will set the BOOL pointed to by* <pListWasEmpty> to TRUE if there were no previous nodes in the list.** RETURNS: OK, or ERROR if packet ptr is NULL, list full, or could* not acquire list lock.** ERRNO: S_smPktLib_LOCK_TIMEOUT, S_smPktLib_LIST_FULL*/LOCAL STATUS smPktSllPut ( FAST SM_SLL_LIST *listLocalAdrs, /* local addr of packet list */ int base, /* base address */ FUNCPTR tasRoutine, /* test-and-set routine addr */ FUNCPTR tasClearRoutine, /* test-and-set routine addr */ SM_SLL_NODE *nodeLocalAdrs, /* local addr of node */ BOOL * pListWasEmpty /* set to true if adding to * empty list */ ) { int oldLvl; /* saved interrupt level */ FAST int nodeOff; /* pointer to node */ FAST SM_SLL_NODE *tailLocalAdrs; /* pointer to list tail node */ nodeLocalAdrs->next = NULL; /* mark node as end of list */ nodeOff = htonl (SM_LOCAL_TO_OFFSET (nodeLocalAdrs, base)); /* Take list lock */ if (SM_LOCK_TAKE (&(listLocalAdrs->lock), tasRoutine, smPktTasTries, &oldLvl) != OK) { errno = S_smPktLib_LOCK_TIMEOUT; return (ERROR); /* can't take lock */ } /* Add node to list */ if (ntohl (listLocalAdrs->count) >= ntohl (listLocalAdrs->limit)) { SM_LOCK_GIVE (&(listLocalAdrs->lock), tasClearRoutine, oldLvl); errno = S_smPktLib_LIST_FULL; return (ERROR); /* list has max nodes already */ } /* if list previously empty */ if (ntohl (listLocalAdrs->tail) == NULL) { if (pListWasEmpty != NULL) *pListWasEmpty = TRUE; /* node is new head also */ listLocalAdrs->head = nodeOff; } else { if (pListWasEmpty != NULL) *pListWasEmpty = FALSE; tailLocalAdrs = SM_OFFSET_TO_LOCAL (ntohl (listLocalAdrs->tail), base, SM_SLL_NODE *); /* get addr of tail node */ tailLocalAdrs->next = nodeOff; /* link new node to old tail */ } listLocalAdrs->tail = nodeOff; /* node is new tail */ listLocalAdrs->count = ntohl (htonl (listLocalAdrs->count) + 1); /* one more node in list */ /* Release list lock */ SM_LOCK_GIVE (&(listLocalAdrs->lock), tasClearRoutine, oldLvl); return (OK); }/********************************************************************************* smPktDetach - detach CPU from shared memory** This routine ends the "attachment" between the calling CPU and* the shared memory area specified by <pSmPktDesc>. No further shared* memory operations may be performed until a subsequent smPktAttach(2)* is completed.** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_NOT_ATTACHED*/STATUS smPktDetach ( FAST SM_PKT_DESC *pSmPktDesc, /* ptr to shared mem descriptor */ BOOL noFlush /* true if input queue should not * be flushed */ ) { FAST SM_PKT_CPU_DESC * pPktCpuDesc; /* cpu descriptor */ SM_PKT * pPkt; /* pointer to input packet */ FAST SM_DESC * pSmDesc = &pSmPktDesc->smDesc; /* Check that this cpu is connected to shared memory */ if (pSmPktDesc->status != SM_CPU_ATTACHED) { errno = S_smPktLib_NOT_ATTACHED; return (ERROR); /* local cpu is not attached */ } if (smDetach (pSmDesc) == ERROR) return (ERROR); pPktCpuDesc = &((pSmPktDesc->cpuLocalAdrs) [pSmDesc->cpuNum]); /* get addr of cpu descriptor */ pPktCpuDesc->status = htonl (SM_CPU_NOT_ATTACHED);/* mark as not attached */ pSmPktDesc->status = SM_CPU_NOT_ATTACHED; /* also mark sh mem descr */ if (noFlush == FALSE) /* flush input queue */ { FOREVER { if (smPktSllGet (&(pPktCpuDesc->inputList), pSmDesc->base, pSmDesc->tasRoutine, pSmDesc->tasClearRoutine, (SM_SLL_NODE **) &pPkt) != OK) return (ERROR); /* error getting input packet */ if (pPkt == NULL) break; /* no more input packets */ if (smPktSllPut (&(pSmPktDesc->hdrLocalAdrs->freeList), pSmDesc->base, pSmDesc->tasRoutine, pSmDesc->tasClearRoutine, &(pPkt->header.node), NULL) != OK) return (ERROR); /* error adding to free list */ } } return (OK); }/********************************************************************************* smPktInfoGet - get current status information about shared memory** This routine obtains various pieces of information which describe the* current state of the shared memory area specified by <pSmPktDesc>. The* current information is returned in a special data structure, SM_PKT_INFO,* whose address is specified by <pInfo>. The structure must have been* allocated before this routine is called.** RETURNS: OK, or ERROR if this CPU is not attached to shared memory area.** ERRNO: S_smPktLib_NOT_ATTACHED*/STATUS smPktInfoGet ( FAST SM_PKT_DESC * pSmPktDesc, /* shared memory descriptor */ FAST SM_PKT_INFO * pInfo /* info structure to fill */ ) { FAST SM_PKT_MEM_HDR * pHdr; /* shared memory header */ FAST SM_PKT_CPU_DESC * pCpuDesc; /* cpu descriptor */ FAST int ix; /* index variable */ /* Check that this cpu is connected to shared memory */ if (pSmPktDesc->status != SM_CPU_ATTACHED) { errno = S_smPktLib_NOT_ATTACHED; return (ERROR); /* local cpu is not attached */ } if (smInfoGet (&(pSmPktDesc->smDesc), &(pInfo->smInfo)) == ERROR) return (ERROR); /* Get info from shared memory packet header */ pHdr = pSmPktDesc->hdrLocalAdrs; /* get local address of hdr */ pInfo->maxPktBytes = ntohl (pHdr->maxPktBytes);/* max data bytes per pkt */ pInfo->totalPkts = ntohl (pHdr->freeList.limit);/* total number */ pInfo->freePkts = ntohl (pHdr->freeList.count);/* number free */ /* Get count of attached cpu's */ pCpuDesc = pSmPktDesc->cpuLocalAdrs; /* first entry in cpu table */ pInfo->attachedCpus = 0; for (ix = 0; ix < pInfo->smInfo.maxCpus; ix++) { if (ntohl (pCpuDesc->status) == SM_CPU_ATTACHED) pInfo->attachedCpus++; pCpuDesc++; /* next entry */ } return (OK); }/********************************************************************************* smPktCpuInfoGet - get information about a single CPU using shared memory** This routine obtains a variety of information describing the CPU specified* by <cpuNum>. If <cpuNum> is NONE (-1), this routine returns information* about the local (calling) CPU. The information is returned in a special* structure, SM_PKT_CPU_INFO, whose address is specified by <pCpuInfo>. (The* structure must have been allocated before this routine is called.)** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_NOT_ATTACHED*/STATUS smPktCpuInfoGet ( SM_PKT_DESC * pSmPktDesc, /* pkt descriptor */ FAST int cpuNum, /* cpu to get info about */ FAST SM_PKT_CPU_INFO * pCpuInfo /* structure to fill */ ) { FAST SM_PKT_CPU_DESC * pCpuDesc; /* ptr to cpu descriptor */ /* Check that the local cpu is connected to shared memory */ if (pSmPktDesc->status != SM_CPU_ATTACHED) { errno = S_smPktLib_NOT_ATTACHED; return (ERROR); /* local cpu is not attached */ } if (cpuNum == NONE) cpuNum = pSmPktDesc->smDesc.cpuNum; if (smCpuInfoGet (&(pSmPktDesc->smDesc), cpuNum, &(pCpuInfo->smCpuInfo)) == ERROR) return (ERROR); /* get address of cpu descr */ pCpuDesc = &(pSmPktDesc->cpuLocalAdrs [cpuNum]); pCpuInfo->status = ntohl (pCpuDesc->status);/* attached or not attached */ /* Get packet counts */ pCpuInfo->inputPkts = ntohl (pCpuDesc->inputList.count); /* current pkts in input queue*/ pCpuInfo->maxInputPkts = ntohl (pCpuDesc->inputList.limit); /* max pkts allowed in queue */ /* XXX - free list counts - for future use when cpu's have free lists... * * pCpuInfo->freePkts = ntohl (pCpuDesc->freeList.count); * pCpuInfo->totalPkts = ntohl (pCpuDesc->freeList.limit); * */ pCpuInfo->freePkts = 0; /* (future use) */ return (OK); }/********************************************************************************* smPktBeat - increment packet heartbeat in shared memory anchor** This routine increments the shared memory packet "heartbeat". The heartbeat* is used by processors using the shared memory packet library to * confirm that the shared memory network is active. The shared memory * area whose heartbeat is to be incremented is specifed by <pAnchor>, which * is the address of a shared memory anchor.** This routine should be called periodically by the master CPU.** RETURNS: N/A*/void smPktBeat ( SM_PKT_MEM_HDR * pSmPktHdr /* ptr to shared mem anchor */ ) { /* Increment heartbeat */ pSmPktHdr->heartBeat = htonl (ntohl (pSmPktHdr->heartBeat) + 1); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -