smObjLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:55k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* smObjLib.c - shared memory objects library (VxMP Option) */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. /*
  4. modification history
  5. --------------------
  6. 01s,03may02,mas  cache flush and volatile fix (SPR 68334); bridge flush fix
  7.  (SPR 68844)
  8. 01r,24oct01,mas  fixed diab warnings (SPR 71120); doc update (SPR 71149)
  9. 01q,20sep01,jws  doc change for SPR68418
  10. 01p,16mar99,dat  fixed declaration of smUtilTasClearRtn. (SPR 25804)
  11. 01o,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  12. 01n,22feb99,wsl  DOC: removed all reference to spurious error code.
  13. 01l,05may93,caf  tweaked for ansi.
  14. 01l,17mar94,pme  Added WindView level 2 event logging.
  15.  Added comments about acknowledge of BUS interrupts (SPR# 2560).
  16. 01k,13mar93,jdi  code style fix for mangen.
  17. 01j,14feb93,jdi  documentation cleanup for 5.1.
  18. 01i,29jan93,pme  added little endian support.
  19.  added smObjLibInit() manual. Made smObjLibInit() return
  20.  ERROR if already initialized.
  21.  suppressed ntohl() macros in smObjCpuInfoGet().
  22.  aligned partition addresses.
  23. 01h,08dec92,jdi  documentation cleanup.
  24. 01g,02oct92,pme  added SPARC support. documentation cleanup.
  25. 01f,29sep92,pme  fixed bug in smObjInit (objCpuTbl was not converted to
  26.  local value in pSmObjHdr).
  27.  Added version number. comments cleanup.
  28.  set PART_OVH to 32 bytes.
  29. 01e,23aug92,jcf  cleanup.
  30. 01d,30jul92,pme  added SM_OBJ_SIZE(), cleaned up smObjSetup.
  31.                  changed parameter to smObjBeat.
  32.  added smObjTasClearRoutine for use with smLockGive().
  33.  added shared memory layout chart.
  34. 01c,24jul92,elh  changed parameters to smIsAlive.
  35. 01b,24jul92,gae  fixed number of parameters to logMsg().
  36. 01a,07feb92,pme  written.
  37. */
  38. /*
  39. DESCRIPTION
  40. This library contains miscellaneous functions used by the shared memory
  41. objects facility (VxMP).  Shared memory objects provide high-speed
  42. synchronization and communication among tasks running on separate CPUs that
  43. have access to a common shared memory.  Shared memory objects are system
  44. objects (e.g., semaphores and message queues) that can be used across
  45. processors.
  46. The main uses of shared memory objects are interprocessor synchronization,
  47. mutual exclusion on multiprocessor shared data structures, and high-speed
  48. data exchange.
  49. Routines for displaying shared memory objects statistics are provided  
  50. by the smObjShow module.
  51. SHARED MEMORY MASTER CPU
  52. One CPU node acts as the shared memory objects master.  This CPU
  53. initializes the shared memory area and sets up the shared memory anchor.
  54. These steps are performed by the master calling smObjSetup().  This
  55. routine should be called only once by the master CPU.  Usually smObjSetup()
  56. is called from usrSmObjInit().  (See "Configuration" below.)
  57. Once smObjSetup() has completed successfully, there is little functional
  58. difference between the master CPU and other CPUs using shared memory objects,
  59. except that the master is responsible for maintaining the heartbeat in
  60. the shared memory objects header.
  61. ATTACHING TO SHARED MEMORY
  62. Each CPU, master or non-master, that will use shared memory objects
  63. must attach itself to the shared memory objects facility, which
  64. must already be initialized.
  65. Before it can attach to a shared memory region, each CPU must allocate
  66. and initialize a shared memory descriptor (SM_DESC), which describes the
  67. individual CPU's attachment to the shared memory objects facility.  Since
  68. the shared memory descriptor is used only by the local CPU, it is not
  69. necessary for the descriptor itself to be located in shared memory.  In
  70. fact, it is preferable for the descriptor to be allocated from the CPU's
  71. local memory, since local memory is usually more efficiently accessed.
  72. The shared memory descriptor is initialized by calling smObjInit().  This
  73. routine takes a number of parameters which specify the characteristics of
  74. the calling CPU and its access to shared memory.
  75. Once the shared memory descriptor has been initialized, the CPU can
  76. attach itself to the shared memory region.  This is done by calling
  77. smObjAttach().
  78. When smObjAttach() is called, it verifies that the shared memory anchor
  79. contains the value SM_READY and that the heartbeat located in the shared
  80. memory objects header is incrementing.  If either of these conditions is
  81. not met, the routine will check periodically until either SM_READY or an
  82. incrementing heartbeat is recognized or a time limit is reached.  The
  83. limit is expressed in seconds, and 600 seconds (10 minutes) is the
  84. default.  If the time limit is reached before SM_READY or a heartbeat is
  85. found, ERROR is returned and `errno' is set to S_smLib_DOWN .
  86. ADDRESS CONVERSION
  87. This library also provides routines for converting between local and
  88. global shared memory addresses, smObjLocalToGlobal() and
  89. smObjGlobalToLocal().  A local shared memory address is the address
  90. required by the local CPU to reach a location in shared memory.  A global
  91. shared memory address is a value common to all CPUs in the system used to
  92. reference a shared memory location.  A global shared memory address is
  93. always an offset from the shared memory anchor.
  94. SPIN-LOCK MECHANISM
  95. The shared memory objects facilities use a spin-lock mechanism based on an
  96. indivisible read-modify-write (RMW) operation on a shared memory location
  97. which acts as a low-level mutual exclusion device.  The spin-lock mechanism
  98. is called with a system-wide configuration parameter,
  99. SM_OBJ_MAX_TRIES, which specifies the maximum number of RMW tries on a
  100. spin-lock location.
  101. Care must be taken that the number of RMW tries on a spin-lock on a
  102. particular CPU never reaches SM_OBJ_MAX_TRIES, otherwise system
  103. behavior becomes unpredictable.  The default value should be sufficient
  104. for reliable operation.
  105. The routine smObjTimeoutLogEnable() can be used to enable or disable the
  106. printing of a message should a shared memory object call fail while trying
  107. to take a spin-lock.
  108. RELATION TO BACKPLANE DRIVER
  109. Shared memory objects and the shared memory network (backplane) driver use 
  110. common underlying shared memory utilities.  They also use the same anchor, 
  111. the same shared memory header, and the same interrupt when they are used at
  112. the same time.
  113. LIMITATIONS
  114. A maximum of twenty CPUs can be used concurrently with shared memory
  115. objects.  Each CPU in the system must have a hardware test-and-set (TAS)
  116. mechanism, which is called via the system-dependent routine sysBusTas().
  117. The use of shared memory objects raises interrupt latency, because internal
  118. mechanisms lock interrupts while manipulating critical shared data
  119. structures.  Interrupt latency does not depend on the number of objects or
  120. CPUs used.
  121. GETTING STATUS INFORMATION
  122. The routine smObjShow() displays useful information regarding the current
  123. status of shared memory objects, including the number of tasks using
  124. shared objects, shared semaphores, and shared message queues, the number
  125. of names in the database, and also the maximum number of tries to get
  126. spin-lock access for the calling CPU.
  127. INTERNAL
  128. Routine structure
  129.     smObjSetup smObjLocalToGlobal smObjGlobalToLocal   smObjAttach   smObjInit
  130.      /                                                /    |            |
  131.  smSetup   ------------------------                smAttach |          smInit
  132.           /                                                |
  133.    smMemPartInit               smNameInit                   |    
  134.                                                             |
  135.                                                             |
  136.                                                             |
  137.   smObjEventSend-*             smObjNotifyHandler-*         | 
  138.    /   |      |                 /      |                    |
  139.   /     smObjCpuInfoGet       /  smObjEventProcess         |     smObjTcbInit  
  140.   |     -------------  --------                             |
  141. smUtilIntGen         /                              smUtilIntConnect
  142.                       |
  143.                   smDllConcat
  144.         *                      *                     (o)
  145.         |                      |                      |
  146.    SM_OBJ_LOCK_TAKE    SM_OBJ_LOCK_GIVE         smMemPartAlloc
  147. Memory layout
  148.  Shared Memory         Shared Memory           Shared Memory
  149.     Anchor              Descriptor             CPU Descriptors
  150.  (SM_ANCHOR)             (SM_HDR)              (SM_CPU_DESC)
  151. --------------   ----->--------------   ------>--------------
  152. |readyValue  |   |     | tasType    |   |      | status     |
  153. |    .       |   |     | maxCpus    |   |      | intType    |
  154. |smHeader    |----     | cpuTable   |----      | intArg1    | CPU 0 
  155. |    .       |         |     .      |          | intArg2    | descriptor
  156. |    .       |         |     .      |          | intArg3    |
  157. |smPktHeader |----     |     .      |          |------------|
  158. |    .       |   |     |     .      |          |    .       | CPU 1
  159. |smObjHeader |-- |     --------------          |------------|
  160. |    .       | | |                             |            |
  161. |    .       | | |                             ~            ~
  162. |    .       | | |                             |            | CPU n
  163. -------------- | |                             --------------
  164.                | |   Shared Memory Packet
  165.                | |     Memory Header 
  166.                | |    (SM_PKT_MEM_HDR)
  167.                | ----->--------------                             Free Packets
  168.                |       | heartBeat  |                        ---->-------------
  169.                |       | freeList   |------------------------|    |           |
  170.                |       | pktCpuTbl  |----                         |           |
  171.                |       | maxPktBytes|   |                         |           |
  172.                |       |     .      |   |                         |           |
  173.                |       --------------   |                         |           |
  174.                |                        |                         |           |
  175.                |                        |          per CPU        |           |
  176.                |                        |     Packet Descriptor   |           |
  177.                |                        |      (SM_PKT_CPU_DESC)  -------------
  178.                |                        ------>----------------
  179.                |                               |  status      | CPU 0
  180.                |                               |  inputList   | Packet Desc
  181.                |                               |  freeList    |
  182.                |                               |--------------|
  183.                |                               |      .       | CPU 1
  184.                |                               |      .       |
  185.                |                               |--------------|
  186.                |                               |              |
  187.                |                               ~              ~
  188.                |                               |              | CPU n
  189.                |                               |              |
  190.                |                               ----------------
  191.                |       Shared memory               per CPU
  192.                |       objects header           sm Objects Desc
  193.                |      (SM_OBJ_MEM_HDR)         (SM_OBJ_CPU_DESC)
  194.                ------->--------------   ------>----------------
  195.                        | heartBeat  |   |      |  status      | CPU 0 
  196.                        | initDone   |   |      |  smObjEventQ | Object Desc 
  197.                        | Partitions |   |      |--------------| 
  198.                        |    .       |   |      |      .       | CPU 1 
  199.                        | Name DTB   |   |      |      .       | 
  200.                        | objCpuTbl  |----      |--------------| 
  201.                        |    .       |          |              | 
  202.                        | max values |          |              | 
  203.                        |    .       |          ~              ~ 
  204.                        | statistics |          |              | CPU n
  205.                        --------------          ---------------- 
  206. CONFIGURATION
  207. When the component INCLUDE_SM_OBJ is included, the init and setup
  208. routines in this library are called automatically during VxWorks
  209. initialization.
  210. AVAILABILITY
  211. This module is distributed as a component of the unbundled shared memory
  212. objects support option, VxMP.
  213. INCLUDE FILES: smObjLib.h
  214. SEE ALSO: smObjShow, semSmLib, msgQSmLib, smMemLib, smNameLib, usrSmObjInit(),
  215. tb VxWorks Programmer's Guide: Shared Memory Objects
  216. */
  217. /* includes */
  218. #include "vxWorks.h"
  219. #include "errno.h"
  220. #include "intLib.h"
  221. #include "logLib.h"
  222. #include "cacheLib.h"
  223. #include "qFifoGLib.h"
  224. #include "smDllLib.h"
  225. #include "smLib.h"
  226. #include "smUtilLib.h"
  227. #include "semLib.h"
  228. #include "string.h"
  229. #include "stdlib.h"
  230. #include "sysLib.h"
  231. #include "wdLib.h"
  232. #include "private/smNameLibP.h"
  233. #include "private/smMemLibP.h"
  234. #include "private/smObjLibP.h"
  235. #include "private/smFixBlkLibP.h"
  236. #include "private/msgQSmLibP.h"
  237. #include "private/windLibP.h"
  238. #include "private/workQLibP.h"
  239. #include "private/funcBindP.h"
  240. #include "private/eventP.h"
  241. /* defines */
  242. #define PART_OVH      32 /* bytes overhead per partition */
  243. #define SM_OBJ_VERSION 1 /* version number */
  244. /* macro to calculate the size of a shared memory allocated object */
  245. #define SM_OBJ_SIZE(type) (ROUND_UP (sizeof (type), SM_ALIGN_BOUNDARY) 
  246.    + sizeof (SM_BLOCK_HDR))
  247. /* typedefs */
  248. /* cached CPU Information Structure */
  249. typedef struct sm_obj_cpu_info  /* SM_OBJ_CPU_INFO */
  250.     {
  251.     BOOL             cached;    /* TRUE if info for this CPU is cached */
  252.     SM_CPU_DESC      smCpuDesc; /* cpu notification info */
  253.     SM_OBJ_EVENT_Q * pCpuEventQ;/* pointer to cpu event queue */
  254.     } SM_OBJ_CPU_INFO;
  255. /* globals */
  256. SM_HDR volatile *         pSmHdr;    /* pointer to shared memory header */
  257. SM_OBJ_MEM_HDR volatile * pSmObjHdr; /* pointer to shared memory obj header */
  258. SM_OBJ_DESC               smObjDesc; /* shared memory object descriptor */
  259. FUNCPTR smObjTasRoutine;        /* test and set routine */
  260. FUNCPTR smObjTasClearRoutine;  /* clear routine */
  261. int     smObjSpinTries;         /* maximum # of tries to obtain lock access */
  262. int     smObjProcNum;           /* processor number */
  263. BOOL    smObjTimeoutLog; /* TRUE : print message if lock take fails */
  264. int smObjInitialized = FALSE; /* smObj facility not initialized */
  265. SM_FIX_BLK_PART_ID smTcbPartId; /* shared TCB partition id */
  266. /* locals */
  267. LOCAL SM_DL_LIST       eventList; /* event list to be processed */
  268. LOCAL SM_OBJ_EVENT_Q * pLocalEventQ; /* cached local event Q pointer */
  269. LOCAL SM_OBJ_CPU_INFO  smObjCpuInfoTbl [SM_OBJ_MAX_CPU];
  270. /* smObj cpu info table */ 
  271. LOCAL int              smObjHeartBeatRate; 
  272. /* heartbeat incrementing rate */
  273. LOCAL WDOG_ID          smObjWdog; /* watch dog for heartbeat */
  274. /* forward */
  275. LOCAL STATUS  smObjNotifyHandler (void);
  276. LOCAL STATUS  smObjCpuInfoGet (SM_OBJ_DESC * pSmObjDesc, int cpuNum, 
  277.                                SM_OBJ_CPU_INFO * pSmObjCpuInfo);
  278. LOCAL void    smObjBeat (UINT * pHeartBeat); 
  279. extern VOIDFUNCPTR smUtilTasClearRtn;
  280. /******************************************************************************
  281. *
  282. * smObjLibInit - install the shared memory objects facility (VxMP Option)
  283. *
  284. * This routine installs the shared memory objects facility.  It is called
  285. * automatically when the component INCLUDE_SM_OBJ is included.
  286. *
  287. * AVAILABILITY
  288. * This routine is distributed as a component of the unbundled shared memory
  289. * objects support option, VxMP.
  290. * RETURNS: OK, or ERROR if the shared memory objects facility has already been
  291. * installed. 
  292. */
  293. STATUS smObjLibInit (void)
  294.    {
  295.    if (!smObjInitialized)
  296. {
  297.     semSmLibInit (); /* initialize shared semaphore facility */
  298.     msgQSmLibInit (); /* initialize shared message queue facility */
  299.     smMemPartLibInit (); /* initialize shared memory manager facility */
  300. smObjInitialized = TRUE;
  301. return (OK);
  302. }
  303.    return (ERROR);
  304.    }
  305. /******************************************************************************
  306. *
  307. * smObjSetup - initialize the shared memory objects facility (VxMP Option)
  308. *
  309. * This routine initializes the shared memory objects facility by filling the
  310. * shared memory header.  It must be called only once by the shared memory
  311. * master CPU.  It is called automatically only by the master CPU, when the
  312. * component INCLUDE_SM_OBJ is included.
  313. *
  314. * Any CPU on the system backplane can use the shared memory objects facility;
  315. * however, the facility must first be initialized on the master CPU.  Then
  316. * before other CPUs are attached to the shared memory area by smObjAttach(), 
  317. * each must initialize its own shared memory objects descriptor using
  318. * smObjInit().  This mechanism is similar to the one used by the shared memory
  319. * network driver.
  320. *
  321. * The <smObjParams> parameter is a pointer to a structure containing the
  322. * values used to describe the shared memory objects setup.  This 
  323. * structure is defined as follows in smObjLib.h:
  324. * cs
  325. * typedef struct sm_obj_params    /@ setup parameters @/
  326. *     {
  327. *     BOOL        allocatedPool;  /@ TRUE if shared memory pool is malloced @/
  328. *     SM_ANCHOR * pAnchor;        /@ shared memory anchor                   @/
  329. *     char *      smObjFreeAdrs;  /@ start address of shared memory pool    @/
  330. *     int         smObjMemSize;   /@ memory size reserved for shared memory @/
  331. *     int         maxCpus;        /@ max number of CPUs in the system       @/
  332. *     int         maxTasks;       /@ max number of tasks using smObj        @/
  333. *     int         maxSems;        /@ max number of shared semaphores        @/
  334. *     int         maxMsgQueues;   /@ max number of shared message queues    @/
  335. *     int         maxMemParts;    /@ max number of shared memory partitions @/
  336. *     int         maxNames;       /@ max number of names of shared objects  @/
  337. *     } SM_OBJ_PARAMS;
  338. * ce
  339. *
  340. * INTERNAL
  341. *   During initialization, five partitions dedicated to each shared
  342. *   memory object type are created to avoid runtime memory fragmentation.
  343. *
  344. *      - smTcbPartId : shared TCBs partition.
  345. *
  346. *        This partition is a fixed block size partition protected 
  347. *        against concurrent access by a spinlock mechanism and 
  348. *        taskSafe()/taskUnsafe().
  349. *        The size of this partition is defined by the maximum number of
  350. *        tasks using shared memory objects facility as defined in the
  351. *        configuration parameter SM_OBJ_MAX_TASK.
  352. *        We use a fixed block size partition for the shared TCBs because 
  353. *        it is less time consuming than the variable block size memory 
  354. *        manager.  Interrupt lattency is thus reduced.  
  355. *        
  356. *      - smSemPartId : shared semaphores partition.
  357. *
  358. *        This partition is protected against concurrent access
  359. *        by a shared semaphore and taskSafe()/taskUnsafe().
  360. *        The size of this partition is defined by the maximum number of
  361. *        shared semaphores as defined in the configuration parameter
  362. *        SM_OBJ_MAX_SEM.
  363. *
  364. *      - smNamePartId : shared name database elements partition.
  365. *
  366. *        This partition is protected against concurrent access
  367. *        by a shared semaphore and taskSafe()/taskUnsafe().
  368. *        The size of this partition is defined by the maximum number of
  369. *        names to be entered in the database as defined in the configuration
  370. *        parameter SM_OBJ_MAX_NAME.
  371. *
  372. *      - smMsgQPartId : shared message queues partition.
  373. *
  374. *        This partition is protected against concurrent access
  375. *        by a shared semaphore and taskSafe()/taskUnsafe().
  376. *        The size of this partition is defined by the maximum number of
  377. *        shared message queues as defined in the configuration parameter
  378. *        SM_OBJ_MAX_MSG_Q.
  379. *
  380. *      - smPartPartId : user created shared partitions partition.
  381. *
  382. *        This partition is protected against concurrent access
  383. *        by a shared semaphore and taskSafe()/taskUnsafe().
  384. *        The size of this partition is defined by the maximum number of
  385. *        user created shared partitions as defined in the configuration
  386. *        parameter SM_OBJ_MAX_PART.
  387. *
  388. *      The remaining memory is dedicated to the default system
  389. *      shared partition : smSystemPart
  390. *
  391. *        This partition is used by smMemMalloc(), smMemFree() ... system calls.
  392. *        This partition is protected against concurrent access
  393. *        by a shared semaphore and taskSafe()/taskUnsafe().
  394. *        The size of this partition is the remaining part of the declared
  395. *        shared memory pool.
  396. *
  397. *   All partition headers are stored in the shared memory object
  398. *   descriptor reachable by all CPUs via the shared memory anchor.
  399. *
  400. * AVAILABILITY
  401. * This routine is distributed as a component of the unbundled shared memory
  402. * objects support option, VxMP.
  403. * RETURNS: OK, or ERROR if the shared memory pool cannot hold all the requested
  404. * objects or the number of CPUs exceeds the maximum.
  405. * ERRNO:
  406. *  S_smObjLib_TOO_MANY_CPU  
  407. *  S_smObjLib_SHARED_MEM_TOO_SMALL
  408. *
  409. * SEE ALSO: smObjInit(), smObjAttach() 
  410. */
  411. STATUS smObjSetup 
  412.     (
  413.     SM_OBJ_PARAMS * smObjParams /* setup parameters */
  414.     )
  415.     {
  416.     int reqMemSize; /* required memory pool size */ 
  417.     int         partSize; /* size of each partition */
  418.     char *      partAdrs; /* free address for each partition */
  419.     int bytesUsed; /* bytes already used by smSetup */
  420.     int internalPartsSize; /* sum of bytes used by all partitions */
  421.     char *      smObjFreeAdrs;  /* start address of shared memory pool */
  422.     int         smObjMemSize;   /* memory size reserved for shared memory */
  423.     SM_ANCHOR volatile * pAnchor;        /* shared memory anchor */
  424.     int         tmp;            /* temp storage */
  425.     /* check that only master CPU is calling us */
  426.     if (sysProcNumGet () != SM_MASTER)
  427.         {
  428. return (ERROR);
  429.         }
  430.     /* 
  431.      * Check that we don't want to use more than absolute maximum 
  432.      * number of CPUs.
  433.      */
  434.     if (smObjParams->maxCpus > SM_OBJ_MAX_CPU)
  435. {
  436. errno = S_smObjLib_TOO_MANY_CPU;
  437. return (ERROR);
  438. }
  439.     smObjFreeAdrs = smObjParams->smObjFreeAdrs;
  440.     smObjMemSize  = smObjParams->smObjMemSize;
  441.     pAnchor       = (SM_ANCHOR volatile *)smObjParams->pAnchor;
  442.     /* 
  443.      * Common shared memory setup.
  444.      * If smSetup has already been called by the bp driver bytesUsed
  445.      * will be 0 indicating that all the shared memory can be used
  446.      * by shared memory objects.
  447.      */
  448.     if (smSetup ((SM_ANCHOR *)pAnchor, smObjFreeAdrs, SM_TAS_HARD,
  449.  smObjParams->maxCpus, &bytesUsed) == ERROR)
  450.         {
  451. return (ERROR);
  452.         }
  453.     /*
  454.      * Move address pool after already used memory and set the
  455.      * new size of the pool.  Already used memory can be the anchor 
  456.      * when an external memory is used and/or memory dedicated
  457.      * to the packet based backplane driver.
  458.      */
  459.     smObjMemSize  -= bytesUsed;
  460.     smObjFreeAdrs += bytesUsed;
  461.     /* check that shared memory pool is big enough */
  462.     reqMemSize = sizeof (SM_OBJ_MEM_HDR) +
  463.      (sizeof (SM_OBJ_CPU_DESC) * SM_OBJ_MAX_CPU) +
  464.      (smObjParams->maxTasks * SM_OBJ_SIZE (SM_OBJ_TCB)) +
  465.      (smObjParams->maxSems * SM_OBJ_SIZE (SM_SEMAPHORE)) +
  466.      (smObjParams->maxNames * SM_OBJ_SIZE (SM_OBJ_NAME)) +
  467.      (smObjParams->maxMsgQueues * SM_OBJ_SIZE (SM_MSG_Q)) +
  468.      (smObjParams->maxMemParts * SM_OBJ_SIZE (SM_PARTITION)) +
  469.      4 * PART_OVH + 5 * SM_ALIGN_BOUNDARY;
  470.     if (smObjMemSize < reqMemSize)
  471. {
  472. errno = S_smObjLib_SHARED_MEM_TOO_SMALL;
  473. return (ERROR);
  474. }
  475.     /* clear shared memory */
  476.     bzero (smObjFreeAdrs, smObjMemSize);
  477.     /* store shared memory objects header at the top of shared memory */
  478.     pSmObjHdr = (SM_OBJ_MEM_HDR volatile *) ((int) smObjFreeAdrs);
  479.     /* set global values needed while initializing */
  480.     localToGlobalOffset = (int) pAnchor;
  481.     smObjPoolMinusOne   = localToGlobalOffset - 1;
  482.     /* set test and set routine pointer */
  483.     smObjTasRoutine      =  (FUNCPTR) sysBusTas;
  484.     smObjTasClearRoutine =  (FUNCPTR) smUtilTasClearRtn;
  485.  
  486.     /* set shared memory objects header in the anchor */
  487.     pAnchor->smObjHeader = htonl (LOC_TO_GLOB_ADRS (pSmObjHdr));
  488.     /* initialize shared TCB partition id */
  489.     smTcbPartId = (SM_FIX_BLK_PART_ID) 
  490.   (LOC_TO_GLOB_ADRS ((&pSmObjHdr->smTcbPart)));
  491.      
  492.     /* free memory is now behind shared memory objects header */
  493.     smObjFreeAdrs += sizeof (SM_OBJ_MEM_HDR);
  494.     smObjMemSize  -= sizeof (SM_OBJ_MEM_HDR);
  495.     /* store the objects CPU table behind the shared mem obj header */
  496.     pSmObjHdr->objCpuTbl = htonl (LOC_TO_GLOB_ADRS ((int) pSmObjHdr + 
  497.     sizeof (SM_OBJ_MEM_HDR)));
  498.     /* free memory is now behind the smObj CPU table */
  499.     smObjFreeAdrs += sizeof (SM_OBJ_CPU_DESC) * SM_OBJ_MAX_CPU;
  500.     smObjMemSize  -= sizeof (SM_OBJ_CPU_DESC) * SM_OBJ_MAX_CPU;
  501.     internalPartsSize = 0;
  502.     /* initialize shared TCBs partition */
  503.     partAdrs = smObjFreeAdrs;
  504.     partSize = SM_ALIGN_BOUNDARY + smObjParams->maxTasks * sizeof (SM_OBJ_TCB);
  505.     internalPartsSize += partSize;
  506.     smFixBlkPartInit (smTcbPartId, (char *) LOC_TO_GLOB_ADRS (partAdrs), 
  507.       partSize, sizeof (SM_OBJ_TCB));
  508.     /* initialize shared semaphores partition */
  509.     /* 
  510.      * align partition address otherwise partition size can 
  511.      * be reduced in smMemPartInit() 
  512.      */
  513.     partAdrs = (char *) ROUND_UP ((partAdrs + partSize), SM_ALIGN_BOUNDARY);
  514.     partSize = PART_OVH + (smObjParams->maxSems * SM_OBJ_SIZE (SM_SEMAPHORE));
  515.     internalPartsSize += partSize;
  516.     smMemPartInit ((SM_PART_ID volatile) smSemPartId,
  517.                    (char *) LOC_TO_GLOB_ADRS(partAdrs), partSize);
  518.     /* initialize shared name database partition */
  519.     partAdrs = (char *) ROUND_UP ((partAdrs + partSize), SM_ALIGN_BOUNDARY);
  520.     partSize = PART_OVH + (smObjParams->maxNames * SM_OBJ_SIZE (SM_OBJ_NAME));
  521.     internalPartsSize += partSize;
  522.     smMemPartInit ((SM_PART_ID volatile) smNamePartId,
  523.                    (char *) LOC_TO_GLOB_ADRS(partAdrs), partSize);
  524.     /* initialize shared message queues partition */
  525.     partAdrs = (char *) ROUND_UP ((partAdrs + partSize), SM_ALIGN_BOUNDARY);
  526.     partSize = PART_OVH + (smObjParams->maxMsgQueues * SM_OBJ_SIZE (SM_MSG_Q)); 
  527.     internalPartsSize += partSize;
  528.     smMemPartInit ((SM_PART_ID volatile) smMsgQPartId,
  529.                    (char *) LOC_TO_GLOB_ADRS(partAdrs), partSize);
  530.     /* initialize shared partitions headers partition */
  531.     partAdrs = (char *) ROUND_UP ((partAdrs + partSize), SM_ALIGN_BOUNDARY);
  532.     partSize = PART_OVH +(smObjParams->maxMemParts * SM_OBJ_SIZE(SM_PARTITION));
  533.     internalPartsSize += partSize;
  534.     smMemPartInit ((SM_PART_ID volatile) smPartPartId,
  535.                    (char *) LOC_TO_GLOB_ADRS(partAdrs), partSize);
  536.     /* initialize system shared partition with remaining memory */
  537.     partAdrs = (char *) (partAdrs + partSize);
  538.     partSize = smObjMemSize - internalPartsSize;
  539.     smMemPartInit ((SM_PART_ID volatile) smSystemPartId,
  540.                    (char *) LOC_TO_GLOB_ADRS(partAdrs), partSize);
  541.     /* put version number */
  542.     pSmObjHdr->version = htonl (SM_OBJ_VERSION);
  543.     /* fills information fields */
  544.     pSmObjHdr->maxSems      = htonl (smObjParams->maxSems);
  545.     pSmObjHdr->maxMsgQueues = htonl (smObjParams->maxMsgQueues);
  546.     pSmObjHdr->maxTasks     = htonl (smObjParams->maxTasks);
  547.     pSmObjHdr->maxMemParts  = htonl (smObjParams->maxMemParts);
  548.     pSmObjHdr->maxNames     = htonl (smObjParams->maxNames);
  549.     /* start smObj heartbeat */
  550.     
  551.     smObjHeartBeatRate = sysClkRateGet ();
  552.     smObjWdog = wdCreate ();
  553.     smObjBeat ((UINT *) &pSmObjHdr->heartBeat);
  554.     pSmObjHdr->initDone = htonl (TRUE); /* indicate initialization done */
  555.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  556.     tmp = pSmObjHdr->initDone;                  /* BRIDGE FLUSH  [SPR 68334] */
  557.     smNameInit (smObjParams->maxNames); /* initialize shared name database */
  558.     return (OK);
  559.     }
  560. /******************************************************************************
  561. *
  562. * smObjInit - initialize a shared memory objects descriptor (VxMP Option)
  563. *
  564. * This routine initializes a shared memory descriptor.  The descriptor must
  565. * already be allocated in the CPU's local memory.  Once the descriptor has
  566. * been initialized by this routine, the CPU may attach itself to the shared  
  567. * memory area by calling smObjAttach().
  568. *
  569. * This routine is called automatically when the component INCLUDE_SM_OBJ is
  570. * included.
  571. * Only the shared memory descriptor itself is modified by this routine.
  572. * No structures in shared memory are affected.
  573. *
  574. * Parameters:
  575. * is
  576. * i `<pSmObjDesc>'
  577. * The address of the shared memory descriptor to be initialized; this
  578. * structure must be allocated before smObjInit() is called.
  579. * i `<anchorLocalAdrs>'
  580. * The memory address by which the local CPU may access the shared memory
  581. * anchor.  This address may vary among CPUs in the system because of address
  582. * offsets (particularly if the anchor is located in one CPU's dual-ported
  583. * memory).
  584. * i `<ticksPerBeat>'
  585. * Specifies the frequency of the shared memory anchor's heartbeat.  The
  586. * frequency is expressed in terms of how many CPU ticks on the local CPU
  587. * correspond to one heartbeat period.
  588. * i `<smObjMaxTries>'
  589. * Specifies the maximum number of tries to obtain access to an internal
  590. * mutually exclusive data structure.
  591. * i `<intType>, <intArg1>, <intArg2>, <intArg3>'
  592. * Allow a CPU to announce the method by which it is to be notified of shared
  593. * memory events.  See the manual entry for if_sm for a discussion about
  594. * interrupt types and their associated parameters.
  595. * ie
  596. *
  597. * AVAILABILITY
  598. * This routine is distributed as a component of the unbundled shared memory
  599. * objects support option, VxMP.
  600. * RETURNS: N/A
  601. *
  602. * SEE ALSO: smObjSetup(), smObjAttach()
  603. */
  604. void smObjInit
  605.     (
  606.     SM_OBJ_DESC * pSmObjDesc,    /* ptr to shared memory descriptor */
  607.     SM_ANCHOR *   anchorLocalAdrs, /* shared memory anchor local adrs */
  608.     int   ticksPerBeat,    /* cpu ticks per heartbeat */
  609.     int   smObjMaxTries,   /* max no. of tries to obtain spinLock */
  610.     int   intType,    /* interrupt method */
  611.     int   intArg1,    /* interrupt argument #1 */
  612.     int   intArg2,    /* interrupt argument #2 */
  613.     int   intArg3    /* interrupt argument #3 */
  614.     )
  615.     {
  616.     if (pSmObjDesc == NULL)
  617.         {
  618.         return;                 /* don't use null ptr */
  619.         }
  620.     /* generic shared memory descriptor initialization */
  621.     smInit (&pSmObjDesc->smDesc, anchorLocalAdrs, ticksPerBeat, intType, 
  622.             intArg1, intArg2, intArg3); 
  623.   
  624.     /* set global processor number */
  625.     smObjProcNum = pSmObjDesc->smDesc.cpuNum;
  626.     /* set test and set routine pointer */
  627.     smObjTasRoutine      =  (FUNCPTR) sysBusTas;
  628.     smObjTasClearRoutine =  (FUNCPTR) smUtilTasClearRtn;
  629.  
  630.     /* allow message to be printed if lock take fails */
  631.     smObjTimeoutLogEnable (TRUE);
  632.     /* set system wide maximum number of tries to obtain lock */
  633.     smObjSpinTries = smObjMaxTries;
  634.     /* install show routines */
  635.     /* XXXmas these should be turned into one or more components in a folder */
  636.     smObjShowInit ();
  637.     smNameShowInit ();
  638.     smMemShowInit ();
  639.     semSmShowInit ();
  640.     msgQSmShowInit ();
  641.     /* generic show routine for shared memory objects called by show() */
  642.     _func_smObjObjShow = (FUNCPTR) smObjObjShow;
  643.     }
  644. /******************************************************************************
  645. *
  646. * smObjAttach - attach the calling CPU to the shared memory objects facility (VxMP Option)
  647. *
  648. * This routine "attaches" the calling CPU to the shared memory objects
  649. * facility.  The shared memory area is identified by the shared memory
  650. * descriptor with an address specified by <pSmObjDesc>.  The descriptor must
  651. * already have been initialized by calling smObjInit().
  652. *
  653. * This routine is called automatically when the component INCLUDE_SM_OBJ is
  654. * included.
  655. *
  656. * This routine will complete the attach process only if and when the shared
  657. * memory has been initialized by the master CPU.  If the shared memory is
  658. * not recognized as active within the timeout period (10 minutes), this
  659. * routine returns ERROR.
  660. *
  661. * The smObjAttach() routine connects the shared memory objects handler to the
  662. * shared memory interrupt.  Note that this interrupt may be shared between
  663. * the shared memory network driver and the shared memory objects facility
  664. * when both are used at the same time.
  665. *
  666. * WARNING:
  667. * Once a CPU has attached itself to the shared memory objects facility, 
  668. * it cannot be detached.  Since the shared memory network driver and 
  669. * the shared memory objects facility use the same low-level attaching
  670. * mechanism, a CPU cannot be detached from a shared memory network driver
  671. * if the CPU also uses shared memory objects.
  672. *
  673. * AVAILABILITY
  674. * This routine is distributed as a component of the unbundled shared memory
  675. * objects support option, VxMP.
  676. * RETURNS:
  677. * OK, or ERROR if the shared memory objects facility is not active
  678. * or the number of CPUs exceeds the maximum.
  679. *
  680. * ERRNO:
  681. *  S_smLib_INVALID_CPU_NUMBER
  682. *
  683. * SEE ALSO: smObjSetup(), smObjInit()
  684. */
  685. STATUS smObjAttach
  686.     (
  687.     SM_OBJ_DESC * pSmObjDesc /* pointer to shared memory descriptor */
  688.     )
  689.     {
  690.     SM_OBJ_CPU_INFO * pSmObjCpuInfo; /* cpu info structure to fill */
  691.     SM_OBJ_CPU_DESC * pObjDesc;      /* pointer to smObj CPU descriptor */
  692.     SM_ANCHOR *       pAnchor;       /* pointer to shared memory anchor */
  693.     int               cpuNum;        /* this CPU number */
  694.     int               beatsToWait;   /* heart beat period */
  695.     int               tmp;           /* temp storage */
  696.     cpuNum  = pSmObjDesc->smDesc.cpuNum;
  697.     pAnchor = pSmObjDesc->smDesc.anchorLocalAdrs;
  698.     /* Check that shared memory is initialized and running */
  699.     beatsToWait = (cpuNum == SM_MASTER) ?
  700.                   DEFAULT_BEATS_TO_WAIT : DEFAULT_ALIVE_TIMEOUT;
  701.     if (smIsAlive (pAnchor, &(pAnchor->smObjHeader), pSmObjDesc->smDesc.base,
  702.    beatsToWait, pSmObjDesc->smDesc.ticksPerBeat) == FALSE)
  703.         {
  704.         return (ERROR);                         /* sh memory not active */
  705.         }
  706.     /* generic shared memory attach */
  707.     if (smAttach (&pSmObjDesc->smDesc) == ERROR)
  708.         {
  709.         return (ERROR);
  710.         }
  711.  
  712.     /* set offset to access shared objects */
  713.     localToGlobalOffset = (int) pSmObjDesc->smDesc.anchorLocalAdrs;
  714.   
  715.     smObjPoolMinusOne = localToGlobalOffset - 1;
  716.     /* get local address of shared memory header */
  717.     pSmObjHdr = (SM_OBJ_MEM_HDR volatile *) GLOB_TO_LOC_ADRS(
  718.                                                   ntohl(pAnchor->smObjHeader));
  719.     pSmObjDesc->hdrLocalAdrs = (SM_OBJ_MEM_HDR *) pSmObjHdr;
  720.     pSmObjDesc->cpuLocalAdrs = (SM_OBJ_CPU_DESC *) 
  721.                                GLOB_TO_LOC_ADRS (ntohl (pSmObjHdr->objCpuTbl));
  722.     /* initialize shared TCB partition id and free routines pointer */
  723.      
  724.     smTcbPartId = (SM_FIX_BLK_PART_ID)
  725.    (LOC_TO_GLOB_ADRS((&pSmObjHdr->smTcbPart)));
  726.     smObjTcbFreeRtn        = (FUNCPTR) smObjTcbFree;
  727.     smObjTcbFreeFailRtn    = (FUNCPTR) smObjTcbFreeLogMsg;
  728.     /* set global name database pointer */
  729.     pSmNameDb = &pSmObjHdr->nameDtb;   /* get name database header */
  730.     /* initialize windDelete failure notification routine pointer */
  731.     smObjTaskDeleteFailRtn = (FUNCPTR) smObjTimeoutLogMsg;
  732.     /* get local event Q pointer */
  733.     pSmObjCpuInfo = (SM_OBJ_CPU_INFO *) malloc (sizeof (SM_OBJ_CPU_INFO));
  734.     bzero ((char *) pSmObjCpuInfo, sizeof (SM_OBJ_CPU_INFO));
  735.     smObjCpuInfoGet (pSmObjDesc, NONE, pSmObjCpuInfo);
  736.     pLocalEventQ = pSmObjCpuInfo->pCpuEventQ;
  737.     /* clear cpu notification info cache table */
  738.     bzero ((char *) smObjCpuInfoTbl, 
  739.            sizeof (SM_OBJ_CPU_INFO) * SM_OBJ_MAX_CPU);
  740.     /* connect the shared memory objects interrupt handler */
  741.    
  742.     if (smUtilIntConnect (HIGH_PRIORITY, (FUNCPTR) smObjNotifyHandler, 0, 
  743.   pSmObjDesc->smDesc.intType, 
  744.                           pSmObjDesc->smDesc.intArg1, 
  745.                           pSmObjDesc->smDesc.intArg2, 
  746.   pSmObjDesc->smDesc.intArg3) == ERROR)
  747.         {
  748. return (ERROR);
  749.         }
  750.     /* calculate addr of cpu desc in global table */
  751.     pObjDesc = &((pSmObjDesc->cpuLocalAdrs) [smObjProcNum]);
  752.     pObjDesc->status = htonl (SM_CPU_ATTACHED); /* mark this cpu as attached */
  753.     pSmObjDesc->status = SM_CPU_ATTACHED;       /* also mark sh mem descr */
  754.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  755.     tmp = pObjDesc->status;                     /* BRIDGE FLUSH  [SPR 68334] */
  756.     return (OK);
  757.     }
  758. /******************************************************************************
  759. *
  760. * smObjDetach - detach CPU from shared memory objects facility
  761. *
  762. * This routine ends the "attachment" between the calling CPU and
  763. * the shared memory objects facility.  
  764. *
  765. * RETURNS: OK, or ERROR.
  766. *
  767. * INTERNAL
  768. * Detaching a CPU that uses shared memory objects is not possible
  769. * as smObj are implemented now.  Indeed, if a CPU has a task pended
  770. * on a shared semaphore, there is a shared TCB attached to the semaphore
  771. *
  772. * NOMANUAL
  773. */
  774. STATUS smObjDetach
  775.     (
  776.     SM_DESC * pSmObjDesc       /* ptr to shared mem object descriptor */
  777.     )
  778.     {
  779.     if (pSmObjDesc == NULL)
  780.         {
  781.         return (ERROR);
  782.         }
  783.     /* PME for now no detachment from shared memory objects available */
  784.     return (ERROR);
  785.     }
  786. /******************************************************************************
  787. *
  788. * smObjEventSend - send one or more events to remote CPU
  789. *
  790. * This routine notifies one or more shared memory events to a remote CPU.
  791. * Notification informations are stored in the shared memory objects task
  792. * control block added to <pEventList> list.  The last parameter <destCpu>
  793. * contains the processor number to which events are sent.
  794. *
  795. * Events are shared TCB of tasks to be added to the ready queue.
  796. *
  797. * A spin-lock mechanism is used to prevent more than one processor to add 
  798. * events to the same processor event queue at the same time.
  799. *
  800. * In order to reduce bus traffic and interrupt number, the destination CPU 
  801. * is interrupted only if its event queue was previously empty. 
  802. *
  803. * This routine uses smMemIntGenFunc() to interrupt the destination CPU.
  804. *
  805. * RETURNS: OK, or ERROR if cannot obtain access to CPU event queue.
  806. *
  807. * ERRNO:
  808. *   S_smObjLib_LOCK_TIMEOUT
  809. *
  810. * NOMANUAL
  811. */
  812. STATUS smObjEventSend
  813.     (
  814.     SM_DL_LIST * pEventList, /* list of events */
  815.     UINT32       destCpu
  816.     )
  817.     {
  818.     SM_OBJ_EVENT_Q * pDestCpuEventQ;   /* remote CPU event queue */
  819.     BOOL destEventQWasEmpty;
  820.     int level;
  821.     /*
  822.      * Cache eventQ and notification informations if this is
  823.      * the first time events are send to destCpu.
  824.      */
  825.     if (!smObjCpuInfoTbl [destCpu].cached)
  826. {
  827. smObjCpuInfoGet (&smObjDesc, destCpu, &smObjCpuInfoTbl [destCpu]);
  828. smObjCpuInfoTbl[destCpu].cached = TRUE;
  829.         }
  830.     pDestCpuEventQ = smObjCpuInfoTbl [destCpu].pCpuEventQ;
  831.     /* ENTER LOCKED SECTION */
  832.     if (SM_OBJ_LOCK_TAKE (&pDestCpuEventQ->lock, &level) != OK)
  833.         {
  834. smObjTimeoutLogMsg ("smObjEventSend", (char *) &pDestCpuEventQ->lock);
  835.         return (ERROR);                         /* can't take lock */
  836.         }
  837.     destEventQWasEmpty = SM_DL_EMPTY (&pDestCpuEventQ->eventList);
  838.     /* add shared TCBs to event queue */
  839.     smDllConcat (&pDestCpuEventQ->eventList, pEventList);
  840.     /* EXIT LOCKED SECTION */
  841.     SM_OBJ_LOCK_GIVE (&pDestCpuEventQ->lock, level);
  842.     /* 
  843.      * now interrupt destination CPU only event queue was previously empty
  844.      */
  845.     if (destEventQWasEmpty)
  846. {
  847.      if (smUtilIntGen (&(smObjCpuInfoTbl[destCpu].smCpuDesc), destCpu) !=OK)
  848.          {
  849.     return (ERROR);                    /* int gen routine error */
  850.          }
  851. }
  852.     return (OK);
  853.     }
  854. /******************************************************************************
  855. *
  856. * smObjEventProcess - shared memory objects event processing
  857. *
  858. * This routine is called at interrupt level to handle the remote CPU part
  859. * of a global semaphore give or flush.  It is called on the CPU that made the
  860. * semTake.
  861. *
  862. * NOTE :
  863. * When the pending node is a remote node, the smObjTcb is removed from
  864. * the waiting list on the semGive or semFlush side and the TCB is put
  865. * on the ready queue on the semTake() side, otherwise since the notification
  866. * time is not null another semGive() or semFlush() could find the smObjTcb() in
  867. * the waiting list before the remote node have removed it.  During
  868. * the notification time the task is not in the shared semaphore
  869. * waiting list and not in the remote CPU ready queue.
  870. *
  871. * NOMANUAL
  872. */
  873. void smObjEventProcess
  874.     (
  875.     SM_DL_LIST * pEventList      /* list of event to process */
  876.     )
  877.     {
  878.     SM_OBJ_TCB * pSmObjTcb;
  879.     WIND_TCB   * pTcb;
  880.     int   level;
  881.     /*
  882.      * We are going to process each event stored in a local copy of 
  883.      * the event list obtain by smObjNotifyHandler.
  884.      */
  885.     while (!(SM_DL_EMPTY (pEventList)))
  886.         {
  887. /* 
  888.  * We must lock out interrupts while removing shared TCBs from 
  889.  * event list, because we can run here as deferred work and another
  890.  * shared TCB event may be added to the global eventList 
  891.  * we use to empty the CPU event queue in smObjNotifyHandler.
  892.  */
  893.         
  894. level = intLock ();
  895.         pSmObjTcb = (SM_OBJ_TCB *) smDllGet (pEventList);
  896. intUnlock (level);
  897. /* get the local TCB */
  898. pTcb = (WIND_TCB *) ntohl ((int) pSmObjTcb->localTcb);
  899. /* 
  900.  * At this time the following can happen, a task delete, a timeout
  901.  * or a signal can have change the status of the previously
  902.  * pending task.  In that the incoming shared TCB must be dropped.
  903.  * The fact that the task was deleted, timeout or signaled is
  904.  * indicated by a NULL value in the localTcb pointer. 
  905.  * See qFifoGRemove for more details.
  906.  */
  907. if (pTcb != NULL)
  908.     {
  909.     /* 
  910.      * The task is still pending on the shared semaphore
  911.      * we are giving.  Put it on the ready Queue.
  912.      * When it comes here the shared TCB has its removedByGive
  913.      * field set to TRUE.  We have to reset removedByGive
  914.      * to indicate that this shared TCB can block again
  915.      * on a shared semaphore otherwise a future call to
  916.      * qFifoGRemove will get lost.
  917.      */
  918.     pSmObjTcb->removedByGive = htonl (FALSE);
  919.             /* don't disturb cache while in ISR, just trigger FIFO flush */
  920.             level = pSmObjTcb->removedByGive;   /* BRIDGE FLUSH  [SPR 68334] */
  921.             /* windview - level 2 event logging */
  922.     EVT_TASK_1 (EVENT_OBJ_SEMGIVE, NULL);
  923.             windReadyQPut (pTcb);
  924.     }
  925. else
  926.     {
  927.     /* 
  928.      * The task was deleted, was signaled or get a timeout,
  929.      * we free the shared TCB.  The next call to semTake
  930.      * on a shared semaphore for this task will allocate 
  931.      * a new shared TCB since the pSmObjTcb field of the local
  932.      * TCB has been set to NULL in qFifoGRemove.
  933.      */
  934.     smObjTcbFree (pSmObjTcb);
  935.     }
  936.         }
  937.     }
  938. /******************************************************************************
  939. *
  940. * smObjNotifyHandler - handle shared memory events
  941. *
  942. * This routine processes all events currently stored in local CPU event queue. 
  943. * Events are shared TCBs of tasks which were previously blocked
  944. * on a shared semaphore and which were unblock by another CPU doing
  945. * a semGive.
  946. *
  947. * This routine must be connected to the shared memory interrupt, mailbox 
  948. * or polling task. 
  949. *
  950. * The CPU event queue is protected against concurrent access by a spin-lock.
  951. * To reduce interrupt lattency, access to the event queue is only
  952. * prevented while events are removed from it, not when they are processed.
  953. *
  954. * When the shared memory backplane driver is used, this handler is connected to
  955. * the interrupt, mailbox, or polling task used by the backplane driver.
  956. *
  957. * RETURNS: OK, or ERROR if cannot obtain access to CPU event queue.
  958. *
  959. * ERRNO:
  960. *   S_smObjLib_LOCK_TIMEOUT
  961. *
  962. * NOMANUAL
  963. */
  964. LOCAL STATUS smObjNotifyHandler (void)
  965.     {
  966.     int                level;
  967.     /* 
  968.      * What we have to do here is remove all the shared TCB from
  969.      * the CPU event queue and put them on a local eventList
  970.      * and process them. 
  971.      * Note that there is no need of a while loop to check again for 
  972.      * CPU event queue emptiness, since if a CPU adds events 
  973.      * to it, it will generate an interrupt because we left
  974.      * the CPU event queue empty after smDllConcat.
  975.      */
  976.     /*
  977.      * We must check for event queue emptiness because
  978.      * we are connected to the same interrupt as the backplane driver.
  979.      */
  980.     if (!(SM_DL_EMPTY (&pLocalEventQ->eventList)))
  981. {
  982. /* ENTER LOCKED SECTION */
  983.         if (SM_OBJ_LOCK_TAKE (&pLocalEventQ->lock, &level) != OK)
  984.     {
  985.     smObjTimeoutLogMsg ("smObjNotifyHandler", 
  986. (char *) &pLocalEventQ->lock);
  987.             return (ERROR);               /* can't take lock */
  988.             }
  989. /* 
  990.  * Now, in order to minimize interrupt lattency, we remove all 
  991.  * the events from event queue at the same time and put them in 
  992.  * a local event list.
  993.  */
  994. smDllConcat (&eventList, &pLocalEventQ->eventList);  
  995. /* EXIT LOCKED SECTION */
  996. SM_OBJ_LOCK_GIVE (&pLocalEventQ->lock, level);
  997. /* 
  998.  * Now process list of events out of the locked section,
  999.  * if we are already in kernel state, defer the work.
  1000.  */
  1001. /* 
  1002.  * We can come here with an empty list in the case where
  1003.  * shared memory objects and sm backplane driver are used
  1004.  * at the same time and the interrupt was for an sm packet
  1005.  * not for a smObj event.  In that case smObjEventProcess
  1006.  * will essentially be a no-op.
  1007.  */
  1008. if (kernelState)
  1009.     {
  1010.     workQAdd1 ((FUNCPTR) smObjEventProcess, (int) &eventList);
  1011.     }
  1012. else
  1013.     {
  1014.     kernelState = TRUE; /* ENTER KERNEL */
  1015.     smObjEventProcess (&eventList); /* unblock tasks */
  1016.     windExit ();  /* EXIT KERNEL */
  1017.     }
  1018.         /* 
  1019.          * If we were notified by a bus interrupt we must acknowledge it.
  1020.          * This is not done here since it is not possible to acknowledge a bus
  1021.          * interrupt more than once on most i960 boards.  Under heavy load
  1022.          * on both the backplane driver and shared memory objects the backplane
  1023.          * driver will also acknowledge the interrupt and cause the CPU to
  1024.          * reboot.  The only solution is to handle the acknowledge in the
  1025.          * smUtilIntRoutine() but this is only possible with a rework of both
  1026.          * VxMP and the shared memory network code.
  1027.          */
  1028. }
  1029.     return (OK);
  1030.     }
  1031. /******************************************************************************
  1032. *
  1033. * smObjLocalToGlobal - convert a local address to a global address (VxMP Option)
  1034. *
  1035. * This routine converts a local shared memory address <localAdrs> to its
  1036. * corresponding global value.  This routine does not verify that
  1037. * <localAdrs> is really a valid local shared memory address.
  1038. *
  1039. * All addresses stored in shared memory are global.  Any access made to shared
  1040. * memory by the local CPU must be done using local addresses.  This routine
  1041. * and smObjGlobalToLocal() are used to convert between these address types.
  1042. *
  1043. * AVAILABILITY
  1044. * This routine is distributed as a component of the unbundled shared memory
  1045. * objects support option, VxMP.
  1046. * RETURNS: The global shared memory address pointed to by <localAdrs>.
  1047. *
  1048. * SEE ALSO: smObjGlobalToLocal()
  1049. */
  1050. void * smObjLocalToGlobal 
  1051.     (
  1052.     void * localAdrs /* local address to convert */
  1053.     )
  1054.     {
  1055.     /* test memory bounds PME */
  1056.     return ((void *) LOC_TO_GLOB_ADRS (localAdrs));
  1057.     }
  1058. /******************************************************************************
  1059. *
  1060. * smObjGlobalToLocal - convert a global address to a local address (VxMP Option)
  1061. *
  1062. * This routine converts a global shared memory address <globalAdrs> to its
  1063. * corresponding local value.  This routine does not verify that <globalAdrs>
  1064. * is really a valid global shared memory address.
  1065. *
  1066. * All addresses stored in shared memory are global.  Any access made to shared
  1067. * memory by the local CPU must be done using local addresses.  This routine
  1068. * and smObjLocalToGlobal() are used to convert between these address types.
  1069. *
  1070. * AVAILABILITY
  1071. * This routine is distributed as a component of the unbundled shared memory
  1072. * objects support option, VxMP.
  1073. * RETURNS: The local shared memory address pointed to by <globalAdrs>.
  1074. *
  1075. * SEE ALSO: smObjLocalToGlobal()
  1076. */
  1077. void * smObjGlobalToLocal 
  1078.     (
  1079.     void * globalAdrs /* global address to convert */
  1080.     )
  1081.     {
  1082.     /*
  1083.      * PME test memory bounds not in the range 
  1084.      * SM_OBJ_FREE_ADRS - (SM_OBJ_FREE_ADRS + SM_OBJ_FREE_SIZE)
  1085.      */
  1086.     return ((void *) GLOB_TO_LOC_ADRS (globalAdrs));
  1087.     }
  1088. /******************************************************************************
  1089. *
  1090. * smObjTcbInit - initialize shared Task Control Block
  1091. *
  1092. * This routine allocates a shared task control block from the shared memory 
  1093. * TCB dedicated pool (smTcbPartId) and initializes it.  The shared TCB pointer
  1094. * is stored in the pSmObjTcb field of the task control block.
  1095. *
  1096. * This function is called the first time a task block on a shared semaphore
  1097. * (ie in semTake).
  1098. *
  1099. * The shared Task Control Block is de-allocated and the associated
  1100. * memory is given back to the shared TCB dedicated pool when the task
  1101. * exits or is deleted.
  1102. *
  1103. * RETURNS: OK, or ERROR if cannot allocate shared TCB.
  1104. *          
  1105. * ERRNO:
  1106. *  S_smMemLib_NOT_INITIALIZED
  1107. *  S_smMemLib_NOT_ENOUGH_MEMORY
  1108. *  S_smObjLib_LOCK_TIMEOUT
  1109. *
  1110. * NOMANUAL
  1111. */
  1112. STATUS smObjTcbInit (void)
  1113.     {
  1114.     WIND_TCB * pTcb;
  1115.     pTcb = (WIND_TCB *) taskIdCurrent; /* get current tcb */
  1116.     /* allocate shared TCB from shared TCBs partition */
  1117.     pTcb->pSmObjTcb = (SM_OBJ_TCB *) smFixBlkPartAlloc (smTcbPartId);
  1118.     if (pTcb->pSmObjTcb == NULL)
  1119.         {
  1120.         return (ERROR);
  1121.         }
  1122.     /* initialize shared TCB */
  1123.     bzero ((char *) pTcb->pSmObjTcb, sizeof (SM_OBJ_TCB));
  1124.     pTcb->pSmObjTcb->ownerCpu = htonl (smObjProcNum);   /* our proc number */
  1125. /* local TCB we belong to */
  1126.     pTcb->pSmObjTcb->localTcb = (WIND_TCB *) htonl ((int) pTcb); 
  1127.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  1128.     return (OK);
  1129.     }
  1130. /******************************************************************************
  1131. *
  1132. * smObjTcbFree - free shared Task Control Block
  1133. *
  1134. * This routine gives back a shared task control block to the shared memory
  1135. * TCB dedicated pool (smTcbPartId).
  1136. *
  1137. * The shared Task Control Block is de-allocated and the associated
  1138. * memory is given back to the shared TCB dedicated pool when the task
  1139. * exits or is deleted.
  1140. *
  1141. * RETURNS: OK, or ERROR if cannot free shared TCB.
  1142. *
  1143. * ERRNO:
  1144. *  S_smMemLib_NOT_INITIALIZED
  1145. *  S_smObjLib_LOCK_TIMEOUT
  1146. *
  1147. * NOMANUAL
  1148. */
  1149. STATUS smObjTcbFree 
  1150.     (
  1151.     SM_OBJ_TCB * pSmObjTcb /* pointer to shared TCB to be freed */
  1152.     )
  1153.     {
  1154.     return (smFixBlkPartFree (smTcbPartId, (char *) pSmObjTcb));
  1155.     }
  1156. /******************************************************************************
  1157. *
  1158. * smObjCpuInfoGet - get information about a single CPU using shared memory
  1159. *
  1160. * This routine obtains a variety of information describing the CPU specified
  1161. * by <cpuNum>.  If <cpuNum> is NONE (-1), this routine returns information
  1162. * about the local (calling) CPU.  The information is returned in a special
  1163. * structure, SM_CPU_INFO, whose address is specified by <pCpuInfo>.  (The
  1164. * structure must have been allocated before this routine is called.)
  1165. *
  1166. * RETURNS: OK, or ERROR.
  1167. *
  1168. * NOMANUAL
  1169. */
  1170. LOCAL STATUS smObjCpuInfoGet
  1171.     (
  1172.     SM_OBJ_DESC *     pSmObjDesc,    /* ptr to shared memory descriptor */
  1173.     int               cpuNum,        /* number of cpu to get info about */
  1174.     SM_OBJ_CPU_INFO * pSmObjCpuInfo  /* cpu info structure to fill */
  1175.     )
  1176.     {
  1177.     SM_CPU_DESC volatile * pCpuDesc; /* ptr to cpu descriptor */
  1178.     int                    tmp;      /* temp storage */
  1179.     /* Report on local cpu if NONE specified */
  1180.     if (cpuNum == NONE)
  1181.         {
  1182.         cpuNum = pSmObjDesc->smDesc.cpuNum;
  1183.         }
  1184.     /* Get info from cpu descriptor */
  1185.     if (cpuNum < 0  ||  cpuNum >= pSmObjDesc->smDesc.maxCpus)
  1186.         {
  1187.         errno = S_smLib_INVALID_CPU_NUMBER;
  1188.         return (ERROR);                 /* cpu number out of range */
  1189.         }
  1190.     /* get address of cpu descr */
  1191.     pCpuDesc = (SM_CPU_DESC volatile *) &(pSmObjDesc->smDesc.cpuTblLocalAdrs 
  1192.                                                                      [cpuNum]);
  1193.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  1194.     tmp = pCpuDesc->status;                     /* PCI bridge bug [SPR 68844]*/
  1195.     pSmObjCpuInfo->smCpuDesc.status  = pCpuDesc->status; 
  1196. /* attached or not attached */
  1197.     pSmObjCpuInfo->smCpuDesc.intType = pCpuDesc->intType;
  1198. /* interrupt type */
  1199.     pSmObjCpuInfo->smCpuDesc.intArg1 = pCpuDesc->intArg1;
  1200. /* interrupt argument #1 */
  1201.     pSmObjCpuInfo->smCpuDesc.intArg2 = pCpuDesc->intArg2;
  1202. /* interrupt argument #2 */
  1203.     pSmObjCpuInfo->smCpuDesc.intArg3 = pCpuDesc->intArg3;
  1204. /* interrupt argument #3 */
  1205.     /* get event Q pointer */
  1206.     pSmObjCpuInfo->pCpuEventQ = &(pSmObjDesc->cpuLocalAdrs[cpuNum].smObjEventQ);
  1207.     return (OK);
  1208.     }
  1209. /******************************************************************************
  1210. *
  1211. * smObjTimeoutLogMsg - notify spin-lock take timeout
  1212. *
  1213. * This routine prints a message on the standard output when an attempt
  1214. * to get lock access on a shared ressource failed if the global
  1215. * boolean smObjTimeoutLog is set to TRUE, otherwise only the error
  1216. * status is set to S_smObjLib_LOCK_TIMEOUT.
  1217. *
  1218. * <routineName> is a string containing the name of the function where
  1219. * attempt to take lock has failed.
  1220. *
  1221. * <lockLocalAdrs> is the local address of the shared memory spin-lock.
  1222. *
  1223. * NOMANUAL
  1224. */
  1225. void smObjTimeoutLogMsg
  1226.     (
  1227.     char * routineName, 
  1228.     char * lockLocalAdrs
  1229.     ) 
  1230.     {
  1231.     if (smObjTimeoutLog)
  1232.         {
  1233. logMsg ("ERROR : %s cannot take lock at address %#x.n", 
  1234. (int) routineName, (int) lockLocalAdrs, 0, 0, 0, 0);
  1235.         }
  1236.     errno = S_smObjLib_LOCK_TIMEOUT;
  1237.     }
  1238. /******************************************************************************
  1239. *
  1240. * smObjTimeoutLogEnable - control logging of failed attempts to take a spin-lock (VxMP Option)
  1241. *
  1242. * This routine enables or disables the printing of a message when
  1243. * an attempt to take a shared memory spin-lock fails.
  1244. *
  1245. * By default, message logging is enabled.
  1246. *
  1247. * AVAILABILITY
  1248. * This routine is distributed as a component of the unbundled shared memory
  1249. * objects support option, VxMP.
  1250. * RETURNS: N/A
  1251. */
  1252. void smObjTimeoutLogEnable
  1253.     (
  1254.     BOOL timeoutLogEnable /* TRUE to enable, FALSE to disable */
  1255.     ) 
  1256.     {
  1257.     smObjTimeoutLog = timeoutLogEnable;
  1258.     }
  1259. /******************************************************************************
  1260. *
  1261. * smObjBeat - increment shared memory objects hearbeat
  1262. *
  1263. * This routine continuously restart itself to increment the shared 
  1264. * memory objects heartbeat.
  1265. *
  1266. * RETURNS: N/A
  1267. *
  1268. * NOMANUAL
  1269. */
  1270. LOCAL void smObjBeat 
  1271.     (
  1272.     UINT * pHeartBeat
  1273.     ) 
  1274.     {
  1275.     int    tmp;           /* temp storage */
  1276.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  1277.     tmp = *pHeartBeat;                          /* PCI bridge bug [SPR 68844]*/
  1278.     *pHeartBeat = htonl (ntohl (*pHeartBeat) + 1); /* increment heartbeat */
  1279.     CACHE_PIPE_FLUSH ();                        /* CACHE FLUSH   [SPR 68334] */
  1280.     tmp = *pHeartBeat;                          /* BRIDGE FLUSH  [SPR 68334] */
  1281.     /* start a watchdog to call ourself every smObjHeartBeatRate */
  1282.     wdStart (smObjWdog, smObjHeartBeatRate, (FUNCPTR) smObjBeat, 
  1283.      (int) pHeartBeat);
  1284.     }
  1285. /******************************************************************************
  1286. *
  1287. * smObjTcbFreeLogMsg - notify shared TCB free failure
  1288. *
  1289. * This routine prints a message on the standard output when 
  1290. * a shared TCB have not been given back to the shared TCB partition 
  1291. * because taskDestroy was unable to take the shared TCB partition spin-lock.
  1292. *
  1293. * NOMANUAL
  1294. */
  1295. void smObjTcbFreeLogMsg (void)
  1296.     {
  1297.     static int failNum;
  1298.     failNum++;
  1299.     if (smObjTimeoutLog)
  1300. {
  1301. logMsg ("WARNING: shared TCB not freed.n", 0, 0, 0, 0, 0, 0); 
  1302. }
  1303.     }