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

📄 smpktlib.c

📁 VxWorks操作系统内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif	/* __STDC__ *//******************************************************************************** smPktSetup - set up shared memory (master CPU only)** This routine should be called only by the master CPU using shared* memory.  It initializes the specified memory area for use by the* shared memory protocol.** After the shared memory has been initialized, this and other CPU's* may initialize a shared memory packet descriptor to it, using smPktInit(),* and then attach to the shared memory area, using smPktAttach().** The <anchorLocalAdrs> parameter is the memory address by which the master* CPU accesses the shared memory anchor.** The <smLocalAdrs> parameter is the memory address by which the master* CPU accesses the actual shared memory region to be initialized.** The <smSize> parameter is the size, in bytes, of the shared memory* region.** The shared memory routines must be able to obtain exclusive access to* shared data structures.  To allow this, a test-and-set operation is* used.  It is preferable to use a genuine test-and-set instruction, if* the hardware being used permits this.  If this is not possible, smUtilLib* provides a software emulation of test-and-set.  The <tasType> parameter* specifies what method of test-and-set is to be used.** The <maxCpus> parameter specifies the maximum number of CPU's which may* use the shared memory region.** The <maxPktBytes> parameter specifies the size, in bytes, of the data* buffer in shared memory packets.  This is the largest amount of data* which may be sent in a single packet.  If this value is not an exact* multiple of 4 bytes, it will be rounded up to the next multiple of 4.** INTERNAL* The first item in the shared memory area is the shared memory packet* header (SM_PKT_MEM_HDR).  Following this is an array of CPU * descriptors (SM_PKT_CPU_DESC); this table contains one CPU descriptor * for each possible CPU, as specified by <maxCpus>.* The shared memory area following the cpu table is allocated to the global* list of free packets (SM_PKT), used for sending data between CPU's.  Note* that the shared memory anchor is NOT part of the regular shared memory area.** Since the size of each data packet is not pre-determined, the actual size* is calculated based on the size of the (fixed) packet header and the* data buffer size, specified by <maxPktBytes>.** The standard smPktSllPut routine is used to build the free packet list.* The software test-and-set routine is always used, regardless of the* definition of <tasType>, because no hardware TAS routine has been supplied* yet. (That is done during smPktAttach.)  Use of any TAS method at this* stage is mainly a formality, since no other CPU's are able to attach to* the shared memory region.** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_SHARED_MEM_TOO_SMALL, S_smPktLib_MEMORY_ERROR** INTERNAL:  This routine and smObjSetup can not be called at the same time!!!*/STATUS smPktSetup    (    SM_ANCHOR * anchorLocalAdrs, 	/* local addr of anchor */    char * 	smLocalAdrs,		/* local addr of sh mem area */    int		smSize,			/* size of shared memory area */    int		tasType, 		/* test and set type */    int		maxCpus,		/* max number of cpus */    int		maxPktBytes		/* max bytes of packet data */    )    {    SM_ANCHOR volatile * pAnchorv = (SM_ANCHOR volatile *) anchorLocalAdrs;    SM_PKT_MEM_HDR volatile *	smPktHdr;	/* local addr of sh mem hdr */    int				pktSize;	/* actual size of pkt */    STATUS			status;	 	/* return status */    SM_PKT volatile *		pPkt;		/* local addr of free packet */    int				memLeft;    char			temp = 0;    int				base = (int) anchorLocalAdrs;    int 			bytesUsed = 0;    int                         tmp;            /* temp storage */    /* set up default values for parameters */    smSize 	= (smSize == 0)  ?  smPktMemSizeDefault : smSize;    maxCpus	= (maxCpus == 0) ?  smPktMaxCpusDefault : maxCpus;    maxPktBytes = (maxPktBytes == 0) ?  smPktMaxBytesDefault : maxPktBytes;    maxPktBytes = ((maxPktBytes + sizeof (int) - 1) / sizeof (int)) *                  sizeof (int);                 /* round up buf to int mult */    pktSize = (sizeof (SM_PKT_HDR) + maxPktBytes);                                                /* pkt size incl data buffer */    if (smSetup (anchorLocalAdrs, smLocalAdrs, tasType, maxCpus,		 &bytesUsed) == ERROR)       return (ERROR);    smSize 	-= bytesUsed;    smLocalAdrs += bytesUsed;    /*     * Check that shared mem size is big enough to contain:     * the shared memory packet header, the shared memory packet     * cpu descriptors and 1 pkt per cpu.     */    if (smSize < (sizeof (SM_PKT_MEM_HDR) +	(maxCpus * sizeof (SM_PKT_CPU_DESC)) + (maxCpus * pktSize)))        {        errno = S_smPktLib_SHARED_MEM_TOO_SMALL;        return (ERROR);                         /* not enough sh mem */        }    /* Probe beginning and end of shared memory */    if ((smUtilMemProbe (smLocalAdrs , VX_WRITE, sizeof (char), &temp) != OK) ||        (smUtilMemProbe (smLocalAdrs + smSize - 1, VX_WRITE, sizeof (char),			 &temp) != OK))        {        errno = S_smPktLib_MEMORY_ERROR;        return (ERROR);        }    /* Clear shared memory */    bzero (smLocalAdrs, smSize);    /* Fill in header */    smPktHdr = (SM_PKT_MEM_HDR volatile *) smLocalAdrs;    smPktHdr->maxPktBytes = htonl (maxPktBytes);/* max size of pkt data buf */    smPktHdr->pktCpuTbl   = htonl (SM_LOCAL_TO_OFFSET ((char *) smPktHdr +				   		       sizeof (SM_PKT_MEM_HDR),						       base));    pAnchorv->smPktHeader = htonl (SM_LOCAL_TO_OFFSET (smLocalAdrs, base));    /* Set up list of free packets */    pPkt = (SM_PKT *) (smLocalAdrs + sizeof (SM_PKT_MEM_HDR) +		      (maxCpus * sizeof (SM_PKT_CPU_DESC)));						/* calculate addr of 1st pkt */    memLeft = smSize - ((int) ((char *) pPkt - smLocalAdrs));						/* calculate remaining sh mem */    while (memLeft >= pktSize)	{	/* allow one more in free list*/	smPktHdr->freeList.limit = htonl (ntohl (smPktHdr->freeList.limit) +1);	/* Add packet to list, always use software test-and-set emulation */	status = smPktSllPut (&(smPktHdr->freeList), base, smUtilSoftTas, NULL,			      &(pPkt->header.node), NULL);	if (status == ERROR)	    {	    smPktHdr->freeList.limit = htonl (ntohl (smPktHdr->freeList.limit)	                                      - 1);	    return (ERROR);			/* error adding to free list */	    }	pPkt = (SM_PKT *) ((char *) pPkt + pktSize);/* advance pkt pointer */	memLeft -= pktSize;			/* decrease mem remaining */	}    CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */    tmp = smPktHdr->freeList.limit;             /* BRIDGE FLUSH  [SPR 68334] */    return (OK);				/* shared mem init complete */    }/******************************************************************************** smPktInit - initialize shared memory packet descriptor** This routine initializes a shared memory packet descriptor.  The descriptor* must have been previously allocated (generally in the CPU's local* memory).  Once the descriptor has been initialized by this routine,* the CPU may attach itself to the shared memory area by calling* smPktAttach().** Only the shared memory descriptor itself is modified by this routine.* No structures in shared memory are affected.** The <pSmPktDesc> paramter is the address of the shared memory packet * descriptor which is to be initialized; this structure must have * already been allocated before smPktInit is called.** The <anchorLocalAdrs> parameter is the memory address by which the local* CPU may access the shared memory anchor.  This address may vary for* different CPU's because of address offsets (particularly if the anchor is* located in one CPU's dual-ported memory).** The <maxInputPkts> parameter specifies the maximum number of incoming* shared memory packets which may be queued to this CPU at one time.  If* a remote CPU attempts to send more packets after this limit is reached,* an error will be returned to the remote CPU.** The <ticksPerBeat> parameter specifies the frequency of the shared memory* heartbeat.  The frequency is expressed in terms of how many CPU* ticks on the local CPU correspond to one heartbeat period.** The <intType>, <intArg1>, <intArg2>, and <intArg3> parameters allow a* CPU to announce the method by which it is to be notified of input packets* which have been queued to it.  Once this CPU has attached to the shared* memory region, other CPU's will be able to determine these interrupt* parameters by calling smPktCpuInfoGet().  The following interrupt * methods are currently recognized by this library: SM_INT_MAILBOX, * SM_INT_BUS, SM_INT_NONE, and SM_INT_USER .** RETURNS: N/A*/void smPktInit    (    SM_PKT_DESC *	pSmPktDesc,         /* ptr to sh mem packet descr */    SM_ANCHOR *		anchorLocalAdrs,    /* local addr of sh mem anchor*/    int                 maxInputPkts,       /* max queued packets allowed */    int                 ticksPerBeat,       /* cpu ticks per heartbeat */    int                 intType,            /* interrupt method */    int                 intArg1,            /* interrupt argument #1 */    int                 intArg2,            /* interrupt argument #2 */    int                 intArg3             /* interrupt argument #3 */    )    {    if (pSmPktDesc == NULL)        return;                                 /* don't use null ptr */    bzero ((char *) pSmPktDesc, sizeof (SM_PKT_DESC));    smInit (&pSmPktDesc->smDesc, anchorLocalAdrs, ticksPerBeat, intType,	    intArg1, intArg2, intArg3);    pSmPktDesc->maxInputPkts  = (maxInputPkts == 0) ? smPktMaxInputDefault :				   		      maxInputPkts;    pSmPktDesc->status        = SM_CPU_NOT_ATTACHED;    /* initial status */    }/******************************************************************************** smPktAttach - attach to shared memory** This routine "attaches" the local CPU to a shared memory area.  The* shared memory area is identified by the shared memory packet descriptor* whose address specified by <pSmPktDesc>.  The descriptor must have* already been initialized by calling smPktInit().** This routine will complete the attach process only if and when the* shared memory has been initialized by the master CPU.  To determine* this, the shared memory anchor is checked for the proper value* (SM_READY_VALUE) in the anchor's ready-value field and a check is made for* an active heartbeat.  This repeated checking continues until either * the ready-value and heartbeat have been verified or a timeout limit * is reached.  If the shared memory is not recognized as active within * the timeout period, this routine returns an error (S_smPktLib_DOWN).** The attachment to shared memory may be ended by calling smPktDetach().** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_DOWN** SEE ALSO: smPktInit()*/STATUS smPktAttach    (    SM_PKT_DESC	*	pSmPktDesc	/* packet descriptor */    )    {    SM_PKT_MEM_HDR volatile *	pHdr;		/* sm pkt header */    SM_PKT_CPU_DESC volatile *	pPktDesc;	/* pkt cpu descriptor */    int				cpuNum;		/* this cpu's number */    SM_ANCHOR volatile *	pAnchor;	/* anchor */    int				beatsToWait;    SM_DESC *			pSmDesc = (SM_DESC *) &pSmPktDesc->smDesc;    cpuNum  = pSmDesc->cpuNum;    pAnchor = pSmDesc->anchorLocalAdrs;    /* Check that shared memory is initialized and running */    /*     * XXX master CPU should only wait DEFAULT_BEATS_TO_WAIT but we don't     * know who the master is unless we look in the anchor.  The anchor may     * not be mapped onto the bus, and we will blow up with a BERR if we     * poke around.  So we just wait a long time, even if we are the master.     * This could be fixed by listing the SM master and local processor     * numbers in the packet descriptor so that the two could be compared.     * If equal, we would be the master and no waiting would be necessary.     */    beatsToWait = DEFAULT_ALIVE_TIMEOUT;    if (smIsAlive ((SM_ANCHOR *)pAnchor, (int *)&(pAnchor->smPktHeader),                   pSmDesc->base, beatsToWait, pSmDesc->ticksPerBeat) == FALSE)        {        errno = S_smPktLib_DOWN;        return (ERROR);                         /* sh memory not active */        }    if (smAttach (pSmDesc) == ERROR)	return (ERROR);    /* Get local address for shared mem packet header */    pHdr = SM_OFFSET_TO_LOCAL (ntohl (pAnchor->smPktHeader), pSmDesc->base, 			       SM_PKT_MEM_HDR volatile *);    pSmPktDesc->hdrLocalAdrs = (SM_PKT_MEM_HDR *) pHdr;    pSmPktDesc->maxPktBytes  = ntohl (pHdr->maxPktBytes);    pSmPktDesc->cpuLocalAdrs = SM_OFFSET_TO_LOCAL (ntohl (pHdr->pktCpuTbl),				 	    	   pSmDesc->base,					    	   SM_PKT_CPU_DESC *);    pPktDesc = &((pSmPktDesc->cpuLocalAdrs) [cpuNum]);						/* calculate addr of cpu desc						 * in global table.						 */    pPktDesc->inputList.limit = htonl (pSmPktDesc->maxInputPkts);						/* max queued count */    pPktDesc->status  = htonl (SM_CPU_ATTACHED);/* mark this cpu as attached */    pSmPktDesc->status = SM_CPU_ATTACHED;	/* also mark sh mem descr */    CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */    cpuNum = pPktDesc->status;			/* BRIDGE FLUSH  [SPR 68334] */    return (OK);				/* attach complete */    }/******************************************************************************** smPktFreeGet - get a shared memory packet from free list** This routine obtains a shared memory packet.  The packet is taken* from the global free packet list.  No initialization of the packet* contents is performed.** The address of the obtained packet is placed in the location specified* by <ppPkt>.  If there were no free packets available, this value will* be NULL.** RETURNS: OK, or ERROR.** ERRNO: S_smPktLib_NOT_ATTACHED*/STATUS smPktFreeGet    (    SM_PKT_DESC *	pSmPktDesc,	/* ptr to shared memory descriptor */    SM_PKT **		ppPkt 		/* location to put packet address */    )    {    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 */	}    /* Get packet from free list */    return (smPktSllGet (&(pSmPktDesc->hdrLocalAdrs->freeList),			 pSmDesc->base, pSmDesc->tasRoutine,			 pSmDesc->tasClearRoutine, (SM_SLL_NODE **) ppPkt));    }/******************************************************************************** smPktSend - send a packet via shared memory** This routine queues a packet (previously acquired via smPktFreeGet)* to be received by another CPU.  If the input list for the destination* CPU was previously empty and the destination has not specified polling * as its interrupt type, this routine will interrupt the destination CPU. ** If the specified <destCpu> is SM_BROADCAST, a copy of the packet will* be sent to each CPU which is attached to the shared memory area (except* the sender CPU).  If there are not enough free packets to send a copy* to each cpu, or if errors occur when sending to one or more destinations,* an error (S_smPktLib_INCOMPLETE_BROADCAST) is returned.** If ERROR is returned and errno equals S_smPktLib_INCOMPLETE_BROADCAST,* the original packet, <pPkt>, was sent to an attached CPU and does not* have to be freed.  A return code of ERROR combined with any other value* of errno indicates that <pPkt> was NOT sent and should be explicitly* freed using smPktFreePut().  (A return value of OK indicates that

⌨️ 快捷键说明

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