ID Number: Q70258
6.00 6.00a
OS/2
Summary:
Writing your own stack checking functions for the C version 6.00 or
6.00a multithreaded libraries is similar to writing them for the
standard, single-threaded libraries. For complete information on
writing your own version of the standard stack checking routine, query
on the following words:
standard and __chkstk and 6.00a
The following is a list of the differences needed to write your own
multithreaded __chkstk routines for use with the various multithreaded
libraries:
1. The symbol STKHQQ, which indicates the limit of the stack, must be
defined for each thread. This pertains to all the multithreaded
libraries.
2. You must be sure you are operating on the correct data segment when
you are inside the __chkstk function. This pertains only to the
LLIBCDLL.LIB and CDLLOBJS.LIB libraries.
3. If you are replacing the __chkstk functions in the run-time DLL
version (CDLLOBJS.LIB), you must define the near model to call the
far model.
More Information:
The following information is a more thorough discussion of the three
points above:
1. In order to access the thread instance data, there is a new
function in C 6.00 called __gettidtab. This function takes no
arguments and returns a pointer to an instance data structure in
AX:DX. Below is the format of that structure C and assembly
notation:
C Notation
----------
struct _tiddata {
unsigned int _terrno; // errno value
unsigned int _tdoserrno; // _doserrno value
unsigned int _stkhqq; // stack limit
unsigned int _fpds; // Floating Point data segment
unsigned long _holdrand; // rand() seed value
char far * _token; // far * to strtok() token
char far * _errmsg; // far * to strerror() buffer
char far * _namebuf; // far * to tmpfile() buffer
char far * _asctimebuf; // far * to asctime() buffer
void far * _gmtimebuf; // far * to gmtime() structure
void far * _stackalloc; // far * to thread's stack
char _padding[28]; // pad up to pow2 boundary
};
struct _tiddata far * cdecl near _gettidtab(void);
ASM Notation
------------
_tiddata struc
__terrno dw 0 ; errno value
__tdoserrno dw 0 ; _doserrno value
__stkhqq dw 0 ; stack limit
__fpds dw 0 ; Floating Point data segment
__holdrand dd 0 ; rand() seed value
__token dd 0 ; far * to strtok() token
__errmsg dd 0 ; far * to strerror() buffer
__namebuf dd 0 ; far * to tmpfile() buffer
__asctimebuf dd 0 ; far * to asctime() buffer
__gmtimebuf dd 0 ; far * to gmtime() structure
__stackalloc dd 0 ; far * to thread's stack
__padding db 28 dup (0) ; pad up to next pow2 boundary
_tiddata ends
extrn __gettidtab:near
2. Because __chkstk is the *first* thing executed when a function is
called (even before _loadds takes effect), it is imperative that
the data segment be set up correctly. This is easily accomplished
by the following code fragment:
push DS
push DGROUP
pop DS
{ __chkstk code goes here }
pop DS
3. In the CDLLOBJS.LIB model, the actual run-time code is in a
separate DLL. Therefore, all calls to the run time must be made as
far calls. For that reason, the near versions of the __chkstk
function (_aNchkstk and _aNrchkstk) must use the far versions to do
the actual work. Below is an example of the code needed to make that
happen for _aNchkstk:
pop cx ; convert near call into a far call
push cs
push cx
jmp _aFchkstk