📄 smlib.c
字号:
SM_ANCHOR * anchorLocalAdrs, /* local addr of anchor */ char * smLocalAdrs, /* local addr of sh mem area */ int tasType, /* method of test-and-set */ int maxCpus, /* max number of cpu's */ int * pMemUsed /* amount of memory used */ ) { SM_ANCHOR volatile * pAnchorv = (SM_ANCHOR volatile *) anchorLocalAdrs; SM_HDR volatile * pHdr; /* local addr of sh mem hdr */ char temp = 0; /* temp location */ /* Initialize shared memory region table */ if (!smLibInitialized) { bzero ((char *) smRegions, sizeof (smRegions)); smLibInitialized = TRUE; } /* Probe shared memory */ if (smUtilMemProbe (smLocalAdrs, VX_WRITE, sizeof (char), &temp) != OK) { errno = S_smLib_MEMORY_ERROR; return (ERROR); } /* Find the Region */ if (smRegionFind (anchorLocalAdrs) != ERROR) { pHdr = SM_OFFSET_TO_LOCAL (ntohl (pAnchorv->smHeader), (int) pAnchorv, SM_HDR volatile *); if ((ntohl (pHdr->maxCpus) != maxCpus) || (ntohl (pHdr->tasType) != tasType)) printf ("smSetup:Warning! previous parameters differ!\n"); *pMemUsed = 0; return (OK); } if (smRegionGet (anchorLocalAdrs) == ERROR) return (ERROR); *pMemUsed = sizeof (SM_HDR) + (maxCpus * sizeof (SM_CPU_DESC)); /* Partially initialize shared memory header */ bzero (smLocalAdrs, *pMemUsed); pHdr = (SM_HDR volatile *) smLocalAdrs; /* header = SM start */ pHdr->tasType = htonl (tasType); /* test-and-set method */ pHdr->maxCpus = htonl (maxCpus); /* max number of cpu's */ pHdr->cpuTable = htonl (SM_LOCAL_TO_OFFSET (pHdr + sizeof (SM_HDR), (int) anchorLocalAdrs)); /* Set up the anchor */ bzero ((char *) pAnchorv, sizeof (SM_ANCHOR)); pAnchorv->version = htonl (SM_VERSION); /* sh mem version */ pAnchorv->smHeader = htonl (SM_LOCAL_TO_OFFSET (pHdr, (int) pAnchorv)); pAnchorv->masterCpu = htonl (SM_MASTER); /* sh mem master */ pAnchorv->readyValue = htonl (SM_READY); /* sh mem available */ CACHE_PIPE_FLUSH (); /* CACHE FLUSH [SPR 68334] */ maxCpus = pHdr->maxCpus; /* BRIDGE FLUSH [SPR 68334] */ return (OK); /* shared mem init complete */ }/******************************************************************************** smInit - initialize shared memory descriptor** This routine initializes a shared memory 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* smAttach().** Only the shared memory descriptor itself is modified by this routine.* No structures in shared memory are affected.** The <pSmDesc> paramter is the address of the shared memory descriptor* which is to be initialized; this structure must have already been* allocated before smInit() 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 <ticksPerBeat> parameter specifies the frequency of the shared memory* anchor's 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 smCpuInfoGet(). ** RETURNS: N/A*/void smInit ( SM_DESC * pSmDesc, /* sh mem descr to init*/ SM_ANCHOR * anchorLocalAdrs, /* local addr of sh mem anchor*/ 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 (pSmDesc == NULL) return; /* don't use null ptr */ bzero ((char *) pSmDesc, sizeof (SM_DESC)); /* Copy input parameters */ pSmDesc->anchorLocalAdrs = anchorLocalAdrs; pSmDesc->base = (int) anchorLocalAdrs; pSmDesc->cpuNum = smUtilProcNumGet (); pSmDesc->ticksPerBeat = (ticksPerBeat == 0) ? smUtilRateGet () : ticksPerBeat; pSmDesc->intType = intType; pSmDesc->intArg1 = intArg1; pSmDesc->intArg2 = intArg2; pSmDesc->intArg3 = intArg3; pSmDesc->status = SM_CPU_NOT_ATTACHED; /* initial status */ }/******************************************************************************** smIsAlive - determine if shared memory is initialized and active** This routine examines the shared memory anchor and heartbeat to* determine whether the shared memory has been initialized and that* it is running. The shared memory is specified by <pAnchor>, the* address of the shared memory anchor. If the shared* memory network is active, TRUE is returned; otherwise, FALSE is* returned. <pHeader> points to the location of the header containing* the heartbeat. <base> is the base address from which to calculate the* address of the heartbeat counter in the header in shared memory.** The anchor ready-value must contain the special value SM_READY to* indicate that the master CPU has successfully initialized the shared* memory region. The heartbeat must increment at least twice* within the timeout period to be recognized as active.** <heartBeats> specifies the number of beats to wait for a correct* ready-value and active heartbeat before timing out. A zero value* indicates the use of a default value, specified by the global variable * 'smAliveTimeout'.** <ticksPerBeat> specifies the number of ticks per heartbeat.** This routine safely probes the anchor addresses to avoid bus errors* (in case the anchor address is not yet accessable). Occasional* messages are written to standard output if a bus error occurs but is* handled. Occasional messages will also appear to indicate the most* recently obtained values for the ready-value and heartbeat.** This routine may not be called from interrupt level.** This routine does not set errno.** RETURNS: TRUE or FALSE.*/BOOL smIsAlive ( SM_ANCHOR * pAnchor, /* ptr to shared mem anchor */ int * pHeader, /* {smObj/smPkt} header */ int base, /* base */ int heartBeats, /* heartbeat periods */ int ticksPerBeat /* ticks per beat */ ) { UINT readyValue; /* ready value from anchor */ UINT newHeartBeat; /* beat value from anchor */ UINT oldHeartBeat; /* saved beat value */ int incCnt; /* number of beat increments observed*/ int * pHeartBeat = NULL; /* ptr to heartbeat */ int temp; /* temp storage */ newHeartBeat = 0; /* init beat values */ oldHeartBeat = 0; incCnt = 0; /* Determine number of heartbeat periods to wait */ if (ticksPerBeat == 0) { ticksPerBeat = smUtilRateGet (); } if (heartBeats == 0) { heartBeats = smAliveTimeout * (smUtilRateGet ()) / ticksPerBeat; } /* Check anchor and heartbeat until ready or countdown expires */ while (heartBeats-- > 0) { /* XXX - invalidate data cache here ?? */ /* Probe and get anchor ready-value */ if (smUtilMemProbe ((char *) &pAnchor->readyValue, VX_READ, sizeof (int), (char *) &readyValue) != OK) { if ((heartBeats % 10) == 8) /* print error occasionally */ { printf ("\nsmIsAlive: bus error checking anchor\n"); } } readyValue = ntohl (readyValue); if (readyValue == SM_READY) /* if anchor appears ready */ { /* * Calculate the location of the heartbeat. * The heartbeat must be the first location in {smPkt/smObj} * header. */ CACHE_PIPE_FLUSH (); /* FLUSH BUFFER [SPR 68334] */ temp = *(int *)pHeader; /* PCI bridge bug [SPR 68844]*/ pHeartBeat = SM_OFFSET_TO_LOCAL (ntohl (*pHeader), base, int *); /* Probe and get heartbeat value */ if (smUtilMemProbe ((char *) pHeartBeat, VX_READ, sizeof (int), (char *) &newHeartBeat) == OK) { newHeartBeat = ntohl (newHeartBeat); /* Check if heartbeat incremented */ if ((newHeartBeat <= oldHeartBeat) || (oldHeartBeat == 0)) { oldHeartBeat = newHeartBeat; /* no beat - try again */ } else /* beat incremented! */ { if (++incCnt >= 2) /* if 2 incr's have been seen*/ { return (TRUE); /* SHARED MEM IS ALIVE & WELL*/ } } } else /* could not probe heartbeat */ { if ((heartBeats % 10) == 8) /* print error occasionally */ { printf ("\nsmIsAlive: bus error getting heartbeat\n"); } } } /* end if (readyValue) */ /* Occasionally display last obtained ready-value and heartbeat */ if ((heartBeats % 10) == 6) { printf ("smIsAlive: readyValue = 0x%x, heartbeat = 0x%x\n", readyValue, newHeartBeat); } /* Wait before checking heartbeat again */ if (smUtilDelay ((char *) pHeartBeat, ticksPerBeat) != OK) { /* wait enough for 1 beat */ return (FALSE); /* called from int level?? */ } } /* end while */ return (FALSE); /* timed out */ }/******************************************************************************** smAttach - attach a node to shared memory** This routine "attaches" the local CPU to a shared memory area. The* shared memory area is identified by the shared memory descriptor* whose address specified by <pSmDesc>. The descriptor must have* already been initialized by calling smInit().** This routine should get called only after and when the shared memory has* been initialized by the master CPU. To determine this, smIsAlive() must* have been called to check the shared memory anchor for both the proper * value (SM_READY_VALUE) in the anchor's ready-value field and an * active heartbeat.** The attachment to shared memory may be ended by calling smDetach().** RETURNS: OK, or ERROR.** ERRNO: S_smLib_INVALID_CPU_NUMBER** SEE ALSO: smIsAlive(), smInit()*/STATUS smAttach ( SM_DESC * pSmDesc /* ptr to shared mem descriptor */ ) { SM_HDR volatile * pHdr; /* ptr to shared mem header */ SM_CPU_DESC volatile * pCpuDesc; /* ptr to shared mem cpu descriptor */ int cpuNum; /* this cpu's number */ int temp; /* temp storage */ cpuNum = pSmDesc->cpuNum; /* Get local address for shared mem header */ CACHE_PIPE_FLUSH (); /* FLUSH BUFFER [SPR 68334] */ temp = pSmDesc->anchorLocalAdrs->smHeader; /* PCI bridge bug [SPR 68844]*/ pHdr = SM_OFFSET_TO_LOCAL (ntohl (pSmDesc->anchorLocalAdrs->smHeader), pSmDesc->base, SM_HDR volatile *); pSmDesc->headerLocalAdrs = (SM_HDR *) pHdr; /* Copy data from shared mem header */ pSmDesc->maxCpus = ntohl (pHdr->maxCpus); pSmDesc->cpuTblLocalAdrs = SM_OFFSET_TO_LOCAL (ntohl (pHdr->cpuTable), pSmDesc->base, SM_CPU_DESC *); /* Determine test-and-set routine to use */ pSmDesc->tasClearRoutine = NULL; if (ntohl (pHdr->tasType) == SM_TAS_HARD) /* if using hardware tas */ { pSmDesc->tasRoutine = smUtilTas; pSmDesc->tasClearRoutine = (FUNCPTR) smUtilTasClear; } else pSmDesc->tasRoutine = smUtilSoftTas; /* use software tas routine */ /* Init entry in cpu table */ if (cpuNum < 0 || cpuNum >= pSmDesc->maxCpus) { errno = S_smLib_INVALID_CPU_NUMBER; return (ERROR); /* cpu number out of range */ } /* calculate addr of cpu desc in global table. */ pCpuDesc = (SM_CPU_DESC volatile *) &((pSmDesc->cpuTblLocalAdrs) [cpuNum]); pCpuDesc->intType = htonl (pSmDesc->intType); /* interrupt method */ pCpuDesc->intArg1 = htonl (pSmDesc->intArg1); /* interrupt argument #1 */ pCpuDesc->intArg2 = htonl (pSmDesc->intArg2); /* interrupt argument #2 */ pCpuDesc->intArg3 = htonl (pSmDesc->intArg3); /* interrupt argument #3 */ pCpuDesc->status = htonl (SM_CPU_ATTACHED); /* mark cpu as attached */ pSmDesc->status = SM_CPU_ATTACHED; /* also mark sh mem descr */ CACHE_PIPE_FLUSH (); /* FLUSH BUFFER [SPR 68334] */ cpuNum = pCpuDesc->intArg1; /* BRIDGE FLUSH [SPR 68334] */ return (OK); /* attach complete */ }/******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -