?? smlib.c
字號:
** smDetach - detach CPU from shared memory** This routine ends the "attachment" between the calling CPU and* the shared memory area specified by <pSmDesc>. No further shared* memory operations may be performed until a subsequent smAttach()* is completed.** RETURNS: OK, or ERROR.** ERRNO: S_smLib_NOT_ATTACHED*/STATUS smDetach ( SM_DESC * pSmDesc /* ptr to shared mem descriptor */ ) { SM_CPU_DESC volatile * pCpuDesc; /* ptr to cpu descriptor in sh mem hdr*/ int temp; /* temp value */ /* Check that this cpu is connected to shared memory */ if (pSmDesc->status != SM_CPU_ATTACHED) { errno = S_smLib_NOT_ATTACHED; return (ERROR); /* local cpu is not attached */ } /* get addr of cpu descriptor */ pCpuDesc = (SM_CPU_DESC volatile *) &((pSmDesc->cpuTblLocalAdrs) \ [pSmDesc->cpuNum]); pCpuDesc->status = htonl (SM_CPU_NOT_ATTACHED);/* mark as not attached */ pSmDesc->status = SM_CPU_NOT_ATTACHED; /* also mark sh mem descr */ CACHE_PIPE_FLUSH (); /* FLUSH BUFFER [SPR 68334] */ temp = pCpuDesc->status; /* BRIDGE FLUSH [SPR 68334] */ return (OK); }/******************************************************************************** smInfoGet - 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 <pSmDesc>. The* current information is returned in a special data structure, SM_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_smLib_NOT_ATTACHED*/STATUS smInfoGet ( SM_DESC * pSmDesc, /* ptr to shared memory descriptor */ SM_INFO * pInfo /* ptr to info structure to fill */ ) { SM_HDR volatile * pHdr; /* ptr to shared memory header */ SM_CPU_DESC volatile * pCpuDesc; /* ptr to cpu descriptor */ int ix; /* index variable */ int temp; /* temp value */ /* Check that this cpu is connected to shared memory */ if (pSmDesc->status != SM_CPU_ATTACHED) { errno = S_smLib_NOT_ATTACHED; return (ERROR); /* local cpu is not attached */ } /* Get protocol version number */ CACHE_PIPE_FLUSH (); /* FLUSH BUFFER [SPR 68334] */ temp = pSmDesc->anchorLocalAdrs->version; /* PCI bridge bug [SPR 68844]*/ pInfo->version = ntohl (pSmDesc->anchorLocalAdrs->version); /* Get info from shared memory header */ pHdr = (SM_HDR volatile *) pSmDesc->headerLocalAdrs; pInfo->tasType = ntohl (pHdr->tasType); /* test-and-set method */ pInfo->maxCpus = ntohl (pHdr->maxCpus); /* max number of cpu's */ /* Get count of attached cpu's starting with first cpu table entry */ pCpuDesc = (SM_CPU_DESC volatile *) pSmDesc->cpuTblLocalAdrs; pInfo->attachedCpus = 0; for (ix = 0; ix < pInfo->maxCpus; ix++) { if (ntohl (pCpuDesc->status) == SM_CPU_ATTACHED) pInfo->attachedCpus++; pCpuDesc++; /* next entry */ } return (OK); }/******************************************************************************** smCpuInfoGet - 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_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_smLib_NOT_ATTACHED, S_smLib_INVALID_CPU_NUMBER*/STATUS smCpuInfoGet ( SM_DESC * pSmDesc, /* ptr to shared memory descriptor */ int cpuNum, /* number of cpu to get info about */ SM_CPU_INFO * pCpuInfo /* cpu info structure to fill */ ) { SM_CPU_DESC volatile * pCpuDesc; /* ptr to cpu descriptor */ int temp; /* temp value */ /* Check that the local cpu is connected to shared memory */ if (pSmDesc->status != SM_CPU_ATTACHED) { errno = S_smLib_NOT_ATTACHED; return (ERROR); /* local cpu is not attached */ } /* Report on local cpu if NONE specified */ if (cpuNum == NONE) { cpuNum = pSmDesc->cpuNum; } /* Get info from cpu descriptor */ if (cpuNum < 0 || cpuNum >= pSmDesc->maxCpus) { errno = S_smLib_INVALID_CPU_NUMBER; return (ERROR); /* cpu number out of range */ } /* get address of cpu descr */ pCpuDesc = (SM_CPU_DESC volatile *) &(pSmDesc->cpuTblLocalAdrs [cpuNum]); pCpuInfo->cpuNum = cpuNum; /* actual cpu number */ CACHE_PIPE_FLUSH (); /* FLUSH BUFFER [SPR 68334] */ temp = pCpuDesc->status; /* PCI bridge bug [SPR 68844]*/ pCpuInfo->status = ntohl (pCpuDesc->status); /* attached/not attached */ pCpuInfo->intType = ntohl (pCpuDesc->intType); /* interrupt type */ pCpuInfo->intArg1 = ntohl (pCpuDesc->intArg1); /* interrupt argument #1 */ pCpuInfo->intArg2 = ntohl (pCpuDesc->intArg2); /* interrupt argument #2 */ pCpuInfo->intArg3 = ntohl (pCpuDesc->intArg3); /* interrupt argument #3 */ return (OK); }/******************************************************************************** smLockTake - take a mutual exclusion lock** This routine repeatedly attempts to obtain a mutual exclusion lock* by using the specified test-and-set routine. If the lock is not* obtained within the specified number of attempts, an error is returned.** If the lock was successfully taken, interrupts will be disabled when* this routine returns and the old interrupt mask level will be copied* to the location pointed to by <pOldLvl>.** If the lock was not taken, interrupts will be enabled upon return (at* the interrupt level which was in effect prior to calling this routine).** This routine does not set errno.** INTERNAL ** RETURNS: OK, or ERROR if lock not taken.*/STATUS smLockTake ( int * lockLocalAdrs, /* local addr of lock */ FUNCPTR tasRoutine, /* test-and-set routine to use */ int numTries, /* number of times to try to take lock */ int * pOldLvl /* where to put old int lvl if success */ ) { int oldLvl; /* previous interrupt level */ int delay; /* time between tries to get lock */ int ix; /* index */ int dummy = 0; /* dummy counter for delay */ volatile int dummy2; /* dummy to avoid warning in delay */ int curNumTries; /* current number of tries */ /* First try to get lock. */ oldLvl = intLock (); /* lock out interrupts */ if ((*tasRoutine) (lockLocalAdrs) == TRUE) { *pOldLvl = oldLvl; /* pass back old int level */ /* * XXXdat These PIPE_FLUSH operations should not be needed. * The tasRoutine should be taking care of the cache issues * related to tas activity. */ CACHE_PIPE_FLUSH (); /* flush write buffer */ dummy2 = *(int *)lockLocalAdrs; /* BRIDGE FLUSH [SPR 68334] */ return (OK); /* done! */ } intUnlock (oldLvl); /* unlock interrupts before retry */ /* * The first try has failed so now we insert a decrementing * delay between each tries to reduce bus contention and deadlock. * * Set maximum delay to a different value for each processor. * Note that this scheme gives a lowest priority to CPUs with * high processor number. A better version would implement * a random delay. */ delay = smLockTakeDelayMin; curNumTries = 1; do { for (ix = 0; ix <= delay; ix++) /* delay loop */ dummy2 = dummy++; /* volatile!! */ oldLvl = intLock (); /* lock out interrupts */ if ((*tasRoutine) (lockLocalAdrs) == TRUE) { *pOldLvl = oldLvl; /* pass back old int level */ CACHE_PIPE_FLUSH (); /* flush write buffer */ dummy2 = *(int *)lockLocalAdrs; /* BRIDGE FLUSH [SPR 68334] */ return (OK); /* done! */ } intUnlock (oldLvl); /* unlock interrupts before retry */ /* Exponential delay, with a limit */ delay <<= 1; if (delay > smLockTakeDelayMax) { delay = smLockTakeDelayMin; } curNumTries++; /* keep track of maximum number of attempts */ if (curNumTries > smCurMaxTries) { smCurMaxTries = curNumTries; } } while (--numTries > 0); /* do for spec'd number of tries */ return (ERROR); /* cannot take lock */ }/******************************************************************************** smLockGive - give a mutual exclusion lock** This routine gives up a mutual exclusion lock taken previously by smLockTake.** RETURNS: N/A*/void smLockGive ( int * lockLocalAdrs, /* local address of lock */ FUNCPTR tasClearRoutine, /* test and set clear routine to use */ int oldLvl /* old interrupt level */ ) { int volatile * pLockv = (int volatile *) lockLocalAdrs; int temp; /* temp value */ if (tasClearRoutine != NULL) /* hardware test-and-set */ { (*tasClearRoutine) (lockLocalAdrs); } else { *pLockv = 0; } CACHE_PIPE_FLUSH (); /* FLUSH BUFFER [SPR 68334] */ temp = *pLockv; /* BRIDGE FLUSH [SPR 68334] */ intUnlock (oldLvl); }/******************************************************************************** smRegionFind - find a shared memory region.** This routine finds the shared memory region associated with* <anchorLocalAdrs>.** RETURNS: index of the region, or ERROR if not found*/LOCAL int smRegionFind ( SM_ANCHOR * anchorLocalAdrs /* local address of anchor */ ) { int ix; /* index */ for (ix = 0; (smRegions [ix].anchor != NULL) && (ix < smRegionsMax); ix++) { if (smRegions [ix].anchor == anchorLocalAdrs) { return (ix); /* region already initialized*/ } } return (ERROR); }/******************************************************************************** smRegionGet - get a shared memory region** smRegionGet reserves a space in the smRegion table for a shared memory* region specified by <anchorLocalAdrs>.** RETURNS: the index of the region, or ERROR if out of space.*/LOCAL int smRegionGet ( SM_ANCHOR * anchorLocalAdrs /* anchor address */ ) { int ix; /* index */ for (ix = 0; (smRegions [ix].anchor != NULL) && (ix < smRegionsMax); ix++) ; if (ix == smRegionsMax) { printf ("Out of shared memory regions!!\n"); errno = S_smLib_NO_REGIONS; return (ERROR); /* no space in table */ } smRegions [ix].anchor = anchorLocalAdrs; return (ix); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -