home *** CD-ROM | disk | FTP | other *** search
/ Netrunner 2004 October / NETRUNNER0410.ISO / regular / ActivePerl-5.8.4.810-MSWin32-x86.msi / _4e59e190c717f8933dad489b06311dfe < prev    next >
Text File  |  2004-06-01  |  15KB  |  527 lines

  1. /*    thread.h
  2.  *
  3.  *    Copyright (C) 1999, 2000, 2001, 2002, 2004, by Larry Wall and others
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  */
  9.  
  10. #if defined(USE_5005THREADS) || defined(USE_ITHREADS)
  11.  
  12. #if defined(VMS)
  13. #include <builtins.h>
  14. #endif
  15.  
  16. #ifdef WIN32
  17. #  include <win32thread.h>
  18. #else
  19. #ifdef NETWARE
  20. #  include <nw5thread.h>
  21. #else
  22. #  ifdef OLD_PTHREADS_API /* Here be dragons. */
  23. #    define DETACH(t) \
  24.     STMT_START {                        \
  25.     int _eC_;                        \
  26.     if ((_eC_ = pthread_detach(&(t)->self))) {        \
  27.         MUTEX_UNLOCK(&(t)->mutex);                \
  28.         Perl_croak_nocontext("panic: DETACH (%d) [%s:%d]",    \
  29.                  _eC_, __FILE__, __LINE__);    \
  30.     }                            \
  31.     } STMT_END
  32.  
  33. #    define PERL_GET_CONTEXT    Perl_get_context()
  34. #    define PERL_SET_CONTEXT(t)    Perl_set_context((void*)t)
  35.  
  36. #    define PTHREAD_GETSPECIFIC_INT
  37. #    ifdef DJGPP
  38. #      define pthread_addr_t any_t
  39. #      define NEED_PTHREAD_INIT
  40. #      define PTHREAD_CREATE_JOINABLE (1)
  41. #    endif
  42. #    ifdef __OPEN_VM
  43. #      define pthread_addr_t void *
  44. #    endif
  45. #    ifdef OEMVS
  46. #      define pthread_addr_t void *
  47. #      define pthread_create(t,a,s,d)        pthread_create(t,&(a),s,d)
  48. #      define pthread_keycreate              pthread_key_create
  49. #    endif
  50. #    ifdef VMS
  51. #      define pthread_attr_init(a) pthread_attr_create(a)
  52. #      define PTHREAD_ATTR_SETDETACHSTATE(a,s) pthread_setdetach_np(a,s)
  53. #      define PTHREAD_CREATE(t,a,s,d) pthread_create(t,a,s,d)
  54. #      define pthread_key_create(k,d) pthread_keycreate(k,(pthread_destructor_t)(d))
  55. #      define pthread_mutexattr_init(a) pthread_mutexattr_create(a)
  56. #      define pthread_mutexattr_settype(a,t) pthread_mutexattr_setkind_np(a,t)
  57. #    endif
  58. #    if defined(__hpux) && defined(__ux_version) && __ux_version <= 1020
  59. #      define pthread_attr_init(a) pthread_attr_create(a)
  60.        /* XXX pthread_setdetach_np() missing in DCE threads on HP-UX 10.20 */
  61. #      define PTHREAD_ATTR_SETDETACHSTATE(a,s)    (0)
  62. #      define PTHREAD_CREATE(t,a,s,d) pthread_create(t,a,s,d)
  63. #      define pthread_key_create(k,d) pthread_keycreate(k,(pthread_destructor_t)(d))
  64. #      define pthread_mutexattr_init(a) pthread_mutexattr_create(a)
  65. #      define pthread_mutexattr_settype(a,t) pthread_mutexattr_setkind_np(a,t)
  66. #    endif
  67. #    if defined(DJGPP) || defined(__OPEN_VM) || defined(OEMVS)
  68. #      define PTHREAD_ATTR_SETDETACHSTATE(a,s) pthread_attr_setdetachstate(a,&(s))
  69. #      define YIELD pthread_yield(NULL)
  70. #    endif
  71. #  endif
  72. #  if !defined(__hpux) || !defined(__ux_version) || __ux_version > 1020
  73. #    define pthread_mutexattr_default NULL
  74. #    define pthread_condattr_default  NULL
  75. #  endif
  76. #endif    /* NETWARE */
  77. #endif
  78.  
  79. #ifndef PTHREAD_CREATE
  80. /* You are not supposed to pass NULL as the 2nd arg of PTHREAD_CREATE(). */
  81. #  define PTHREAD_CREATE(t,a,s,d) pthread_create(t,&(a),s,d)
  82. #endif
  83.  
  84. #ifndef PTHREAD_ATTR_SETDETACHSTATE
  85. #  define PTHREAD_ATTR_SETDETACHSTATE(a,s) pthread_attr_setdetachstate(a,s)
  86. #endif
  87.  
  88. #ifndef PTHREAD_CREATE_JOINABLE
  89. #  ifdef OLD_PTHREAD_CREATE_JOINABLE
  90. #    define PTHREAD_CREATE_JOINABLE OLD_PTHREAD_CREATE_JOINABLE
  91. #  else
  92. #    define PTHREAD_CREATE_JOINABLE 0 /* Panic?  No, guess. */
  93. #  endif
  94. #endif
  95.  
  96. #ifdef DGUX
  97. #  define THREAD_CREATE_NEEDS_STACK (32*1024)
  98. #endif
  99.  
  100. #ifdef I_MACH_CTHREADS
  101.  
  102. /* cthreads interface */
  103.  
  104. /* #include <mach/cthreads.h> is in perl.h #ifdef I_MACH_CTHREADS */
  105.  
  106. #define MUTEX_INIT(m) \
  107.     STMT_START {                        \
  108.     *m = mutex_alloc();                    \
  109.     if (*m) {                        \
  110.         mutex_init(*m);                    \
  111.     } else {                        \
  112.         Perl_croak_nocontext("panic: MUTEX_INIT [%s:%d]",    \
  113.                  __FILE__, __LINE__);        \
  114.     }                            \
  115.     } STMT_END
  116.  
  117. #define MUTEX_LOCK(m)            mutex_lock(*m)
  118. #define MUTEX_UNLOCK(m)            mutex_unlock(*m)
  119. #define MUTEX_DESTROY(m) \
  120.     STMT_START {                        \
  121.     mutex_free(*m);                        \
  122.     *m = 0;                            \
  123.     } STMT_END
  124.  
  125. #define COND_INIT(c) \
  126.     STMT_START {                        \
  127.     *c = condition_alloc();                    \
  128.     if (*c) {                        \
  129.         condition_init(*c);                    \
  130.     }                            \
  131.     else {                            \
  132.         Perl_croak_nocontext("panic: COND_INIT [%s:%d]",    \
  133.                  __FILE__, __LINE__);        \
  134.     }                            \
  135.     } STMT_END
  136.  
  137. #define COND_SIGNAL(c)        condition_signal(*c)
  138. #define COND_BROADCAST(c)    condition_broadcast(*c)
  139. #define COND_WAIT(c, m)        condition_wait(*c, *m)
  140. #define COND_DESTROY(c) \
  141.     STMT_START {                        \
  142.     condition_free(*c);                    \
  143.     *c = 0;                            \
  144.     } STMT_END
  145.  
  146. #define THREAD_CREATE(thr, f)    (thr->self = cthread_fork(f, thr), 0)
  147. #define THREAD_POST_CREATE(thr)
  148.  
  149. #define THREAD_RET_TYPE        any_t
  150. #define THREAD_RET_CAST(x)    ((any_t) x)
  151.  
  152. #define DETACH(t)        cthread_detach(t->self)
  153. #define JOIN(t, avp)        (*(avp) = (AV *)cthread_join(t->self))
  154.  
  155. #define PERL_SET_CONTEXT(t)    cthread_set_data(cthread_self(), t)
  156. #define PERL_GET_CONTEXT    cthread_data(cthread_self())
  157.  
  158. #define INIT_THREADS        cthread_init()
  159. #define YIELD            cthread_yield()
  160. #define ALLOC_THREAD_KEY    NOOP
  161. #define FREE_THREAD_KEY        NOOP
  162. #define SET_THREAD_SELF(thr)    (thr->self = cthread_self())
  163.  
  164. #endif /* I_MACH_CTHREADS */
  165.  
  166. #ifndef YIELD
  167. #  ifdef SCHED_YIELD
  168. #    define YIELD SCHED_YIELD
  169. #  else
  170. #    ifdef HAS_SCHED_YIELD
  171. #      define YIELD sched_yield()
  172. #    else
  173. #      ifdef HAS_PTHREAD_YIELD
  174.     /* pthread_yield(NULL) platforms are expected
  175.      * to have #defined YIELD for themselves. */
  176. #        define YIELD pthread_yield()
  177. #      endif
  178. #    endif
  179. #  endif
  180. #endif
  181.  
  182. #ifdef __hpux
  183. #  define MUTEX_INIT_NEEDS_MUTEX_ZEROED
  184. #endif
  185.  
  186. #ifndef MUTEX_INIT
  187.  
  188. #  ifdef MUTEX_INIT_NEEDS_MUTEX_ZEROED
  189.     /* Temporary workaround, true bug is deeper. --jhi 1999-02-25 */
  190. #    define MUTEX_INIT(m) \
  191.     STMT_START {                        \
  192.     int _eC_;                        \
  193.     Zero((m), 1, perl_mutex);                               \
  194.      if ((_eC_ = pthread_mutex_init((m), pthread_mutexattr_default)))    \
  195.         Perl_croak_nocontext("panic: MUTEX_INIT (%d) [%s:%d]",    \
  196.                  _eC_, __FILE__, __LINE__);    \
  197.     } STMT_END
  198. #  else
  199. #    define MUTEX_INIT(m) \
  200.     STMT_START {                        \
  201.     int _eC_;                        \
  202.     if ((_eC_ = pthread_mutex_init((m), pthread_mutexattr_default)))    \
  203.         Perl_croak_nocontext("panic: MUTEX_INIT (%d) [%s:%d]",    \
  204.                  _eC_, __FILE__, __LINE__);    \
  205.     } STMT_END
  206. #  endif
  207.  
  208. #  define MUTEX_LOCK(m) \
  209.     STMT_START {                        \
  210.     int _eC_;                        \
  211.     if ((_eC_ = pthread_mutex_lock((m))))            \
  212.         Perl_croak_nocontext("panic: MUTEX_LOCK (%d) [%s:%d]",    \
  213.                  _eC_, __FILE__, __LINE__);    \
  214.     } STMT_END
  215.  
  216. #  define MUTEX_UNLOCK(m) \
  217.     STMT_START {                        \
  218.     int _eC_;                        \
  219.     if ((_eC_ = pthread_mutex_unlock((m))))            \
  220.         Perl_croak_nocontext("panic: MUTEX_UNLOCK (%d) [%s:%d]",    \
  221.                  _eC_, __FILE__, __LINE__);    \
  222.     } STMT_END
  223.  
  224. #  define MUTEX_DESTROY(m) \
  225.     STMT_START {                        \
  226.     int _eC_;                        \
  227.     if ((_eC_ = pthread_mutex_destroy((m))))        \
  228.         Perl_croak_nocontext("panic: MUTEX_DESTROY (%d) [%s:%d]",    \
  229.                  _eC_, __FILE__, __LINE__);    \
  230.     } STMT_END
  231. #endif /* MUTEX_INIT */
  232.  
  233. #ifndef COND_INIT
  234. #  define COND_INIT(c) \
  235.     STMT_START {                        \
  236.     int _eC_;                        \
  237.     if ((_eC_ = pthread_cond_init((c), pthread_condattr_default)))    \
  238.         Perl_croak_nocontext("panic: COND_INIT (%d) [%s:%d]",    \
  239.                  _eC_, __FILE__, __LINE__);    \
  240.     } STMT_END
  241.  
  242. #  define COND_SIGNAL(c) \
  243.     STMT_START {                        \
  244.     int _eC_;                        \
  245.     if ((_eC_ = pthread_cond_signal((c))))            \
  246.         Perl_croak_nocontext("panic: COND_SIGNAL (%d) [%s:%d]",    \
  247.                  _eC_, __FILE__, __LINE__);    \
  248.     } STMT_END
  249.  
  250. #  define COND_BROADCAST(c) \
  251.     STMT_START {                        \
  252.     int _eC_;                        \
  253.     if ((_eC_ = pthread_cond_broadcast((c))))        \
  254.         Perl_croak_nocontext("panic: COND_BROADCAST (%d) [%s:%d]",    \
  255.                  _eC_, __FILE__, __LINE__);    \
  256.     } STMT_END
  257.  
  258. #  define COND_WAIT(c, m) \
  259.     STMT_START {                        \
  260.     int _eC_;                        \
  261.     if ((_eC_ = pthread_cond_wait((c), (m))))        \
  262.         Perl_croak_nocontext("panic: COND_WAIT (%d) [%s:%d]",    \
  263.                  _eC_, __FILE__, __LINE__);    \
  264.     } STMT_END
  265.  
  266. #  define COND_DESTROY(c) \
  267.     STMT_START {                        \
  268.     int _eC_;                        \
  269.     if ((_eC_ = pthread_cond_destroy((c))))            \
  270.         Perl_croak_nocontext("panic: COND_DESTROY (%d) [%s:%d]",    \
  271.                  _eC_, __FILE__, __LINE__);    \
  272.     } STMT_END
  273. #endif /* COND_INIT */
  274.  
  275. /* DETACH(t) must only be called while holding t->mutex */
  276. #ifndef DETACH
  277. #  define DETACH(t) \
  278.     STMT_START {                        \
  279.     int _eC_;                        \
  280.     if ((_eC_ = pthread_detach((t)->self))) {        \
  281.         MUTEX_UNLOCK(&(t)->mutex);                \
  282.         Perl_croak_nocontext("panic: DETACH (%d) [%s:%d]",    \
  283.                  _eC_, __FILE__, __LINE__);    \
  284.     }                            \
  285.     } STMT_END
  286. #endif /* DETACH */
  287.  
  288. #ifndef JOIN
  289. #  define JOIN(t, avp) \
  290.     STMT_START {                        \
  291.     int _eC_;                        \
  292.     if ((_eC_ = pthread_join((t)->self, (void**)(avp))))    \
  293.         Perl_croak_nocontext("panic: pthread_join (%d) [%s:%d]",    \
  294.                  _eC_, __FILE__, __LINE__);    \
  295.     } STMT_END
  296. #endif /* JOIN */
  297.  
  298. /* Use an unchecked fetch of thread-specific data instead of a checked one.
  299.  * It would fail if the key were bogus, but if the key were bogus then
  300.  * Really Bad Things would be happening anyway. --dan */
  301. #if (defined(__ALPHA) && (__VMS_VER >= 70000000)) || \
  302.     (defined(__alpha) && defined(__osf__) && !defined(__GNUC__)) /* Available only on >= 4.0 */
  303. #  define HAS_PTHREAD_UNCHECKED_GETSPECIFIC_NP /* Configure test needed */
  304. #endif
  305.  
  306. #ifdef HAS_PTHREAD_UNCHECKED_GETSPECIFIC_NP
  307. #  define PTHREAD_GETSPECIFIC(key) pthread_unchecked_getspecific_np(key)
  308. #else
  309. #    define PTHREAD_GETSPECIFIC(key) pthread_getspecific(key)
  310. #endif
  311.  
  312. #ifndef PERL_GET_CONTEXT
  313. #  define PERL_GET_CONTEXT    PTHREAD_GETSPECIFIC(PL_thr_key)
  314. #endif
  315.  
  316. #ifndef PERL_SET_CONTEXT
  317. #  define PERL_SET_CONTEXT(t) \
  318.     STMT_START {                        \
  319.     int _eC_;                        \
  320.     if ((_eC_ = pthread_setspecific(PL_thr_key, (void *)(t))))    \
  321.         Perl_croak_nocontext("panic: pthread_setspecific (%d) [%s:%d]",    \
  322.                  _eC_, __FILE__, __LINE__);    \
  323.     } STMT_END
  324. #endif /* PERL_SET_CONTEXT */
  325.  
  326. #ifndef INIT_THREADS
  327. #  ifdef NEED_PTHREAD_INIT
  328. #    define INIT_THREADS pthread_init()
  329. #  endif
  330. #endif
  331.  
  332. #ifndef ALLOC_THREAD_KEY
  333. #  define ALLOC_THREAD_KEY \
  334.     STMT_START {                        \
  335.     int _eC_;                        \
  336.     if ((_eC_ = pthread_key_create(&PL_thr_key, 0))) {    \
  337.         PerlIO_printf(PerlIO_stderr(), "panic: pthread_key_create (%d) [%s:%d]",    \
  338.                  _eC_, __FILE__, __LINE__);    \
  339.         exit(1);                        \
  340.     }                            \
  341.     } STMT_END
  342. #endif
  343.  
  344. #ifndef FREE_THREAD_KEY
  345. #  define FREE_THREAD_KEY \
  346.     STMT_START {                        \
  347.     pthread_key_delete(PL_thr_key);                \
  348.     } STMT_END
  349. #endif
  350.  
  351. #ifndef PTHREAD_ATFORK
  352. #  ifdef HAS_PTHREAD_ATFORK
  353. #    define PTHREAD_ATFORK(prepare,parent,child)        \
  354.     pthread_atfork(prepare,parent,child)
  355. #  else
  356. #    define PTHREAD_ATFORK(prepare,parent,child)        \
  357.     NOOP
  358. #  endif
  359. #endif
  360.  
  361. #ifndef THREAD_RET_TYPE
  362. #  define THREAD_RET_TYPE    void *
  363. #  define THREAD_RET_CAST(p)    ((void *)(p))
  364. #endif /* THREAD_RET */
  365.  
  366. #if defined(USE_5005THREADS)
  367.  
  368. /* Accessor for per-thread SVs */
  369. #  define THREADSV(i) (thr->threadsvp[i])
  370.  
  371. /*
  372.  * LOCK_SV_MUTEX and UNLOCK_SV_MUTEX are performance-critical. Here, we
  373.  * try only locking them if there may be more than one thread in existence.
  374.  * Systems with very fast mutexes (and/or slow conditionals) may wish to
  375.  * remove the "if (threadnum) ..." test.
  376.  * XXX do NOT use C<if (PL_threadnum) ...> -- it sets up race conditions!
  377.  */
  378. #  define LOCK_SV_MUTEX        MUTEX_LOCK(&PL_sv_mutex)
  379. #  define UNLOCK_SV_MUTEX    MUTEX_UNLOCK(&PL_sv_mutex)
  380. #  define LOCK_STRTAB_MUTEX    MUTEX_LOCK(&PL_strtab_mutex)
  381. #  define UNLOCK_STRTAB_MUTEX    MUTEX_UNLOCK(&PL_strtab_mutex)
  382. #  define LOCK_CRED_MUTEX    MUTEX_LOCK(&PL_cred_mutex)
  383. #  define UNLOCK_CRED_MUTEX    MUTEX_UNLOCK(&PL_cred_mutex)
  384. #  define LOCK_FDPID_MUTEX    MUTEX_LOCK(&PL_fdpid_mutex)
  385. #  define UNLOCK_FDPID_MUTEX    MUTEX_UNLOCK(&PL_fdpid_mutex)
  386. #  define LOCK_SV_LOCK_MUTEX    MUTEX_LOCK(&PL_sv_lock_mutex)
  387. #  define UNLOCK_SV_LOCK_MUTEX    MUTEX_UNLOCK(&PL_sv_lock_mutex)
  388.  
  389. /* Values and macros for thr->flags */
  390. #define THRf_STATE_MASK    7
  391. #define THRf_R_JOINABLE    0
  392. #define THRf_R_JOINED    1
  393. #define THRf_R_DETACHED    2
  394. #define THRf_ZOMBIE    3
  395. #define THRf_DEAD    4
  396.  
  397. #define THRf_DID_DIE    8
  398.  
  399. /* ThrSTATE(t) and ThrSETSTATE(t) must only be called while holding t->mutex */
  400. #define ThrSTATE(t) ((t)->flags & THRf_STATE_MASK)
  401. #define ThrSETSTATE(t, s) STMT_START {        \
  402.     (t)->flags &= ~THRf_STATE_MASK;        \
  403.     (t)->flags |= (s);            \
  404.     DEBUG_S(PerlIO_printf(Perl_debug_log,    \
  405.                   "thread %p set to state %d\n", (t), (s))); \
  406.     } STMT_END
  407.  
  408. typedef struct condpair {
  409.     perl_mutex    mutex;        /* Protects all other fields */
  410.     perl_cond    owner_cond;    /* For when owner changes at all */
  411.     perl_cond    cond;        /* For cond_signal and cond_broadcast */
  412.     Thread    owner;        /* Currently owning thread */
  413. } condpair_t;
  414.  
  415. #define MgMUTEXP(mg) (&((condpair_t *)(mg->mg_ptr))->mutex)
  416. #define MgOWNERCONDP(mg) (&((condpair_t *)(mg->mg_ptr))->owner_cond)
  417. #define MgCONDP(mg) (&((condpair_t *)(mg->mg_ptr))->cond)
  418. #define MgOWNER(mg) ((condpair_t *)(mg->mg_ptr))->owner
  419.  
  420. #endif /* USE_5005THREADS */
  421.  
  422. #  define LOCK_DOLLARZERO_MUTEX        MUTEX_LOCK(&PL_dollarzero_mutex)
  423. #  define UNLOCK_DOLLARZERO_MUTEX    MUTEX_UNLOCK(&PL_dollarzero_mutex)
  424.  
  425. #endif /* USE_5005THREADS || USE_ITHREADS */
  426.  
  427. #ifndef MUTEX_LOCK
  428. #  define MUTEX_LOCK(m)
  429. #endif
  430.  
  431. #ifndef MUTEX_UNLOCK
  432. #  define MUTEX_UNLOCK(m)
  433. #endif
  434.  
  435. #ifndef MUTEX_INIT
  436. #  define MUTEX_INIT(m)
  437. #endif
  438.  
  439. #ifndef MUTEX_DESTROY
  440. #  define MUTEX_DESTROY(m)
  441. #endif
  442.  
  443. #ifndef COND_INIT
  444. #  define COND_INIT(c)
  445. #endif
  446.  
  447. #ifndef COND_SIGNAL
  448. #  define COND_SIGNAL(c)
  449. #endif
  450.  
  451. #ifndef COND_BROADCAST
  452. #  define COND_BROADCAST(c)
  453. #endif
  454.  
  455. #ifndef COND_WAIT
  456. #  define COND_WAIT(c, m)
  457. #endif
  458.  
  459. #ifndef COND_DESTROY
  460. #  define COND_DESTROY(c)
  461. #endif
  462.  
  463. #ifndef LOCK_SV_MUTEX
  464. #  define LOCK_SV_MUTEX
  465. #endif
  466.  
  467. #ifndef UNLOCK_SV_MUTEX
  468. #  define UNLOCK_SV_MUTEX
  469. #endif
  470.  
  471. #ifndef LOCK_STRTAB_MUTEX
  472. #  define LOCK_STRTAB_MUTEX
  473. #endif
  474.  
  475. #ifndef UNLOCK_STRTAB_MUTEX
  476. #  define UNLOCK_STRTAB_MUTEX
  477. #endif
  478.  
  479. #ifndef LOCK_CRED_MUTEX
  480. #  define LOCK_CRED_MUTEX
  481. #endif
  482.  
  483. #ifndef UNLOCK_CRED_MUTEX
  484. #  define UNLOCK_CRED_MUTEX
  485. #endif
  486.  
  487. #ifndef LOCK_FDPID_MUTEX
  488. #  define LOCK_FDPID_MUTEX
  489. #endif
  490.  
  491. #ifndef UNLOCK_FDPID_MUTEX
  492. #  define UNLOCK_FDPID_MUTEX
  493. #endif
  494.  
  495. #ifndef LOCK_SV_LOCK_MUTEX
  496. #  define LOCK_SV_LOCK_MUTEX
  497. #endif
  498.  
  499. #ifndef UNLOCK_SV_LOCK_MUTEX
  500. #  define UNLOCK_SV_LOCK_MUTEX
  501. #endif
  502.  
  503. #ifndef LOCK_DOLLARZERO_MUTEX
  504. #  define LOCK_DOLLARZERO_MUTEX
  505. #endif
  506.  
  507. #ifndef UNLOCK_DOLLARZERO_MUTEX
  508. #  define UNLOCK_DOLLARZERO_MUTEX
  509. #endif
  510.  
  511. /* THR, SET_THR, and dTHR are there for compatibility with old versions */
  512. #ifndef THR
  513. #  define THR        PERL_GET_THX
  514. #endif
  515.  
  516. #ifndef SET_THR
  517. #  define SET_THR(t)    PERL_SET_THX(t)
  518. #endif
  519.  
  520. #ifndef dTHR
  521. #  define dTHR dNOOP
  522. #endif
  523.  
  524. #ifndef INIT_THREADS
  525. #  define INIT_THREADS NOOP
  526. #endif
  527.