home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional Developers Kit 1992 November / Disc01 / Disc01.mdf / runnable / mmos2 / mmtoolkt / samples / fssht / shinit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-06  |  13.7 KB  |  336 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*                    Copyright (c) IBM Corporation 1992                    */
  4. /*                           All Rights Reserved                            */
  5. /*                                                                          */
  6. /* SOURCE FILE NAME: SHINIT.C                                               */
  7. /*                                                                          */
  8. /* DESCRIPTIVE NAME:  Stream Handler Dll Initialization routine             */
  9. /*                                                                          */
  10. /* FUNCTION: This function is called each time a new process loads this     */
  11. /*           DLL.  If this is the first call, we must register with the     */
  12. /*           SSM as a handler.  For each call, we need to allocate any      */
  13. /*           resources needed on a process basis (GetSeg's, etc), and       */
  14. /*           set up an exit list routine to deallocate these resources.     */
  15. /*                                                                          */
  16. /* ENTRY POINTS:                                                            */
  17. /*   _DLL_InitTerm                                                          */
  18. /*   ShExitList                                                             */
  19. /*************************** END OF SPECIFICATIONS **************************/
  20. #define  INCL_NOPMAPI                  /* no PM include files required */
  21. #define  INCL_DOSSEMAPHORES
  22. #define  INCL_DOSPROCESS               /* For exit list defines        */
  23. #define  INCL_DOSERRORS
  24. #define  INCL_DOSMISC
  25. #define  INCL_DOSDEVICES
  26. #include <os2.h>
  27. #include <os2me.h>
  28. #include <hhpheap.h>
  29. #include <shi.h>
  30.  
  31. /************************** START OF SPECIFICATIONS *************************/
  32. /*                                                                          */
  33. /* SUBROUTINE NAME: _DLL_InitTerm                                           */
  34. /*                                                                          */
  35. /* DESCRIPTIVE NAME: Stream Handler Initialization routine                  */
  36. /*                                                                          */
  37. /* FUNCTION:                                                                */
  38. /*                                                                          */
  39. /* NOTES:  This routine utilizes a feature of the IBM C Set/2 Compiler      */
  40. /*         that frees programmers from having to write assembler stubs to   */
  41. /*         initialize their re-entrant DLLs.                                */
  42. /*         C Set/2 provides an assembler initialization stub with the       */
  43. /*         compiler, and that stub sets the entry point of the DLL to       */
  44. /*         _DLL_InitTerm.  As long as the DLL entry point has this name,    */
  45. /*         the DLL can take advantage of the C SET/2 assembler stub instead */
  46. /*         of writing one of it's own.                                      */
  47. /*                                                                          */
  48. /* ENTRY POINT: _DLL_InitTerm                                               */
  49. /*                                                                          */
  50. /*************************** END OF SPECIFICATIONS **************************/
  51. #pragma linkage (_DLL_InitTerm, system)
  52.  
  53. unsigned long _DLL_InitTerm (unsigned long hModhandle, unsigned long fTerm)
  54.  
  55. { /* Start of ShInit */
  56.  
  57. RC rc = NO_ERROR;                       // local return code
  58. PARM_REG smhRegParm;                    // Parameters for SMH_REGISTER
  59. int Registered = FALSE;
  60. int HeapAllocated_Attached = FALSE;
  61. int GlobDataMtxCreated = FALSE;
  62.  
  63.   /*
  64.    * Checking this parameter will insure that this routine will only
  65.    * be run on an actual initialization.  Return success from the
  66.    * termination.
  67.    */
  68.  
  69.   if (fTerm)
  70.      {
  71.      return (1L);
  72.      }
  73.  
  74.   /*
  75.    * Get the semaphore controlling the process count & update the process
  76.    * count if successful.  Then after we have the sem, if the count is
  77.    * one, we are guaranteed that we must do the global initializations.
  78.    *
  79.    * There is a problem that to determine if we need to create or open the
  80.    * semaphore we need to check the ProcessCount to see if this is the
  81.    * first process, but since we don't have the semaphore we don't have
  82.    * a guarentee the count won't change.  If we get caught in this window
  83.    * then we will fail to get the semaphore and the rc will indicate error.
  84.    */
  85.   if (ulProcessCount == 0)
  86.     { /* First process */
  87.       if (!(rc = DosCreateMutexSem(pszProcCntMutexName,
  88.                                    &hmtxProcCnt,
  89.                                    0L,
  90.                                    TRUE)))
  91.         {
  92.           ulProcessCount++;
  93.         }
  94.     } /* First process */
  95.   else
  96.     { /* not first process */
  97.       /* if a process exits and decrements ProcessCount before we get  */
  98.       /* the semaphore here, we will fail. */
  99.       if (!(rc = DosOpenMutexSem(pszProcCntMutexName,
  100.                                  &hmtxProcCnt)))
  101.         {
  102.           if (!(rc = DosRequestMutexSem(hmtxProcCnt,
  103.                                         SEM_INDEFINITE_WAIT)))
  104.             {
  105.               ulProcessCount++;
  106.             }
  107.           else
  108.             {
  109.               DosCloseMutexSem(hmtxProcCnt);
  110.             }
  111.         }
  112.     } /* not first process */
  113.  
  114.   if (!rc)
  115.   { /* Semaphore ok, In critical section */
  116.     /*
  117.      * If this is the first time this init routine is called then we are
  118.      * being brought in by the loader the first time, so we need to register
  119.      * with the SSM.
  120.      */
  121.     if (ulProcessCount == 1)
  122.       { /* First process */
  123.         smhRegParm.ulFunction = SMH_REGISTER;
  124.         smhRegParm.pszSHName = pszHandlerName;
  125.         smhRegParm.phidSrc = &SrcHandlerID;
  126.         smhRegParm.phidTgt = &TgtHandlerID;
  127.         smhRegParm.pshcfnEntry = ( PSHCFN ) ShcRouter;
  128.         smhRegParm.ulFlags = REGISTER_TGT_HNDLR+REGISTER_SRC_HNDLR;
  129.         rc = SMHEntryPoint((PVOID)&smhRegParm);
  130.         /*
  131.          * If ok then allocate our memory pool (heap), since it is under
  132.          * semaphore control create and get the semaphore first.
  133.          */
  134.         if (!rc)
  135.           { /* Register ok */
  136.             Registered = TRUE;
  137.             hHeap = HhpCreateHeap(HEAPSIZE,
  138.                                   HH_SHARED);
  139.             if (hHeap)
  140.               { /* Heap Allocated */
  141.                 HeapAllocated_Attached = TRUE;
  142.                 if (!(rc = DosCreateMutexSem(NULL,
  143.                                              &hmtxGlobalData,
  144.                                              DC_SEM_SHARED,
  145.                                              FALSE)))
  146.                   {
  147.                     GlobDataMtxCreated = TRUE;
  148.                   }
  149.               } /* Heap Allocated */
  150.             else
  151.               { /* Heap not allocated */
  152.                 rc = ERROR_ALLOC_RESOURCES;
  153.               } /* Heap not allocated */
  154.           } /* Register ok */
  155.       } /* First Process */
  156.     else
  157.       { /* Not first process */
  158.         if (!(rc = DosOpenMutexSem(NULL,
  159.                                    &hmtxGlobalData)))
  160.           { /* Global data semaphore opened */
  161.  
  162.             GlobDataMtxCreated = TRUE;
  163.             if (!(rc = DosRequestMutexSem(hmtxGlobalData,
  164.                                           SEM_INDEFINITE_WAIT)))
  165.               { /* Global Data Sem obtained */
  166.  
  167.                 if (HhpAccessHeap(hHeap, HhpGetPID()))
  168.                   { /* Error accessing heap */
  169.                     rc = ERROR_ALLOC_RESOURCES;
  170.                   } /* Error accessing heap */
  171.                 else
  172.                   { /* Heap attached */
  173.                     HeapAllocated_Attached = TRUE;
  174.                   } /* Heap attached */
  175.  
  176.                 DosReleaseMutexSem(hmtxGlobalData);
  177.  
  178.               } /* Global Data Sem obtained */
  179.           } /* Global data semaphore opened */
  180.       } /* Not first process */
  181.  
  182.     /*
  183.      * If things are ok, Register an exit list handler and if that works
  184.      * increment the process count.
  185.      */
  186.     if (!rc)
  187.       {
  188.         rc = DosExitList(EXTLSTADD_ORDER,
  189.                          (PFNEXITLIST)ShExitList);
  190.       }
  191.  
  192.     if (rc)
  193.       { /* Error occurred - Clean Up */
  194.         if (HeapAllocated_Attached)
  195.           {
  196.             HhpReleaseHeap(hHeap,
  197.                            HhpGetPID());
  198.           }
  199.         if (GlobDataMtxCreated)
  200.           {
  201.             DosCloseMutexSem(hmtxGlobalData);
  202.           }
  203.         if (Registered)
  204.           { /* Deregister */
  205.             PARM_DEREG smhDeregParm;
  206.  
  207.             smhDeregParm.ulFunction = SMH_DEREGISTER;
  208.             smhDeregParm.pszSHName = pszHandlerName;
  209.             SMHEntryPoint(&smhDeregParm);
  210.           } /* Deregister */
  211.         ulProcessCount--;
  212.         DosReleaseMutexSem(hmtxProcCnt);
  213.         DosCloseMutexSem(hmtxProcCnt);
  214.       } /* Error occurred - Clean Up */
  215.     else
  216.       {
  217.         DosReleaseMutexSem(hmtxProcCnt);
  218.       }
  219.  
  220.   } /* Semaphore ok, In critical section */
  221.   /*
  222.    * The return codes expected are:
  223.    *  TRUE (any non-zero) - init routine worked
  224.    *  FALSE (zero)        - init routine failed
  225.    *
  226.    * So we have to reverse the local rc before we pass it back.
  227.    */
  228.   return(!rc);
  229.  
  230. } /* End of SHInit */
  231.  
  232. /************************** START OF SPECIFICATIONS *************************/
  233. /*                                                                          */
  234. /* SUBROUTINE NAME: ShExitList                                              */
  235. /*                                                                          */
  236. /* DESCRIPTIVE NAME: Stream Hanlder Exit List routine                       */
  237. /*                                                                          */
  238. /* FUNCTION: Clean up resources allocated for each process, and if this is  */
  239. /*           the last process, then deregister with the SSM.                */
  240. /*           In all cases we need to destroy all streams owned by this      */
  241. /*           process.                                                       */
  242. /*                                                                          */
  243. /* ENTRY POINT:                                                             */
  244. /*   LINKAGE:   CALL NEAR (0:32)                                            */
  245. /*                                                                          */
  246. /* INPUT:                                                                   */
  247. /*                                                                          */
  248. /* EXIT-NORMAL:                                                             */
  249. /*                                                                          */
  250. /* EXIT-ERROR:                                                              */
  251. /*                                                                          */
  252. /* SIDE EFFECTS:                                                            */
  253. /*                                                                          */
  254. /* INTERNAL REFERENCES:                                                     */
  255. /*        ROUTINES:                                                         */
  256. /*                                                                          */
  257. /* EXTERNAL REFERENCES:                                                     */
  258. /*        ROUTINES:                                                         */
  259. /*        DATA STRUCTURES:                                                  */
  260. /*                                                                          */
  261. /*************************** END OF SPECIFICATIONS **************************/
  262.  
  263. VOID APIENTRY ShExitList()
  264.  
  265. { /* Start of ShExitList */
  266.  
  267. PSIB psib;                              // Stream instance block
  268. PSIB psibToDestroy = NULL;              // Stream instance block to destroy
  269. PARM_DESTROY dyparm;                    // parameter block to destroy routine
  270. PID  pid;                               // Process ID
  271.  
  272.   /*
  273.    * There is nothing we can do if calls fail, so don't bother checking.
  274.    */
  275.  
  276.   DosRequestMutexSem(hmtxProcCnt, SEM_INDEFINITE_WAIT);
  277.   /*
  278.    * If this is the last process we will be removed from memory, so
  279.    * call SSM to deregister.
  280.    */
  281.  
  282.   if (ulProcessCount == 1)
  283.     {
  284.       PARM_DEREG smhDeregParm;
  285.  
  286.       smhDeregParm.ulFunction = SMH_DEREGISTER;
  287.       smhDeregParm.pszSHName = pszHandlerName;
  288.       SMHEntryPoint(&smhDeregParm);
  289.     }
  290.  
  291.   //
  292.   // We need to call destroy for each stream created by this process.
  293.   //   Get the PID, and the global data semaphore.
  294.   //   Search the SIB chain for this process's stream instances.
  295.   //   Call destroy to destroy the stream instances
  296.   //   Release the global data semaphore
  297.   //
  298.   pid = HhpGetPID();
  299.   DosRequestMutexSem(hmtxGlobalData, SEM_INDEFINITE_WAIT);
  300.   psib = pSIB_list_head;
  301.   while (psib)
  302.     {
  303.       if (psib->ProcessID == pid)
  304.         {
  305.           psibToDestroy = psib;
  306.           psib = psib->pnxtSIB;
  307.           psibToDestroy->ulActionFlags |= SIBACTFLG_THREAD_DEAD;
  308.           dyparm.hstream = psibToDestroy->hStream;
  309.           dyparm.hid = psibToDestroy->HandlerID;
  310.           ShcDestroy(&dyparm);
  311.         }
  312.       else
  313.         {
  314.           psib = psib->pnxtSIB;
  315.         }
  316.     }
  317.  
  318.   /*
  319.    * Unattach from the memory pool, and from the Global data semaphore
  320.    */
  321.   HhpReleaseHeap(hHeap, pid);
  322.   DosReleaseMutexSem(hmtxGlobalData);
  323.   DosCloseMutexSem(hmtxGlobalData);
  324.  
  325.   //
  326.   // Clean up the process count variable and it's semaphore.
  327.   //
  328.   ulProcessCount--;
  329.   DosReleaseMutexSem(hmtxProcCnt);
  330.   DosCloseMutexSem(hmtxProcCnt);
  331.  
  332.   DosExitList(EXLST_EXIT, (PFNEXITLIST)ShExitList);
  333.  
  334. } /* End of ShExitList */
  335.  
  336.