home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / thread.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  6KB  |  244 lines

  1. /***
  2. *thread.c - Begin and end a thread
  3. *
  4. *       Copyright (c) 1989-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       This source contains the _beginthread() and _endthread()
  8. *       routines which are used to start and terminate a thread.
  9. *
  10. *******************************************************************************/
  11.  
  12. #ifdef _MT
  13.  
  14. #include <cruntime.h>
  15. #include <oscalls.h>
  16. #include <internal.h>
  17. #include <mtdll.h>
  18. #include <msdos.h>
  19. #include <malloc.h>
  20. #include <process.h>
  21. #include <rterr.h>
  22. #include <dbgint.h>
  23.  
  24. /*
  25.  * Startup code for new thread.
  26.  */
  27. static unsigned long WINAPI _threadstart(void *);
  28.  
  29. /*
  30.  * declare pointers to per-thread FP initialization and termination routines
  31.  */
  32. _PVFV _FPmtinit;
  33. _PVFV _FPmtterm;
  34.  
  35.  
  36. /***
  37. *_beginthread() - Create a child thread
  38. *
  39. *Purpose:
  40. *       Create a child thread.
  41. *
  42. *Entry:
  43. *       initialcode = pointer to thread's startup code address
  44. *       stacksize = size of stack
  45. *       argument = argument to be passed to new thread
  46. *
  47. *Exit:
  48. *       success = handle for new thread if successful
  49. *
  50. *       failure = (unsigned long) -1L in case of error, errno and _doserrno
  51. *                 are set
  52. *
  53. *Exceptions:
  54. *
  55. *******************************************************************************/
  56.  
  57. unsigned long __cdecl _beginthread (
  58.         void (__cdecl * initialcode) (void *),
  59.         unsigned stacksize,
  60.         void * argument
  61.         )
  62. {
  63.         _ptiddata ptd;                  /* pointer to per-thread data */
  64.         unsigned long thdl;             /* thread handle */
  65.         unsigned long errcode = 0L;     /* Return from GetLastError() */
  66.  
  67.         /*
  68.          * Allocate and initialize a per-thread data structure for the to-
  69.          * be-created thread.
  70.          */
  71.         if ( (ptd = _calloc_crt(1, sizeof(struct _tiddata))) == NULL )
  72.                 goto error_return;
  73.  
  74.         /*
  75.          * Initialize the per-thread data
  76.          */
  77.  
  78.         _initptd(ptd);
  79.  
  80.         ptd->_initaddr = (void *) initialcode;
  81.         ptd->_initarg = argument;
  82.  
  83.         /*
  84.          * Create the new thread. Bring it up in a suspended state so that
  85.          * the _thandle and _tid fields are filled in before execution
  86.          * starts.
  87.          */
  88.         if ( (ptd->_thandle = thdl = (unsigned long)
  89.               CreateThread( NULL,
  90.                             stacksize,
  91.                             _threadstart,
  92.                             (LPVOID)ptd,
  93.                             CREATE_SUSPENDED,
  94.                             (LPDWORD)&(ptd->_tid) ))
  95.              == 0L )
  96.         {
  97.                 errcode = GetLastError();
  98.                 goto error_return;
  99.         }
  100.  
  101.         /*
  102.          * Start the new thread executing
  103.          */
  104.         if ( ResumeThread( (HANDLE)thdl ) == (DWORD)(-1L) ) {
  105.                 errcode = GetLastError();
  106.                 goto error_return;
  107.         }
  108.  
  109.         /*
  110.          * Good return
  111.          */
  112.         return(thdl);
  113.  
  114.         /*
  115.          * Error return
  116.          */
  117. error_return:
  118.         /*
  119.          * Either ptd is NULL, or it points to the no-longer-necessary block
  120.          * calloc-ed for the _tiddata struct which should now be freed up.
  121.          */
  122.         _free_crt(ptd);
  123.  
  124.         /*
  125.          * Map the error, if necessary.
  126.          */
  127.         if ( errcode != 0L )
  128.                 _dosmaperr(errcode);
  129.  
  130.         return((unsigned long)-1L);
  131. }
  132.  
  133.  
  134. /***
  135. *_threadstart() - New thread begins here
  136. *
  137. *Purpose:
  138. *       The new thread begins execution here.  This routine, in turn,
  139. *       passes control to the user's code.
  140. *
  141. *Entry:
  142. *       void *ptd       = pointer to _tiddata structure for this thread
  143. *
  144. *Exit:
  145. *       Never returns - terminates thread!
  146. *
  147. *Exceptions:
  148. *
  149. *******************************************************************************/
  150.  
  151. static unsigned long WINAPI _threadstart (
  152.         void * ptd
  153.         )
  154. {
  155.         /*
  156.          * Stash the pointer to the per-thread data stucture in TLS
  157.          */
  158.         if ( !TlsSetValue(__tlsindex, ptd) )
  159.                 _amsg_exit(_RT_THREAD);
  160.  
  161.         /*
  162.          * Call fp initialization, if necessary
  163.          */
  164.         if ( _FPmtinit != NULL )
  165.                 (*_FPmtinit)();
  166.  
  167.         /*
  168.          * Guard call to user code with a _try - _except statement to
  169.          * implement runtime errors and signal support
  170.          */
  171.         __try {
  172.                 ( (void(__cdecl *)(void *))(((_ptiddata)ptd)->_initaddr) )
  173.                     ( ((_ptiddata)ptd)->_initarg );
  174.  
  175.                 _endthread();
  176.         }
  177.         __except ( _XcptFilter(GetExceptionCode(), GetExceptionInformation()) )
  178.         {
  179.                 /*
  180.                  * Should never reach here
  181.                  */
  182.                 _exit( GetExceptionCode() );
  183.  
  184.         } /* end of _try - _except */
  185.  
  186.         /*
  187.          * Never executed!
  188.          */
  189.         return(0L);
  190. }
  191.  
  192.  
  193. /***
  194. *_endthread() - Terminate the calling thread
  195. *
  196. *Purpose:
  197. *
  198. *Entry:
  199. *       void
  200. *
  201. *Exit:
  202. *       Never returns!
  203. *
  204. *Exceptions:
  205. *
  206. *******************************************************************************/
  207.  
  208. void __cdecl _endthread (
  209.         void
  210.         )
  211. {
  212.         _ptiddata ptd;           /* pointer to thread's _tiddata struct */
  213.  
  214.         /*
  215.          * Call fp termination, if necessary
  216.          */
  217.         if ( _FPmtterm != NULL )
  218.                 (*_FPmtterm)();
  219.  
  220.         if ( (ptd = _getptd()) == NULL )
  221.                 _amsg_exit(_RT_THREAD);
  222.  
  223.         /*
  224.          * Close the thread handle (if there was one)
  225.          */
  226.         if ( ptd->_thandle != (unsigned long)(-1L) )
  227.                 (void) CloseHandle( (HANDLE)(ptd->_thandle) );
  228.  
  229.         /*
  230.          * Free up the _tiddata structure & its subordinate buffers
  231.          *      _freeptd() will also clear the value for this thread
  232.          *      of the TLS variable __tlsindex.
  233.          */
  234.         _freeptd(ptd);
  235.  
  236.         /*
  237.          * Terminate the thread
  238.          */
  239.         ExitThread(0);
  240.  
  241. }
  242.  
  243. #endif  /* _MT */
  244.