⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smpktlib.c

📁 VxWorks操作系统内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
* <pPkt> was either sent or freed before this routine returned, and no* further action is required.)** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_NOT_ATTACHED, S_smPktLib_INVALID_PACKET,* S_smPktLib_PACKET_TOO_BIG, S_smPktLib_INVALID_CPU_NUMBER,* S_smPktLib_DEST_NOT_ATTACHED, S_smPktLib_INCOMPLETE_BROADCAST* */STATUS smPktSend    (    SM_PKT_DESC *	pSmPktDesc,	/* ptr to shared memory descriptor */    SM_PKT *		pPkt,		/* local addr of packet to be sent */    int			destCpu		/* destination cpu number */    )    {    SM_PKT volatile *		pPktv = (SM_PKT volatile *) pPkt;    STATUS			status;		/* return status */    SM_PKT_CPU_DESC volatile *	pPktCpuDesc;	/* destination cpu pkt descr*/    SM_CPU_DESC volatile *	pCpuDesc;	/* destination cpu descr*/    int				i;    BOOL			listWasEmpty;	/* list empty */    SM_DESC *			pSmDesc = (SM_DESC *) &pSmPktDesc->smDesc;    int                         tmp;            /* temp storage */    /* 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 */	}    /* Check for null pointer */    if (pPkt == NULL)	{	errno = S_smPktLib_INVALID_PACKET;	return (ERROR);				/* null packet address */	}    /* Enforce max data length */    CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */    tmp = pPktv->header.nBytes;                 /* BRIDGE FLUSH  [SPR 68334] */    if (pPktv->header.nBytes > pSmPktDesc->maxPktBytes)	{	errno = S_smPktLib_PACKET_TOO_BIG;	return (ERROR);				/* too much data ! */	}						/* byte swap info */    pPktv->header.nBytes = htonl (pPktv->header.nBytes);    /* Call special routine if doing broadcast */    if (destCpu == SM_BROADCAST)		/* if sending to all cpu's */	return (smPktBroadcast (pSmPktDesc, pPkt));    /* Make sure destination cpu is valid and attached */    if (destCpu < 0  ||  destCpu >= pSmDesc->maxCpus)        {        errno = S_smPktLib_INVALID_CPU_NUMBER;        return (ERROR);				/* cpu number out of range */        }    pPktCpuDesc = &((pSmPktDesc->cpuLocalAdrs) [destCpu]);    pCpuDesc    = &((pSmDesc->cpuTblLocalAdrs) [destCpu]);    						/* get addr of cpu descriptor */    if (ntohl (pPktCpuDesc->status) != SM_CPU_ATTACHED)        {        errno = S_smPktLib_DEST_NOT_ATTACHED;        return (ERROR);				/* dest cpu is not attached */        }    /* Complete packet header info */    pPktv->header.srcCpu   = htonl (pSmDesc->cpuNum);	/* source cpu */    CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */    i = pPktv->header.srcCpu;			/* BRIDGE FLUSH  [SPR 68334] */    /* Add this packet to destination cpu's input list */    status = smPktSllPut (&(pPktCpuDesc->inputList), pSmDesc->base,			  pSmDesc->tasRoutine, pSmDesc->tasClearRoutine, 			  &(pPktv->header.node), &listWasEmpty);    if ((status == OK) && (listWasEmpty) && (destCpu != pSmDesc->cpuNum))        {	/* Interrupt destination cpu */	if ((status = smUtilIntGen ((SM_CPU_DESC *)pCpuDesc, destCpu)) != OK)            {            /*             * Packet put in input list but interrupt failed.             * This is not an error.  It means another interrupt will have             * to be sent after a short delay.  This will be repeated until             * the interrupt is successful or a timeout occurs.             * (See SPR 25341, 33771)             */            for (i = smPktMaxIntRetries; (status != OK) && (i > 0); --i)                {                taskDelay (1);                status = smUtilIntGen ((SM_CPU_DESC *)pCpuDesc, destCpu);                }            /* time out on interrupt generation */            if (status != OK)                {                /* packet still in input list so do NOT delete it */                errno = S_smPktLib_INCOMPLETE_BROADCAST;                }            }        }    return (status);    }/******************************************************************************** smPktBroadcast - send packet data to all attached CPU's via shared memory** This sends a copy of the packet specified by <pPkt> to all CPU's attached* to the specified shared memory area (except the sending CPU).** This routine attempts to obtain a new packet for each destination CPU,* copying the packet contents to each newly-acquired packet.  If no new* packets are available, this routine will go ahead and send the original* packet to the next destination CPU.  If there are still more destinations* after the original has been sent, an error (S_smPktLib_INCOMPLETE_BROADCAST)* is returned.  This same error is returned if one or more destinations did* not receive the broadcast due to other problems (e.g. the input queue for* a destination CPU was full).** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_INCOMPLETE_BROADCAST*/LOCAL STATUS smPktBroadcast    (    SM_PKT_DESC *	pSmPktDesc,	/* sh mem pkt descriptor */    SM_PKT volatile *	pPktOrig	/* ptr to original packet */    )    {    STATUS			status;		/* return status */    SM_PKT volatile *		pPkt;		/* ptr to packet being sent */    SM_PKT volatile *		pPktNew;	/* ptr to newly obtained pkt */    int				destCpu;	/* destination cpu number */    SM_CPU_DESC volatile *	pCpuDesc;	/* destination cpu descriptor*/    SM_PKT_CPU_DESC volatile *	pPktCpuDesc;	/* destination cpu descriptor*/    BOOL			destMissed;	/* TRUE if a dest was missed */    BOOL			listWasEmpty;	/* list added to was empty */    SM_DESC *			pSmDesc = (SM_DESC *) &pSmPktDesc->smDesc;    pCpuDesc = pSmDesc->cpuTblLocalAdrs;    pPktCpuDesc = pSmPktDesc->cpuLocalAdrs;    destMissed = FALSE;				/* no destinations missed yet */    /* Send copy of packet to each attached cpu (except self) */    for (destCpu = 0;  destCpu < pSmDesc->maxCpus;  destCpu++)        {        if ((ntohl (pPktCpuDesc->status) == SM_CPU_ATTACHED)  &&	    (destCpu != pSmDesc->cpuNum))    	    {    	    if (pPktOrig == NULL)		/* if original already used */    	    	{    	    	destMissed = TRUE;		/* weren't enough free packets*/    	    	break;				/* can't do any more */    	    	}	    /* Get new packet */    	    if (smPktFreeGet (pSmPktDesc, (SM_PKT **)&pPktNew) != OK)    	    	return (ERROR);			/* error getting packet */    	    if (pPktNew != NULL)		/* if a new pkt was obtained */    	    	{		pPkt = pPktNew;			/* it is the packet to send */    	    	pPkt->header.type   = pPktOrig->header.type;						/* copy packet type */    	    	pPkt->header.nBytes = pPktOrig->header.nBytes;						/* copy byte count */    	    	bcopy ((char *)pPktOrig->data, (char *)pPkt->data,    	    	       ntohl (pPkt->header.nBytes));    						/* copy packet data */    	    	}    	    else				/* if could not get new pkt */    	    	{    	    	pPkt = pPktOrig;		/*  set up to send original */    	    	}    	    pPkt->header.srcCpu  = htonl (pSmDesc->cpuNum);						/* source cpu number */    	    /* Send packet */            status = smPktSllPut (&(pPktCpuDesc->inputList), pSmDesc->base, 				  pSmDesc->tasRoutine, pSmDesc->tasClearRoutine,    			          &(pPkt->header.node), &listWasEmpty);            if ((status == OK) && listWasEmpty)	/* if list previously empty */        	{		/* Interrupt destination CPU */        	if (smUtilIntGen ((SM_CPU_DESC *)pCpuDesc, destCpu) != OK)		    {		    destMissed = TRUE;	/* a destination was missed */		    }        	}    	    else if (status == ERROR)		/* if error sending pkt */		{		/*		 *  NOTE: We do not return just because an error occurred.		 *        The destination cpu's input list may simply have been		 *        full, or some other error may have occurred which		 *	  will not affect the remaining destinations.  When		 *	  this routine ultimately returns, the broadcast will		 *	  be reported as having been incomplete.		 */		destMissed = TRUE;		/* a destination was missed */		if (pPkt != pPktOrig)		/* if pkt was not the original*/        	    {    	    	    /* New packet not sent - return to free pool */        	    if (smPktFreePut (pSmPktDesc, (SM_PKT *)pPkt) != OK)    		    	return (ERROR);		/* could not return packet */		    }    	    	}    	    if (pPkt == pPktOrig  &&  status != ERROR)    	    	{				/* if original actually sent */    	    	pPktOrig = NULL;		/*  clear pointer to orig pkt */    	    	}    	    }  /* end if (attached) */        pCpuDesc++;				/* next cpu descriptor */	pPktCpuDesc++;        }  /* end for */    /* Free original packet if it wasn't sent during broadcast */    if (pPktOrig != NULL)        {        if (smPktFreePut (pSmPktDesc, (SM_PKT *)pPktOrig) != OK)    	    return (ERROR);			/* could not free packet */        }    if (destMissed)				/* if a destination was missed*/	{    	errno = S_smPktLib_INCOMPLETE_BROADCAST;    	return (ERROR);				/* broadcast not complete */    	}    else	{    	return (OK);	}    }/******************************************************************************** smPktFreePut - return a shared memory packet to free list** This routine frees a shared memory packet.  The packet is placed* on the global free packet list.  No modification of the packet* contents is performed.** The address of the packet to be returned is specified in <pPkt>.** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_NOT_ATTACHED, S_smPktLib_INVALID_PACKET*/STATUS smPktFreePut    (    SM_PKT_DESC	*	pSmPktDesc,	/* ptr to shared memory descriptor */    SM_PKT *		pPkt		/* addr of packet to be returned */    )    {    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 */	}    /* Check for null pointer */    if (pPkt == NULL)	{	errno = S_smPktLib_INVALID_PACKET;	return (ERROR);				/* null packet address */	}    /* Return packet to free list */    return (smPktSllPut (&(pSmPktDesc->hdrLocalAdrs->freeList), pSmDesc->base, 			 pSmDesc->tasRoutine, pSmDesc->tasClearRoutine, 			 &(pPkt->header.node), NULL));    }/******************************************************************************** smPktRecv - receive a packet sent via shared memory** This routine receives a shared memory packet which was queued to this CPU.* This routine should be called in response to an interrupt which notifies* this CPU of the packet, or it can be called repeatedly in a polling* fashion to check for input packets.  (NOTE: An interrupt will be generated* only if there previously was not a packet queued to this CPU.  Therefore,* after a packet is received, this routine should be called again to check* for more packets.)** Upon return, the location indicated by <ppPkt> will contain the address* of the received packet, or NULL if there was none.** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_NOT_ATTACHED*/STATUS smPktRecv    (    SM_PKT_DESC	*	pSmPktDesc,	/* shared memory descriptor */    SM_PKT **		ppPkt		/* location to put pkt addr */    )    {    SM_PKT_CPU_DESC volatile *	pPktCpuDesc;    STATUS			status;    SM_DESC *			pSmDesc = (SM_DESC *) &pSmPktDesc->smDesc;    int                         tmp;         /* temp storage */    /* 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 */	}    /* Get packet (if any) from input list */    pPktCpuDesc = &((pSmPktDesc->cpuLocalAdrs) [pSmDesc->cpuNum]);    						/* get addr of cpu descriptor */    status = smPktSllGet (&(pPktCpuDesc->inputList), pSmDesc->base,    		      	  pSmDesc->tasRoutine, pSmDesc->tasClearRoutine, 			  (SM_SLL_NODE **) ppPkt);    if ((status == OK) && (*ppPkt != NULL))	{	(*ppPkt)->header.nBytes = ntohl ((*ppPkt)->header.nBytes);	(*ppPkt)->header.srcCpu = ntohl ((*ppPkt)->header.srcCpu);        CACHE_PIPE_FLUSH ();                    /* CACHE FLUSH   [SPR 68334] */        tmp = (*ppPkt)->header.srcCpu;		/* BRIDGE FLUSH  [SPR 68334] */	}    return (status);    }/******************************************************************************** smPktSllGet - get a shared memory node from a singly-linked list** This routine attempts to obtain a shared memory node from the* specified singly-linked list of nodes.  If a node is available,* the local address (for this CPU) of the node is placed in the* location specified by <pNodeLocalAdrs>.  If no node was available* from the list, a NULL is placed in this location.** 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.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -