Library Name |
Description |
LIBC.LIB |
Statically linked library for single-threaded applications (this is the default library chosen when you create a new project). |
LIBCD.LIB |
Statically linked debug version of the library for single-threaded applications. |
LIBCMT.LIB |
Statically linked release version of the library for multithreaded applications. |
LIBCMTD.LIB |
Statically linked debug version of the library for multithreaded applications. |
MSVCRT.LIB |
Import library for dynamically linking the release version of the MSVCRT.DLL library. The library supports both single-threaded and multithreaded applications. |
MSVCRTD.LIB |
Import library for dynamically linking the debug version of the MSVCRT.DLL library. The library supports both single-threaded and multithreaded applications. |
Figure 3 _beginthreadex Pseudocode
unsigned long __cdecl _beginthreadex (
void *psa,
unsigned cbStack,
unsigned (__stdcall * pfnStartAddr) (void *),
void * pvParam,
unsigned fdwCreate,
unsigned *pdwThreadID) {
_ptiddata ptd; // Pointer to thread's data block
unsigned long thdl; // Thread's handle
// Allocate data block for the new thread
if ((ptd = calloccrt(1, sizeof(struct tiddata))) == NULL)
goto errorreturn;
// Initialize the data block
initptd(ptd);
// Save the desired thread function and the parameter
// we want it to get in the data block
ptd->_initaddr = (void *) pfnStartAddr;
ptd->_initarg = pvParam;
// Create the new thread
thdl = (unsigned long) CreateThread(psa, cbStack,
_threadstartex, (PVOID) ptd, fdwCreate, pdwThreadID);
if (thdl == NULL) {
// Thread couldn't be created, cleanup and return failure
goto error_return;
}
// Create created OK, return the handle
return(thdl);
error_return:
// Error: data block or thread couldn't be created
_free_crt(ptd);
return((unsigned long)0L);
}
Figure 4 The tiddata Structure
struct _tiddata {
unsigned long _tid; /* thread ID */
unsigned long _thandle; /* thread handle */
int _terrno; /* errno value */
unsigned long _tdoserrno; /* _doserrno value */
unsigned int _fpds; /* Floating Point data segment */
unsigned long _holdrand; /* rand() seed value */
char * _token; /* ptr to strtok() token */
#ifdef _WIN32
wchar_t * _wtoken; /* ptr to wcstok() token */
#endif /* _WIN32 */
unsigned char * _mtoken; /* ptr to _mbstok() token */
/* following pointers get malloc'd at runtime */
char * _errmsg; /* ptr to strerror()/_strerror() buff */
char * _namebuf0; /* ptr to tmpnam() buffer */
#ifdef _WIN32
wchar_t * _wnamebuf0; /* ptr to _wtmpnam() buffer */
#endif /* _WIN32 */
char * _namebuf1; /* ptr to tmpfile() buffer */
#ifdef _WIN32
wchar_t * _wnamebuf1; /* ptr to _wtmpfile() buffer */
#endif /* _WIN32 */
char * _asctimebuf; /* ptr to asctime() buffer */
#ifdef _WIN32
wchar_t * _wasctimebuf; /* ptr to _wasctime() buffer */
#endif /* _WIN32 */
void * _gmtimebuf; /* ptr to gmtime() structure */
char * _cvtbuf; /* ptr to ecvt()/fcvt buffer */
/* following fields are needed by _beginthread code */
void * _initaddr; /* initial user thread address */
void * _initarg; /* initial user thread argument */
/* following three fields are needed to support signal handling and
* runtime errors */
void * _pxcptacttab; /* ptr to exception-action table */
void * _tpxcptinfoptrs; /* ptr to exception info pointers */
int _tfpecode; /* float point exception code */
/* following field is needed by NLG routines */
unsigned long _NLG_dwCode;
/*
* Per-Thread data needed by C++ Exception Handling
*/
void * _terminate; /* terminate() routine */
void * _unexpected; /* unexpected() routine */
void * _translator; /* S.E. translator */
void * _curexception; /* current exception */
void * _curcontext; /* current exception context */
#if defined (_M_MRX000)
void * _pFrameInfoChain;
void * _pUnwindContext;
void * _pExitContext;
int _MipsPtdDelta;
int _MipsPtdEpsilon;
#elif defined (_M_PPC)
void * _pExitContext;
void * _pUnwindContext;
void * _pFrameInfoChain;
int _FrameInfo[6];
#endif /* defined (_M_PPC) */
};
typedef struct _tiddata * _ptiddata;
Figure 5 _threadstartex Pseudocode
static unsigned long WINAPI _threadstartex (void* ptd) {
// Note: ptd is the address of this thread's tiddata block
// Associate the tiddata block with this thread
TlsSetValue(__tlsindex, ptd);
// Save this thread ID in the tiddata block
((_ptiddata) ptd)->_tid = GetCurrentThreadId();
// Initialize floating-point support (code not shown)
// Wrap desired thread function in SEH frame to
// handle runtime errors and signal support
__try {
// Call desired thread function passing it the desired parameter
// Pass threads exit code value to _endthreadex
_endthreadex(
( (unsigned (WINAPI *)(void *))(((_ptiddata)ptd)->_initaddr) )
( ((_ptiddata)ptd)->_initarg ) ) ;
}
__except(_XcptFilter(GetExceptionCode(), GetExceptionInformation()){
// The C-Runtime's exception handler deals with runtime errors
// and signal support, we should never get it here.
_exit(GetExceptionCode());
}
// We never get here, the thread dies in this function
return(0L);
}