📄 smobjlib.c
字号:
** This routine will complete the attach process only if and when the shared* memory has been initialized by the master CPU. If the shared memory is* not recognized as active within the timeout period (10 minutes), this* routine returns ERROR.** The smObjAttach() routine connects the shared memory objects handler to the* shared memory interrupt. Note that this interrupt may be shared between* the shared memory network driver and the shared memory objects facility* when both are used at the same time.** WARNING:* Once a CPU has attached itself to the shared memory objects facility, * it cannot be detached. Since the shared memory network driver and * the shared memory objects facility use the same low-level attaching* mechanism, a CPU cannot be detached from a shared memory network driver* if the CPU also uses shared memory objects.** AVAILABILITY* This routine is distributed as a component of the unbundled shared memory* objects support option, VxMP.* * RETURNS:* OK, or ERROR if the shared memory objects facility is not active* or the number of CPUs exceeds the maximum.** ERRNO:* S_smLib_INVALID_CPU_NUMBER** SEE ALSO: smObjSetup(), smObjInit()*/STATUS smObjAttach ( SM_OBJ_DESC * pSmObjDesc /* pointer to shared memory descriptor */ ) { SM_OBJ_CPU_INFO * pSmObjCpuInfo; /* cpu info structure to fill */ SM_OBJ_CPU_DESC * pObjDesc; /* pointer to smObj CPU descriptor */ SM_ANCHOR * pAnchor; /* pointer to shared memory anchor */ int cpuNum; /* this CPU number */ int beatsToWait; /* heart beat period */ int tmp; /* temp storage */ cpuNum = pSmObjDesc->smDesc.cpuNum; pAnchor = pSmObjDesc->smDesc.anchorLocalAdrs; /* Check that shared memory is initialized and running */ beatsToWait = (cpuNum == SM_MASTER) ? DEFAULT_BEATS_TO_WAIT : DEFAULT_ALIVE_TIMEOUT; if (smIsAlive (pAnchor, &(pAnchor->smObjHeader), pSmObjDesc->smDesc.base, beatsToWait, pSmObjDesc->smDesc.ticksPerBeat) == FALSE) { return (ERROR); /* sh memory not active */ } /* generic shared memory attach */ if (smAttach (&pSmObjDesc->smDesc) == ERROR) { return (ERROR); } /* set offset to access shared objects */ localToGlobalOffset = (int) pSmObjDesc->smDesc.anchorLocalAdrs; smObjPoolMinusOne = localToGlobalOffset - 1; /* get local address of shared memory header */ pSmObjHdr = (SM_OBJ_MEM_HDR volatile *) GLOB_TO_LOC_ADRS(\ ntohl(pAnchor->smObjHeader)); pSmObjDesc->hdrLocalAdrs = (SM_OBJ_MEM_HDR *) pSmObjHdr; pSmObjDesc->cpuLocalAdrs = (SM_OBJ_CPU_DESC *) GLOB_TO_LOC_ADRS (ntohl (pSmObjHdr->objCpuTbl)); /* initialize shared TCB partition id and free routines pointer */ smTcbPartId = (SM_FIX_BLK_PART_ID) (LOC_TO_GLOB_ADRS((&pSmObjHdr->smTcbPart))); smObjTcbFreeRtn = (FUNCPTR) smObjTcbFree; smObjTcbFreeFailRtn = (FUNCPTR) smObjTcbFreeLogMsg; /* set global name database pointer */ pSmNameDb = &pSmObjHdr->nameDtb; /* get name database header */ /* initialize windDelete failure notification routine pointer */ smObjTaskDeleteFailRtn = (FUNCPTR) smObjTimeoutLogMsg; /* get local event Q pointer */ pSmObjCpuInfo = (SM_OBJ_CPU_INFO *) malloc (sizeof (SM_OBJ_CPU_INFO)); bzero ((char *) pSmObjCpuInfo, sizeof (SM_OBJ_CPU_INFO)); smObjCpuInfoGet (pSmObjDesc, NONE, pSmObjCpuInfo); pLocalEventQ = pSmObjCpuInfo->pCpuEventQ; /* clear cpu notification info cache table */ bzero ((char *) smObjCpuInfoTbl, sizeof (SM_OBJ_CPU_INFO) * SM_OBJ_MAX_CPU); /* connect the shared memory objects interrupt handler */ if (smUtilIntConnect (HIGH_PRIORITY, (FUNCPTR) smObjNotifyHandler, 0, pSmObjDesc->smDesc.intType, pSmObjDesc->smDesc.intArg1, pSmObjDesc->smDesc.intArg2, pSmObjDesc->smDesc.intArg3) == ERROR) { return (ERROR); } /* calculate addr of cpu desc in global table */ pObjDesc = &((pSmObjDesc->cpuLocalAdrs) [smObjProcNum]); pObjDesc->status = htonl (SM_CPU_ATTACHED); /* mark this cpu as attached */ pSmObjDesc->status = SM_CPU_ATTACHED; /* also mark sh mem descr */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ tmp = pObjDesc->status; /* BRIDGE FLUSH [SPR 68334] */ return (OK); }/******************************************************************************** smObjDetach - detach CPU from shared memory objects facility** This routine ends the "attachment" between the calling CPU and* the shared memory objects facility. ** RETURNS: OK, or ERROR.** INTERNAL* Detaching a CPU that uses shared memory objects is not possible* as smObj are implemented now. Indeed, if a CPU has a task pended* on a shared semaphore, there is a shared TCB attached to the semaphore** NOMANUAL*/STATUS smObjDetach ( SM_DESC * pSmObjDesc /* ptr to shared mem object descriptor */ ) { if (pSmObjDesc == NULL) { return (ERROR); } /* PME for now no detachment from shared memory objects available */ return (ERROR); }/******************************************************************************** smObjEventSend - send one or more events to remote CPU** This routine notifies one or more shared memory events to a remote CPU.* Notification informations are stored in the shared memory objects task* control block added to <pEventList> list. The last parameter <destCpu>* contains the processor number to which events are sent.** Events are shared TCB of tasks to be added to the ready queue.** A spin-lock mechanism is used to prevent more than one processor to add * events to the same processor event queue at the same time.** In order to reduce bus traffic and interrupt number, the destination CPU * is interrupted only if its event queue was previously empty. ** This routine uses smMemIntGenFunc() to interrupt the destination CPU.** RETURNS: OK, or ERROR if cannot obtain access to CPU event queue.** ERRNO:* S_smObjLib_LOCK_TIMEOUT** NOMANUAL*/STATUS smObjEventSend ( SM_DL_LIST * pEventList, /* list of events */ UINT32 destCpu ) { SM_OBJ_EVENT_Q * pDestCpuEventQ; /* remote CPU event queue */ BOOL destEventQWasEmpty; int level; /* * Cache eventQ and notification informations if this is * the first time events are send to destCpu. */ if (!smObjCpuInfoTbl [destCpu].cached) { smObjCpuInfoGet (&smObjDesc, destCpu, &smObjCpuInfoTbl [destCpu]); smObjCpuInfoTbl[destCpu].cached = TRUE; } pDestCpuEventQ = smObjCpuInfoTbl [destCpu].pCpuEventQ; /* ENTER LOCKED SECTION */ if (SM_OBJ_LOCK_TAKE (&pDestCpuEventQ->lock, &level) != OK) { smObjTimeoutLogMsg ("smObjEventSend", (char *) &pDestCpuEventQ->lock); return (ERROR); /* can't take lock */ } destEventQWasEmpty = SM_DL_EMPTY (&pDestCpuEventQ->eventList); /* add shared TCBs to event queue */ smDllConcat (&pDestCpuEventQ->eventList, pEventList); /* EXIT LOCKED SECTION */ SM_OBJ_LOCK_GIVE (&pDestCpuEventQ->lock, level); /* * now interrupt destination CPU only event queue was previously empty */ if (destEventQWasEmpty) { if (smUtilIntGen (&(smObjCpuInfoTbl[destCpu].smCpuDesc), destCpu) !=OK) { return (ERROR); /* int gen routine error */ } } return (OK); }/******************************************************************************** smObjEventProcess - shared memory objects event processing** This routine is called at interrupt level to handle the remote CPU part* of a global semaphore give or flush. It is called on the CPU that made the* semTake.** NOTE :* When the pending node is a remote node, the smObjTcb is removed from* the waiting list on the semGive or semFlush side and the TCB is put* on the ready queue on the semTake() side, otherwise since the notification* time is not null another semGive() or semFlush() could find the smObjTcb() in* the waiting list before the remote node have removed it. During* the notification time the task is not in the shared semaphore* waiting list and not in the remote CPU ready queue.** NOMANUAL*/void smObjEventProcess ( SM_DL_LIST * pEventList /* list of event to process */ ) { SM_OBJ_TCB * pSmObjTcb; WIND_TCB * pTcb; int level; /* * We are going to process each event stored in a local copy of * the event list obtain by smObjNotifyHandler. */ while (!(SM_DL_EMPTY (pEventList))) { /* * We must lock out interrupts while removing shared TCBs from * event list, because we can run here as deferred work and another * shared TCB event may be added to the global eventList * we use to empty the CPU event queue in smObjNotifyHandler. */ level = intLock (); pSmObjTcb = (SM_OBJ_TCB *) smDllGet (pEventList); intUnlock (level); /* get the local TCB */ pTcb = (WIND_TCB *) ntohl ((int) pSmObjTcb->localTcb); /* * At this time the following can happen, a task delete, a timeout * or a signal can have change the status of the previously * pending task. In that the incoming shared TCB must be dropped. * The fact that the task was deleted, timeout or signaled is * indicated by a NULL value in the localTcb pointer. * See qFifoGRemove for more details. */ if (pTcb != NULL) { /* * The task is still pending on the shared semaphore * we are giving. Put it on the ready Queue. * When it comes here the shared TCB has its removedByGive * field set to TRUE. We have to reset removedByGive * to indicate that this shared TCB can block again * on a shared semaphore otherwise a future call to * qFifoGRemove will get lost. */ pSmObjTcb->removedByGive = htonl (FALSE); /* don't disturb cache while in ISR, just trigger FIFO flush */ level = pSmObjTcb->removedByGive; /* BRIDGE FLUSH [SPR 68334] */ /* windview - level 2 event logging */ EVT_TASK_1 (EVENT_OBJ_SEMGIVE, NULL); windReadyQPut (pTcb); } else { /* * The task was deleted, was signaled or get a timeout, * we free the shared TCB. The next call to semTake * on a shared semaphore for this task will allocate * a new shared TCB since the pSmObjTcb field of the local * TCB has been set to NULL in qFifoGRemove. */ smObjTcbFree (pSmObjTcb); } } }/******************************************************************************** smObjNotifyHandler - handle shared memory events** This routine processes all events currently stored in local CPU event queue. * Events are shared TCBs of tasks which were previously blocked* on a shared semaphore and which were unblock by another CPU doing* a semGive.** This routine must be connected to the shared memory interrupt, mailbox * or polling task. ** The CPU event queue is protected against concurrent access by a spin-lock.* To reduce interrupt lattency, access to the event queue is only* prevented while events are removed from it, not when they are processed.** When the shared memory backplane driver is used, this handler is connected to* the interrupt, mailbox, or polling task used by the backplane driver.** RETURNS: OK, or ERROR if cannot obtain access to CPU event queue.** ERRNO:* S_smObjLib_LOCK_TIMEOUT** NOMANUAL*/LOCAL STATUS smObjNotifyHandler (void) { int level; /* * What we have to do here is remove all the shared TCB from * the CPU event queue and put them on a local eventList * and process them. * Note that there is no need of a while loop to check again for * CPU event queue emptiness, since if a CPU adds events * to it, it will generate an interrupt because we left * the CPU event queue empty after smDllConcat. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -