home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / k95source / ckothr.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  11KB  |  412 lines

  1. /* C K O T H R  --  Kermit thread management functions for OS/2 and NT systems */
  2.  
  3. /*
  4.   Author: Jeffrey Altman (jaltman@secure-endpoints.com),
  5.             Secure Endpoints Inc., New York City.
  6.  
  7.   Copyright (C) 1996,2004, Trustees of Columbia University in the City of New
  8.   York.
  9. */
  10.  
  11. #include "ckcdeb.h"                     /* Debug & other symbols */
  12. #ifdef NT
  13. #include <windows.h>
  14. #else /* NT */
  15. #define INCL_WIN
  16. #define INCL_VIO
  17. #define INCL_ERRORS
  18. #define INCL_DOSPROCESS
  19. #define INCL_DOSSEMAPHORES
  20. #define INCL_DOSDEVIOCTL
  21. #define INCL_WINCLIPBOARD
  22. #define INCL_DOSDATETIME
  23. #include <os2.h>
  24. #undef COMMENT                /* COMMENT is defined in os2.h */
  25. #endif /* NT */
  26. #include "ckothr.h"
  27.  
  28. #ifdef NT
  29. #include <setjmpex.h>
  30. #else /* NT */
  31. #include <setjmp.h>
  32. #endif /* NT */
  33. #include "ckcsig.h"
  34. extern int isinterrupted ;
  35.  
  36. #define MAXTHREAD 16
  37. struct _threadinfo threads[MAXTHREAD];
  38.  
  39. static int
  40. findfreeindex( void )
  41. {
  42.    int i = 0 ;
  43.    for ( i = 0 ; i<MAXTHREAD ; i++ )
  44.    {
  45.       if ( !threads[i].inuse )
  46.          return i ;
  47.    }
  48.    return -1 ;
  49. }
  50.  
  51. static int
  52. #ifdef NT
  53. findthreadindex( HANDLE id )
  54. #else
  55. findthreadindex( TID id )
  56. #endif
  57. {
  58.    int i = 0 ;
  59.    for ( i = 0 ; i<MAXTHREAD ; i++ )
  60.    {
  61.       if ( threads[i].inuse && threads[i].id == id )
  62.       {
  63.          debug(F101,"ckothr findthreadindex - found","",i);
  64.          return i ;
  65.       }
  66.    }
  67.    debug(F101,"ckothr findthreadindex - not found","",-1);
  68.    return -1 ;
  69. }
  70.  
  71. static void
  72. insertchildintoparent( int child, int parent )
  73. {
  74.    int sibling = 0 ;
  75.  
  76.    debug(F101,"ckothr insertchildintoparent - parent","",parent) ;
  77.    debug(F101,"ckothr insertchildintoparent - child","",child) ;
  78.  
  79.    if ( parent < 0 || parent >= MAXTHREAD )
  80.       return ;
  81.  
  82.    if ( threads[parent].child < 0 )
  83.    {
  84.       threads[parent].child = child ;
  85.    }
  86.    else
  87.    {
  88.       sibling = threads[parent].child ;
  89.       while ( threads[sibling].sibling >= 0 )
  90.          sibling = threads[sibling].sibling ;
  91.       threads[sibling].child = child ;
  92.    }
  93. }
  94.  
  95. static void
  96. removechildfromparent( int child, int parent )
  97. {
  98.    int sibling = 0 ;
  99.  
  100.    debug(F101,"ckothr removechildfromparent - parent","",parent) ;
  101.    debug(F101,"ckothr removechildfromparent - child","",child) ;
  102.  
  103.    if ( parent < 0 || parent >= MAXTHREAD )
  104.       return ;
  105.  
  106.  
  107.    if ( threads[parent].child < 0 )
  108.    {
  109.       return ;
  110.    }
  111.    else if ( threads[parent].child == child )
  112.    {
  113.       threads[parent].child = threads[child].sibling ;
  114. #ifdef NT
  115.       threads[child].parent = (HANDLE) -1 ;
  116. #else
  117.       threads[child].parent = (TID) -1 ;
  118. #endif
  119.  
  120.    }
  121.    else
  122.    {
  123.       sibling = threads[parent].child ;
  124.       while ( threads[sibling].sibling != child &&
  125.               threads[sibling].sibling >= 0)
  126.          sibling = threads[sibling].sibling ;
  127.  
  128.       if ( threads[sibling].sibling < 0 )
  129.          return ;
  130.  
  131.       threads[sibling].sibling = threads[child].sibling ;
  132.    }
  133. }
  134.  
  135. /*
  136.     If manage is TRUE, then we will add the new thread to our thread structures.
  137.     This requires that parent be a valid thread handle
  138. */
  139. TID
  140. #ifdef NT
  141. ckThreadBegin( void (*func)(void *), ULONG stacksize, void * param, BOOL manage, HANDLE parent )
  142. #else
  143. ckThreadBegin( void (*func)(void *), ULONG stacksize, void * param, BOOL manage, TID parent )
  144. #endif
  145. {
  146.     int newthread, parentthread ;
  147. #ifdef NT
  148.     HANDLE hevThread ;
  149. #else /* NT */
  150.     HEV hevThread ;
  151. #endif /* NT */
  152.  
  153.     while (RequestThreadMgmtMutex(250))
  154.     {
  155. #ifdef NTSIG
  156.         ck_ih();
  157. #else
  158.         ;
  159. #endif /* NTSIG */
  160.     }
  161.  
  162.     if ( manage )
  163.     {
  164.         newthread = findfreeindex() ;
  165.         debug(F101,"ckothr ckThreadBegin newthread","",newthread ) ;
  166.         if ( newthread < 0 )
  167.         {
  168.             ReleaseThreadMgmtMutex() ;
  169.             return (TID) -1 ;
  170.         }
  171.  
  172.         threads[newthread].inuse = TRUE ;
  173.         threads[newthread].child = -1 ;
  174.         threads[newthread].sibling = -1 ;
  175.         threads[newthread].id = 0 ;
  176.  
  177.  
  178.         if (param)
  179.             threads[newthread].CompletionSem =
  180. #ifdef NT
  181.                 *((HANDLE *) param) ;
  182. #else
  183.                 *((HEV *) param) ;
  184. #endif /* NT*/
  185.  
  186.       /* create an event semaphore for new thread        */
  187. #ifdef NT
  188.         hevThread = CreateEvent( NULL, TRUE, FALSE, NULL ) ;
  189. #else
  190.         DosCreateEventSem( NULL, &hevThread, DC_SEM_SHARED, FALSE ) ;
  191. #endif /* NT */
  192.         threads[newthread].DieSem = hevThread ;
  193.  
  194.         threads[newthread].id = (TID) _beginthread( func,
  195. #ifndef NT
  196.                                                   0,
  197. #endif /* NT */
  198.                                                   stacksize,
  199.                                                   (void *)&threads[newthread]
  200.                                                   ) ;
  201.  
  202.         threads[newthread].parent = parent ;
  203.         parentthread = findthreadindex( parent ) ;
  204.         insertchildintoparent( newthread, parentthread ) ;
  205.  
  206.         debug(F101,"ckothr threads->inuse","",  threads[newthread].inuse) ;
  207.         debug(F101,"ckothr threads->child","",  threads[newthread].child) ;
  208.         debug(F101,"ckothr threads->sibling","",threads[newthread].sibling) ;
  209.         debug(F101,"ckothr ckThreadBegin TID","",threads[newthread].id) ;
  210.         ReleaseThreadMgmtMutex() ;
  211.         return threads[newthread].id;
  212.    }
  213.    else
  214.    {
  215.        TID tid ;
  216.        tid = (TID) _beginthread( func,
  217. #ifndef NT
  218.                                 0,
  219. #endif /* NT */
  220.                                 stacksize,
  221.                                 param ) ;
  222.        debug(F101,"ckothr ckThreadBegin TID","",tid) ;
  223.        ReleaseThreadMgmtMutex() ;
  224.        return tid;
  225.    }
  226. }
  227.  
  228. BOOL
  229. ckThreadKill( TID startthread )
  230. {
  231.     int found = 0 ;
  232.     int where = 999 ;
  233.     int i ;
  234.     int myindex = 0, parentindex = 0 ;
  235.  
  236.     while (RequestThreadMgmtMutex(250))
  237.     {
  238. #ifdef NTSIG
  239.         ck_ih();
  240. #else
  241.         ;
  242. #endif /* NTSIG */
  243.     }
  244.  
  245.     debug(F101,"ckothr ckThreadKill TID","",startthread ) ;
  246.     myindex = findthreadindex( startthread ) ;
  247.     if ( myindex >= 0 )
  248.     {
  249.         debug(F101,"ckothr threads->inuse","",  threads[myindex].inuse) ;
  250.         debug(F101,"ckothr threads->child","",  threads[myindex].child) ;
  251.         debug(F101,"ckothr threads->sibling","",threads[myindex].sibling) ;
  252.  
  253.         parentindex = findthreadindex( threads[myindex].parent ) ;
  254.         removechildfromparent( myindex, parentindex ) ;
  255.  
  256.         while ( threads[myindex].child >= 0 )
  257.         {
  258.             int child = threads[myindex].child ;
  259.             ckThreadKill( threads[child].id ) ;
  260.  
  261.             debug(F101,"ckothr threads->inuse","",  threads[myindex].inuse) ;
  262.             debug(F101,"ckothr threads->child","",  threads[myindex].child) ;
  263.             debug(F101,"ckothr threads->sibling","",threads[myindex].sibling) ;
  264.  
  265.             if ( threads[myindex].child >= 0 )
  266.             {
  267.                 debug(F101,"ckThreadKill failed to find kill child","",0);
  268.                 threads[myindex].child = -1 ;
  269.             }
  270.         }
  271.  
  272. #ifdef NT
  273.         isinterrupted = 1 ;
  274.         /* Not safe to terminate threads */
  275.         /* TerminateThread( threads[threadindex].id, -1 ) ; */
  276.         PostSem( threads[myindex].DieSem ) ;
  277.         if ( threads[myindex].CompletionSem ) {
  278.             WaitSem( threads[myindex].CompletionSem, SEM_INDEFINITE_WAIT );
  279.             /* CompletionSem will be cleared by starting thread */
  280.         }
  281.         else
  282.             msleep(50);
  283.  
  284.         /* we would like to wait for the completion of the thread but that is
  285.            not currently practical
  286.         */
  287.         CloseHandle( threads[myindex].DieSem ) ;
  288.  
  289. #ifdef COMMENT
  290.         /* Do not do this.  The handle will be closed by endthread() */
  291.         if (threads[myindex].id) {
  292.             CloseHandle( threads[myindex].id ) ;
  293.         }
  294. #endif /* COMMENT */
  295.         threads[myindex].handle = 0 ;
  296. #else /* NT */
  297.         DosKillThread( threads[myindex].id ) ;
  298. #endif /* NT */
  299.         threads[myindex].id = 0 ;
  300.         threads[myindex].CompletionSem = 0 ;
  301.         threads[myindex].DieSem = 0 ;
  302.         threads[myindex].inuse = 0 ;
  303.     }
  304.  
  305.     ReleaseThreadMgmtMutex() ;
  306.     return TRUE;
  307. }
  308.  
  309. void
  310. ckThreadEnd( void * param )
  311. {
  312.     struct _threadinfo * threadinfo ;
  313.     debug(F100,"ckothr ckThreadEnd","",0);
  314.     while (RequestThreadMgmtMutex(250))
  315.     {
  316. #ifdef NTSIG
  317.         ck_ih();
  318. #else
  319.         ;
  320. #endif /* NTSIG */
  321.     }
  322.     if ( param )
  323.     {
  324.         int myindex = 0 ;
  325.         int parentindex = 0 ;
  326.  
  327.         threadinfo = (struct _threadinfo *) param ;
  328.         debug(F101,"ckothr ckThreadEnd","",threadinfo->id) ;
  329.         myindex = findthreadindex( threadinfo->id ) ;
  330.         if ( myindex >= 0 )
  331.         {
  332.             debug(F101,"ckothr threads->inuse","",  threads[myindex].inuse) ;
  333.             debug(F101,"ckothr threads->child","",  threads[myindex].child) ;
  334.             debug(F101,"ckothr threads->sibling","",threads[myindex].sibling) ;
  335.  
  336.             parentindex = findthreadindex( threads[myindex].parent ) ;
  337.             removechildfromparent( myindex, parentindex ) ;
  338.  
  339.             while ( threads[myindex].child >= 0 )
  340.             {
  341.                 int child = threads[myindex].child ;
  342.                 ckThreadKill( threads[child].id ) ;
  343.  
  344.                 debug(F101,"ckothr threads->inuse","",  threads[myindex].inuse) ;
  345.                 debug(F101,"ckothr threads->child","",  threads[myindex].child) ;
  346.                 debug(F101,"ckothr threads->sibling","",threads[myindex].sibling) ;
  347.             }
  348.  
  349.             if ( threadinfo->CompletionSem )
  350.                 PostSem( threadinfo->CompletionSem ) ;
  351.             /* if CompletionSem was set, then it was set by the thread started it */
  352. #ifdef NT
  353.             CloseHandle( threads[myindex].DieSem ) ;
  354. #else /* NT */
  355.             DosCloseEventSem( threads[myindex].DieSem ) ;
  356. #endif /* NT */
  357.             threads[myindex].id = 0 ;
  358.             threads[myindex].CompletionSem = 0 ;
  359.             threads[myindex].DieSem = 0 ;
  360.             threads[myindex].inuse = 0 ;
  361.         }
  362.         else
  363.         {
  364.             PostSem( threadinfo->CompletionSem ) ;
  365. #ifdef NT
  366.             CloseHandle( threadinfo->DieSem ) ;
  367. #else /* NT */
  368.             DosCloseEventSem( threadinfo->DieSem ) ;
  369. #endif /* NT */
  370.             threadinfo->id = 0 ;
  371.             threadinfo->CompletionSem = 0 ;
  372.             threadinfo->DieSem = 0 ;
  373.             threadinfo->inuse = 0 ;
  374.         }
  375.     }
  376.     else
  377.     {
  378.         /* must look up the threadinfo block */
  379.         /* Post the Completion Sem and then  */
  380.         /* call ckThreadCleanup on the id    */
  381.     }
  382.     ReleaseThreadMgmtMutex() ;
  383.     _endthread() ;
  384. }
  385.  
  386. void
  387. ckThreadDie( void * param )
  388. {
  389.    struct _threadinfo * threadinfo ;
  390.    debug(F100,"ckothr ckThreadDie","",0);
  391. #ifdef NT
  392.    if ( param )
  393.    {
  394.       threadinfo = (struct _threadinfo *) param ;
  395.       debug(F101,"ckothr ckThreadDie","",threadinfo->id) ;
  396.       PostSem( threadinfo->CompletionSem ) ;
  397.  
  398.       debug(F101,"ckothr threads->inuse","",  threadinfo->inuse) ;
  399.       debug(F101,"ckothr threads->child","",  threadinfo->child) ;
  400.       debug(F101,"ckothr threads->sibling","",threadinfo->sibling) ;
  401.    }
  402.    else
  403.    {
  404.     /* must look up the threadinfo block */
  405.     /* Post the Completion Sem and then  */
  406.     /* call ckThreadCleanup on the id    */
  407.    }
  408. #endif
  409.   _endthread() ;
  410. }
  411.  
  412.