1 /*
2  * The contents of this file are subject to the Mozilla Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is the Netscape Portable Runtime library.
13  *
14  * The Initial Developer of the Original Code is Netscape
15  * Communications Corporation.  Portions created by Netscape are
16  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
17  * Rights Reserved.
18  *
19  * Contributor(s):  Silicon Graphics, Inc.
20  *
21  * Portions created by SGI are Copyright (C) 2000-2001 Silicon
22  * Graphics, Inc.  All Rights Reserved.
23  *
24  * Alternatively, the contents of this file may be used under the
25  * terms of the GNU General Public License Version 2 or later (the
26  * "GPL"), in which case the provisions of the GPL are applicable
27  * instead of those above.  If you wish to allow use of your
28  * version of this file only under the terms of the GPL and not to
29  * allow others to use your version of this file under the MPL,
30  * indicate your decision by deleting the provisions above and
31  * replace them with the notice and other provisions required by
32  * the GPL.  If you do not delete the provisions above, a recipient
33  * may use your version of this file under either the MPL or the
34  * GPL.
35  */
36 
37 /*
38  * This file is derived directly from Netscape Communications Corporation,
39  * and consists of extensive modifications made during the year(s) 1999-2000.
40  */
41 
42 #ifndef __ST_MD_H__
43 #define __ST_MD_H__
44 
45 #if defined(ETIMEDOUT) && !defined(ETIME)
46 #define ETIME ETIMEDOUT
47 #endif
48 
49 #if defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
50 #define MAP_ANON MAP_ANONYMOUS
51 #endif
52 
53 #ifndef MAP_FAILED
54 #define MAP_FAILED -1
55 #endif
56 
57 /*****************************************
58  * Platform specifics
59  */
60 
61 #if defined (AIX)
62 
63 #define MD_STACK_GROWS_DOWN
64 #define MD_USE_SYSV_ANON_MMAP
65 #define MD_ACCEPT_NB_INHERITED
66 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
67 
68 #ifndef MD_HAVE_SOCKLEN_T
69 #define MD_HAVE_SOCKLEN_T
70 #define socklen_t unsigned long
71 #endif
72 
73 #define MD_SETJMP(env) _setjmp(env)
74 #define MD_LONGJMP(env, val) _longjmp(env, val)
75 
76 #define MD_INIT_CONTEXT(_thread, _sp, _main) \
77   ST_BEGIN_MACRO                             \
78   if (MD_SETJMP((_thread)->context))         \
79     _main();                                 \
80   (_thread)->context[3] = (long) (_sp);      \
81   ST_END_MACRO
82 
83 #define MD_GET_UTIME()                        \
84   timebasestruct_t rt;                        \
85   (void) read_real_time(&rt, TIMEBASE_SZ);    \
86   (void) time_base_to_time(&rt, TIMEBASE_SZ); \
87   return (rt.tb_high * 1000000LL + rt.tb_low / 1000)
88 
89 #elif defined (CYGWIN)
90 
91 #define MD_STACK_GROWS_DOWN
92 #define MD_USE_BSD_ANON_MMAP
93 #define MD_ACCEPT_NB_NOT_INHERITED
94 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
95 
96 #define MD_SETJMP(env) setjmp(env)
97 #define MD_LONGJMP(env, val) longjmp(env, val)
98 
99 #define MD_JB_SP  7
100 
101 #define MD_GET_SP(_t) (_t)->context[MD_JB_SP]
102 
103 #define MD_INIT_CONTEXT(_thread, _sp, _main) \
104   ST_BEGIN_MACRO                             \
105   if (MD_SETJMP((_thread)->context))         \
106     _main();                                 \
107   MD_GET_SP(_thread) = (long) (_sp);         \
108   ST_END_MACRO
109 
110 #define MD_GET_UTIME()            \
111   struct timeval tv;              \
112   (void) gettimeofday(&tv, NULL); \
113   return (tv.tv_sec * 1000000LL + tv.tv_usec)
114 
115 #elif defined (DARWIN)
116 
117 #define MD_STACK_GROWS_DOWN
118 #define MD_USE_BSD_ANON_MMAP
119 #define MD_ACCEPT_NB_INHERITED
120 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
121 #define MD_HAVE_SOCKLEN_T
122 
123 #define MD_SETJMP(env) _setjmp(env)
124 #define MD_LONGJMP(env, val) _longjmp(env, val)
125 
126 #if defined(__ppc__)
127 #define MD_JB_SP  0
128 #elif defined(__i386__)
129 #define MD_JB_SP  9
130 #elif defined(__x86_64__)
131 #define MD_JB_SP  4
132 #else
133 #error Unknown CPU architecture
134 #endif
135 
136 #define MD_INIT_CONTEXT(_thread, _sp, _main)   \
137   ST_BEGIN_MACRO                               \
138   if (MD_SETJMP((_thread)->context))           \
139     _main();                                   \
140   *((long *)&((_thread)->context[MD_JB_SP])) = (long) (_sp); \
141   ST_END_MACRO
142 
143 #define MD_GET_UTIME()            \
144   struct timeval tv;              \
145   (void) gettimeofday(&tv, NULL); \
146   return (tv.tv_sec * 1000000LL + tv.tv_usec)
147 
148 #elif defined (FREEBSD)
149 
150 #define MD_STACK_GROWS_DOWN
151 #define MD_USE_BSD_ANON_MMAP
152 #define MD_ACCEPT_NB_INHERITED
153 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
154 
155 #define MD_SETJMP(env) _setjmp(env)
156 #define MD_LONGJMP(env, val) _longjmp(env, val)
157 
158 #if defined(__i386__)
159 #define MD_JB_SP   2
160 #elif defined(__alpha__)
161 #define MD_JB_SP  34
162 #elif defined(__amd64__)
163 #define MD_JB_SP   2
164 /*
165  * The following comment is taken from src/lib/libc/amd64/gen/makecontext.c
166  * It explains why we specifically break the alignment to 64 byte boundary
167  * that is unconditionally enforced by sched.c, by setting MD_STACK_PAD_SIZE
168  * to this funky value.
169  * Without this, anything using va_start() & friends fails unpredictably.
170  */
171         /*
172          * Account for arguments on stack and do the funky C entry alignment.
173          * This means that we need an 8-byte-odd alignment since the ABI expects
174          * the return address to be pushed, thus breaking the 16 byte alignment.
175          */
176 #define MD_STACK_PAD_SIZE 8
177 #else
178 #error Unknown CPU architecture
179 #endif
180 
181 #define MD_INIT_CONTEXT(_thread, _sp, _main)          \
182   ST_BEGIN_MACRO                                      \
183   if (MD_SETJMP((_thread)->context))                  \
184     _main();                                          \
185   (_thread)->context[0]._jb[MD_JB_SP] = (long) (_sp); \
186   ST_END_MACRO
187 
188 #define MD_GET_UTIME()            \
189   struct timeval tv;              \
190   (void) gettimeofday(&tv, NULL); \
191   return (tv.tv_sec * 1000000LL + tv.tv_usec)
192 
193 #elif defined (HPUX)
194 
195 #define MD_STACK_GROWS_UP
196 #define MD_USE_BSD_ANON_MMAP
197 #define MD_ACCEPT_NB_INHERITED
198 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
199 
200 #define MD_SETJMP(env) _setjmp(env)
201 #define MD_LONGJMP(env, val) _longjmp(env, val)
202 
203 #ifndef __LP64__
204 /* 32-bit mode (ILP32 data model) */
205 #define MD_INIT_CONTEXT(_thread, _sp, _main)        \
206   ST_BEGIN_MACRO                                    \
207   if (MD_SETJMP((_thread)->context))                \
208     _main();                                        \
209   ((long *)((_thread)->context))[1] = (long) (_sp); \
210   ST_END_MACRO
211 #else
212 /* 64-bit mode (LP64 data model) */
213 #define MD_STACK_PAD_SIZE 256
214 /* Last stack frame must be preserved */
215 #define MD_INIT_CONTEXT(_thread, _sp, _main)                     \
216   ST_BEGIN_MACRO                                                 \
217   if (MD_SETJMP((_thread)->context))                             \
218     _main();                                                     \
219   memcpy((char *)(_sp) - MD_STACK_PAD_SIZE,                      \
220          ((char **)((_thread)->context))[1] - MD_STACK_PAD_SIZE, \
221          MD_STACK_PAD_SIZE);                                     \
222   ((long *)((_thread)->context))[1] = (long) (_sp);              \
223   ST_END_MACRO
224 #endif /* !__LP64__ */
225 
226 #define MD_GET_UTIME()            \
227   struct timeval tv;              \
228   (void) gettimeofday(&tv, NULL); \
229   return (tv.tv_sec * 1000000LL + tv.tv_usec)
230 
231 #elif defined (IRIX)
232 
233 #include <sys/syssgi.h>
234 
235 #define MD_STACK_GROWS_DOWN
236 #define MD_USE_SYSV_ANON_MMAP
237 #define MD_ACCEPT_NB_INHERITED
238 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
239 
240 #define MD_SETJMP(env) setjmp(env)
241 #define MD_LONGJMP(env, val) longjmp(env, val)
242 
243 #define MD_INIT_CONTEXT(_thread, _sp, _main) \
244   ST_BEGIN_MACRO                             \
245   (void) MD_SETJMP((_thread)->context);      \
246   (_thread)->context[JB_SP] = (long) (_sp);  \
247   (_thread)->context[JB_PC] = (long) _main;  \
248   ST_END_MACRO
249 
250 #define MD_GET_UTIME()                         \
251   static int inited = 0;                       \
252   static clockid_t clock_id = CLOCK_SGI_CYCLE; \
253   struct timespec ts;                          \
254   if (!inited) {                               \
255     if (syssgi(SGI_CYCLECNTR_SIZE) < 64)       \
256       clock_id = CLOCK_REALTIME;               \
257     inited = 1;                                \
258   }                                            \
259   (void) clock_gettime(clock_id, &ts);         \
260   return (ts.tv_sec * 1000000LL + ts.tv_nsec / 1000)
261 
262 /*
263  * Cap the stack by zeroing out the saved return address register
264  * value. This allows libexc, used by SpeedShop, to know when to stop
265  * backtracing since it won't find main, start, or any other known
266  * stack root function in a state thread's stack. Without this libexc
267  * traces right off the stack and crashes.
268  * The function preamble stores ra at 8(sp), this stores zero there.
269  * N.B. This macro is compiler/ABI dependent. It must change if ANY more
270  * automatic variables are added to the _st_thread_main() routine, because
271  * the address where ra is stored will change.
272  */
273 #if !defined(__GNUC__) && defined(_MIPS_SIM) && _MIPS_SIM != _ABIO32
274 #define MD_CAP_STACK(var_addr) \
275   (((volatile __uint64_t *)(var_addr))[1] = 0)
276 #endif
277 
278 #elif defined (LINUX)
279 
280 /*
281  * These are properties of the linux kernel and are the same on every
282  * flavor and architecture.
283  */
284 #define MD_USE_BSD_ANON_MMAP
285 #define MD_ACCEPT_NB_NOT_INHERITED
286 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
287 /*
288  * Modern GNU/Linux is Posix.1g compliant.
289  */
290 #define MD_HAVE_SOCKLEN_T
291 
292 /*
293  * All architectures and flavors of linux have the gettimeofday
294  * function but if you know of a faster way, use it.
295  */
296 #define MD_GET_UTIME()            \
297   struct timeval tv;              \
298   (void) gettimeofday(&tv, NULL); \
299   return (tv.tv_sec * 1000000LL + tv.tv_usec)
300 
301 #if defined(__ia64__)
302 #define MD_STACK_GROWS_DOWN
303 
304 /*
305  * IA-64 architecture.  Besides traditional memory call stack, IA-64
306  * uses general register stack.  Thus each thread needs a backing store
307  * for register stack in addition to memory stack.  Standard
308  * setjmp()/longjmp() cannot be used for thread context switching
309  * because their implementation implicitly assumes that only one
310  * register stack exists.
311  */
312 #ifdef USE_LIBC_SETJMP
313 #undef USE_LIBC_SETJMP
314 #endif
315 #define MD_USE_BUILTIN_SETJMP
316 
317 #define MD_STACK_PAD_SIZE 128
318 /* Last register stack frame must be preserved */
319 #define MD_INIT_CONTEXT(_thread, _sp, _bsp, _main)                       \
320   ST_BEGIN_MACRO                                                         \
321   if (MD_SETJMP((_thread)->context))                                     \
322     _main();                                                             \
323   memcpy((char *)(_bsp) - MD_STACK_PAD_SIZE,                             \
324          (char *)(_thread)->context[0].__jmpbuf[17] - MD_STACK_PAD_SIZE, \
325          MD_STACK_PAD_SIZE);                                             \
326   (_thread)->context[0].__jmpbuf[0]  = (long) (_sp);                     \
327   (_thread)->context[0].__jmpbuf[17] = (long) (_bsp);                    \
328   ST_END_MACRO
329 
330 #elif defined(__mips__)
331 #define MD_STACK_GROWS_DOWN
332 
333 #define MD_INIT_CONTEXT(_thread, _sp, _main)               \
334   ST_BEGIN_MACRO                                           \
335   MD_SETJMP((_thread)->context);                           \
336   _thread->context[0].__jmpbuf[0].__pc = (__ptr_t) _main;  \
337   _thread->context[0].__jmpbuf[0].__sp = _sp;              \
338   ST_END_MACRO
339 
340 #else /* Not IA-64 or mips */
341 
342 /*
343  * On linux, there are a few styles of jmpbuf format.  These vary based
344  * on architecture/glibc combination.
345  *
346  * Most of the glibc based toggles were lifted from:
347  * mozilla/nsprpub/pr/include/md/_linux.h
348  */
349 
350 /*
351  * Starting with glibc 2.4, JB_SP definitions are not public anymore.
352  * They, however, can still be found in glibc source tree in
353  * architecture-specific "jmpbuf-offsets.h" files.
354  * Most importantly, the content of jmp_buf is mangled by setjmp to make
355  * it completely opaque (the mangling can be disabled by setting the
356  * LD_POINTER_GUARD environment variable before application execution).
357  * Therefore we will use built-in _st_md_cxt_save/_st_md_cxt_restore
358  * functions as a setjmp/longjmp replacement wherever they are available
359  * unless USE_LIBC_SETJMP is defined.
360  */
361 
362 #if defined(__powerpc__)
363 #define MD_STACK_GROWS_DOWN
364 
365 #if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1)
366 #ifndef JB_GPR1
367 #define JB_GPR1 0
368 #endif
369 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[JB_GPR1]
370 #else
371 /* not an error but certainly cause for caution */
372 #error "Untested use of old glibc on powerpc"
373 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[0].__misc[0]
374 #endif /* glibc 2.1 or later */
375 
376 #elif defined(__alpha)
377 #define MD_STACK_GROWS_DOWN
378 
379 #if defined(__GLIBC__) && __GLIBC__ >= 2
380 #ifndef JB_SP
381 #define JB_SP 8
382 #endif
383 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[JB_SP]
384 #else
385 /* not an error but certainly cause for caution */
386 #error "Untested use of old glibc on alpha"
387 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[0].__sp
388 #endif
389 
390 #elif defined(__mc68000__)
391 #define MD_STACK_GROWS_DOWN
392 
393 /* m68k still uses old style sigjmp_buf */
394 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[0].__sp
395 
396 #elif defined(__sparc__)
397 #define MD_STACK_GROWS_DOWN
398 
399 #if defined(__GLIBC__) && __GLIBC__ >= 2
400 #ifndef JB_SP
401 #define JB_SP 0
402 #endif
403 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[JB_SP]
404 #else
405 /* not an error but certainly cause for caution */
406 #error "Untested use of old glic on sparc -- also using odd mozilla derived __fp"
407 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[0].__fp
408 #endif
409 
410 #elif defined(__i386__)
411 #define MD_STACK_GROWS_DOWN
412 #define MD_USE_BUILTIN_SETJMP
413 
414 #if defined(__GLIBC__) && __GLIBC__ >= 2
415 #ifndef JB_SP
416 #define JB_SP 4
417 #endif
418 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[JB_SP]
419 #else
420 /* not an error but certainly cause for caution */
421 #error "Untested use of old glibc on i386"
422 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[0].__sp
423 #endif
424 
425 #elif defined(__amd64__) || defined(__x86_64__)
426 #define MD_STACK_GROWS_DOWN
427 #define MD_USE_BUILTIN_SETJMP
428 
429 #ifndef JB_RSP
430 #define JB_RSP 6
431 #endif
432 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[JB_RSP]
433 
434 #elif defined(__arm__)
435 #define MD_STACK_GROWS_DOWN
436 
437 #if defined(__GLIBC__) && __GLIBC__ >= 2
438 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[20]
439 #else
440 #error "ARM/Linux pre-glibc2 not supported yet"
441 #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */
442 
443 #elif defined(__s390__)
444 #define MD_STACK_GROWS_DOWN
445 
446 /* There is no JB_SP in glibc at this time. (glibc 2.2.5)
447  */
448 #define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[0].__gregs[9]
449 
450 #elif defined(__hppa__)
451 #define MD_STACK_GROWS_UP
452 
453 /* yes, this is gross, unfortunately at the moment (2002/08/01) there is
454  * a bug in hppa's glibc header definition for JB_SP, so we can't
455  * use that...
456  */
457 #define MD_GET_SP(_t) (*(long *)(((char *)&(_t)->context[0].__jmpbuf[0]) + 76))
458 
459 #else
460 #error "Unknown CPU architecture"
461 #endif /* Cases with common MD_INIT_CONTEXT and different SP locations */
462 
463 #define MD_INIT_CONTEXT(_thread, _sp, _main) \
464   ST_BEGIN_MACRO                             \
465   if (MD_SETJMP((_thread)->context))         \
466     _main();                                 \
467   MD_GET_SP(_thread) = (long) (_sp);         \
468   ST_END_MACRO
469 
470 #endif /* Cases with different MD_INIT_CONTEXT */
471 
472 #if defined(MD_USE_BUILTIN_SETJMP) && !defined(USE_LIBC_SETJMP)
473 #define MD_SETJMP(env) _st_md_cxt_save(env)
474 #define MD_LONGJMP(env, val) _st_md_cxt_restore(env, val)
475 
476 extern int _st_md_cxt_save(jmp_buf env);
477 extern void _st_md_cxt_restore(jmp_buf env, int val);
478 #else
479 #define MD_SETJMP(env) setjmp(env)
480 #define MD_LONGJMP(env, val) longjmp(env, val)
481 #endif
482 
483 #elif defined (NETBSD)
484 
485 #define MD_STACK_GROWS_DOWN
486 #define MD_USE_BSD_ANON_MMAP
487 #define MD_ACCEPT_NB_INHERITED
488 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
489 #define MD_HAVE_SOCKLEN_T
490 
491 #define MD_SETJMP(env) _setjmp(env)
492 #define MD_LONGJMP(env, val) _longjmp(env, val)
493 
494 #if defined(__i386__)
495 #define MD_JB_SP   2
496 #elif defined(__alpha__)
497 #define MD_JB_SP  34
498 #elif defined(__sparc__)
499 #define MD_JB_SP   0
500 #elif defined(__vax__)
501 #define MD_JB_SP   2
502 #else
503 #error Unknown CPU architecture
504 #endif
505 
506 #define MD_INIT_CONTEXT(_thread, _sp, _main)   \
507   ST_BEGIN_MACRO                               \
508   if (MD_SETJMP((_thread)->context))           \
509     _main();                                   \
510   (_thread)->context[MD_JB_SP] = (long) (_sp); \
511   ST_END_MACRO
512 
513 #define MD_GET_UTIME()            \
514   struct timeval tv;              \
515   (void) gettimeofday(&tv, NULL); \
516   return (tv.tv_sec * 1000000LL + tv.tv_usec)
517 
518 #elif defined (OPENBSD)
519 
520 #define MD_STACK_GROWS_DOWN
521 #define MD_USE_BSD_ANON_MMAP
522 #define MD_ACCEPT_NB_INHERITED
523 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
524 
525 #define MD_SETJMP(env) _setjmp(env)
526 #define MD_LONGJMP(env, val) _longjmp(env, val)
527 
528 #if defined(__i386__)
529 #define MD_JB_SP   2
530 #elif defined(__alpha__)
531 #define MD_JB_SP  34
532 #elif defined(__sparc__)
533 #define MD_JB_SP   0
534 #elif defined(__amd64__)
535 #define MD_JB_SP   6
536 #else
537 #error Unknown CPU architecture
538 #endif
539 
540 #define MD_INIT_CONTEXT(_thread, _sp, _main)   \
541   ST_BEGIN_MACRO                               \
542   if (MD_SETJMP((_thread)->context))           \
543     _main();                                   \
544   (_thread)->context[MD_JB_SP] = (long) (_sp); \
545   ST_END_MACRO
546 
547 #define MD_GET_UTIME()            \
548   struct timeval tv;              \
549   (void) gettimeofday(&tv, NULL); \
550   return (tv.tv_sec * 1000000LL + tv.tv_usec)
551 
552 #elif defined (OSF1)
553 
554 #include <signal.h>
555 
556 #define MD_STACK_GROWS_DOWN
557 #define MD_USE_SYSV_ANON_MMAP
558 #define MD_ACCEPT_NB_NOT_INHERITED
559 #define MD_ALWAYS_UNSERIALIZED_ACCEPT
560 
561 #define MD_SETJMP(env) _setjmp(env)
562 #define MD_LONGJMP(env, val) _longjmp(env, val)
563 
564 #define MD_INIT_CONTEXT(_thread, _sp, _main)                         \
565   ST_BEGIN_MACRO                                                     \
566   if (MD_SETJMP((_thread)->context))                                 \
567     _main();                                                         \
568   ((struct sigcontext *)((_thread)->context))->sc_sp = (long) (_sp); \
569   ST_END_MACRO
570 
571 #define MD_GET_UTIME()            \
572   struct timeval tv;              \
573   (void) gettimeofday(&tv, NULL); \
574   return (tv.tv_sec * 1000000LL + tv.tv_usec)
575 
576 #elif defined (SOLARIS)
577 
578 #include <sys/filio.h>
579 extern int getpagesize(void);
580 
581 #define MD_STACK_GROWS_DOWN
582 #define MD_USE_SYSV_ANON_MMAP
583 #define MD_ACCEPT_NB_NOT_INHERITED
584 
585 #define MD_SETJMP(env) setjmp(env)
586 #define MD_LONGJMP(env, val) longjmp(env, val)
587 
588 #if defined(sparc) || defined(__sparc)
589 #ifdef _LP64
590 #define MD_STACK_PAD_SIZE 4095
591 #endif
592 #define MD_INIT_CONTEXT(_thread, _sp, _main) \
593   ST_BEGIN_MACRO                             \
594   (void) MD_SETJMP((_thread)->context);      \
595   (_thread)->context[1] = (long) (_sp);      \
596   (_thread)->context[2] = (long) _main;      \
597   ST_END_MACRO
598 #elif defined(i386) || defined(__i386)
599 #define MD_INIT_CONTEXT(_thread, _sp, _main) \
600   ST_BEGIN_MACRO                             \
601   (void) MD_SETJMP((_thread)->context);      \
602   (_thread)->context[4] = (long) (_sp);      \
603   (_thread)->context[5] = (long) _main;      \
604   ST_END_MACRO
605 #elif defined(__amd64__)
606 #define MD_INIT_CONTEXT(_thread, _sp, _main)   \
607   ST_BEGIN_MACRO                               \
608   if (MD_SETJMP((_thread)->context))           \
609     _main();                                   \
610   (_thread)->context[6] = (long) (_sp); \
611   ST_END_MACRO
612 #else
613 #error Unknown CPU architecture
614 #endif
615 
616 #define MD_GET_UTIME() \
617   return (gethrtime() / 1000)
618 
619 #else
620 #error Unknown OS
621 #endif /* OS */
622 
623 #if !defined(MD_HAVE_POLL) && !defined(MD_DONT_HAVE_POLL)
624 #define MD_HAVE_POLL
625 #endif
626 
627 #ifndef MD_STACK_PAD_SIZE
628 #define MD_STACK_PAD_SIZE 128
629 #endif
630 
631 #if !defined(MD_HAVE_SOCKLEN_T) && !defined(socklen_t)
632 #define socklen_t int
633 #endif
634 
635 #ifndef MD_CAP_STACK
636 #define MD_CAP_STACK(var_addr)
637 #endif
638 
639 #endif /* !__ST_MD_H__ */
640 
641