home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / threads / src / pthread_internals.h < prev    next >
C/C++ Source or Header  |  1996-09-28  |  12KB  |  429 lines

  1. /* Copyright (C) 1992, the Florida State University
  2.    Distributed by the Florida State University under the terms of the
  3.    GNU Library General Public License.
  4.  
  5. This file is part of Pthreads.
  6.  
  7. Pthreads is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Library General Public
  9. License as published by the Free Software Foundation (version 2).
  10.  
  11. Pthreads is distributed "AS IS" in the hope that it will be
  12. useful, but WITHOUT ANY WARRANTY; without even the implied
  13. warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. See the GNU Library General Public License for more details.
  15.  
  16. You should have received a copy of the GNU Library General Public
  17. License along with Pthreads; see the file COPYING.  If not, write
  18. to the Free Software Foundation, 675 Mass Ave, Cambridge,
  19. MA 02139, USA.
  20.  
  21. Report problems and direct all questions to:
  22.  
  23.   pthreads-bugs@ada.cs.fsu.edu
  24.  
  25.   @(#)pthread_internals.h    2.5 4/12/95
  26.  
  27. */
  28.  
  29. #ifndef _pthread_pthread_internals_h
  30. #define _pthread_pthread_internals_h
  31.  
  32. /*
  33.  * Pthreads interface internals
  34.  */
  35.  
  36. /*
  37.  * We needed for MINFRAME and WINDOWSIZE. For SVR4, get it from include files
  38.  * or figure it out and plug it in.
  39.  */
  40. #ifdef SOLARIS
  41. #include <sys/asm_linkage.h>
  42. #else !SOLARIS
  43. #ifdef SVR4
  44. #define MINFRAME ???
  45. #define WINDOWSIZE MINFRAME
  46. #else !SVR4
  47. #include <sparc/asm_linkage.h>
  48. #endif !SVR4
  49. #endif !SOLARIS
  50.  
  51. #include "signal_internals.h"
  52. #include <pthread.h>
  53.  
  54. #ifndef SRP
  55. #ifdef _POSIX_THREADS_PRIO_PROTECT
  56.  ERROR: undefine _POSIX_THREADS_PRIO_PROTECT in unistd.h when SRP is undefined!
  57. #endif 
  58. #else SRP
  59. #ifndef _POSIX_THREADS_PRIO_PROTECT
  60.  ERROR: define _POSIX_THREADS_PRIO_PROTECT in unistd.h when SRP is defined!
  61. #endif
  62. #endif
  63.  
  64. /* Other Program Specific Constants */
  65. #define MAX_PRIORITY        101
  66. #define MIN_PRIORITY        0
  67. #define DEFAULT_PRIORITY    MIN_PRIORITY
  68. #define DEFAULT_STACKSIZE   12288
  69. #define MAX_STACKSIZE       2097152
  70. #define PTHREAD_BODY_OFFSET 200
  71.  
  72. #ifdef DEF_RR
  73. #define TIMER_QUEUE   0
  74. #else
  75. #define TIMER_QUEUE   2
  76. #endif
  77.  
  78. #ifdef SOLARIS
  79. #define READ  _read
  80. #define WRITE _write
  81. #else !SOALRIS
  82. #define READ  read
  83. #define WRITE write
  84. #endif !SOLARIS
  85.  
  86. /*
  87.  * page alignment
  88.  */
  89. #define PA(X) ((((int)X)+((int)pthread_page_size-1)) & \
  90.                 ~((int)pthread_page_size-1))
  91.  
  92. #define MAX(x, y) ((x > y)? x : y)
  93. /*
  94.  * timer queue
  95.  */
  96. #ifdef DEF_RR
  97. typedef struct timer_ent {
  98.         struct timeval tp;                     /* wake-up time                */
  99.         pthread_t thread;                      /* thread                      */
  100.         int mode;                              /* mode of timer (ABS/REL/RR)  */
  101.         struct timer_ent *next[TIMER_QUEUE+1]; /* next request in the queue   */
  102. } *timer_ent_t;
  103. #else
  104. typedef pthread_t timer_ent_t;
  105. #endif
  106.  
  107. #ifdef DEF_RR
  108. typedef struct pthread_timer_q_s {
  109.     struct timer_ent *head;
  110.     struct timer_ent *tail;
  111. } pthread_timer_q;
  112. #elif defined(STAND_ALONE)
  113. typedef struct pthread pthread_timer_q;
  114. #else
  115. typedef struct pthread_queue pthread_timer_q;
  116. #endif
  117. typedef pthread_timer_q *pthread_timer_q_t;
  118.  
  119. #define NO_QUEUE          ((pthread_queue_t) NULL)
  120.  
  121. #define NO_TIMER_QUEUE    ((pthread_timer_q_t) NULL)
  122.  
  123. #define NO_TIMER      ((timer_ent_t) NULL)
  124.  
  125. #define NO_QUEUE_INDEX    0
  126.  
  127. #define    NO_QUEUE_ITEM      ((struct pthread *) NULL)
  128.  
  129. #define    QUEUE_INITIALIZER { NO_QUEUE_ITEM, NO_QUEUE_ITEM }
  130.  
  131. #define    pthread_queue_init(q) \
  132.     ((q)->head = (q)->tail = NO_QUEUE_ITEM)
  133.  
  134. #ifdef STAND_ALONE
  135. #define    pthread_timer_queue_init(q) \
  136.     (q = NO_TIMER_QUEUE)
  137. #else
  138. #define    pthread_timer_queue_init(q) \
  139.     ((q)->head = (q)->tail = NO_TIMER)
  140. #endif
  141.  
  142. pthread_mutexattr_t pthread_mutexattr_default;
  143.  
  144. #ifdef _POSIX_THREADS_PRIO_PROTECT 
  145. #ifdef SRP 
  146. #define MUTEX_WAIT -2
  147. #define NO_PRIO -1
  148. #endif
  149. #endif
  150.  
  151. #define    MUTEX_INITIALIZER    { 0, QUEUE_INITIALIZER, 0, 1 }
  152. #define NO_MUTEX      ((pthread_mutex_t *)0)
  153. #define MUTEX_VALID 0x1
  154.  
  155. pthread_condattr_t pthread_condattr_default;
  156.  
  157. #define    CONDITION_INITIALIZER    { QUEUE_INITIALIZER, 1, 0 }
  158. #define NO_COND       ((pthread_cond_t *) 0)
  159. #define COND_VALID 0x1
  160.  
  161. /*
  162.  * SIGKILL, SIGSTOP cannot be masked; therefore reused as masks
  163.  */
  164. #define TIMER_SIG       SIGKILL
  165. #define AIO_SIG         SIGSTOP
  166.  
  167. #define TIMER_MAX   _POSIX_TIMER_MAX+2
  168.  
  169. #define    NO_PTHREAD    ((pthread_t) 0)
  170.  
  171. pthread_attr_t pthread_attr_default;
  172.  
  173. #define NO_ATTRIBUTE ((pthread_attr_t *)0)
  174.  
  175. struct cleanup {
  176.   void (*func)();
  177.   any_t arg;
  178.   struct cleanup *next;
  179. };
  180.  
  181. typedef struct kernel {
  182.   pthread_t k_pthread_self;            /* thread that is currently running   */
  183.   volatile int k_is_in_kernel;         /* flag to test if in kernel          */
  184.   int k_is_updating_timer;             /* flag to test if timeout is handled */
  185.   volatile int k_state_change;         /* dispatcher state (run q/signals)   */
  186.   volatile sigset_t k_new_signals;     /* bit set of new signals to handle   */
  187.   sigset_t k_pending_signals;          /* bit set of pending signals         */
  188.   sigset_t k_all_signals;              /* mask of all (maskable) signals     */
  189.   sigset_t k_no_signals;               /* mask of no signals                 */
  190.   sigset_t k_cantmask;                 /* mask of signals (cannot be caught) */
  191.   char *k_process_stack_base;          /* stack base of process              */
  192.   struct pthread_queue k_ready;        /* ready queue                        */
  193.   struct pthread_queue k_all;          /* queue of all threads               */
  194.   sigset_t k_handlerset;               /* set of signals with user handler   */
  195.   char *k_set_warning;                 /* pointer to set warning message     */
  196.   char *k_clear_warning;               /* pointer to clear warning message   */
  197.   char *k_prio_warning;                /* pointer to prio warning message    */
  198.                                        /* for STAND_ALONE                    */
  199.   sigset_t k_proc_mask;               /* Mask for process                   */
  200.   int  k_cur_heap;               /* current break                      */
  201.   volatile struct timespec k_timeofday;/* Time of Day                        */
  202. #ifdef IO
  203.   int k_gwidth;                        /* global width                       */
  204.   fd_set k_greadfds;                   /* global read file descriptor set    */
  205.   fd_set k_gwritefds;                  /* global write file descriptor set   */ 
  206.   fd_set k_gexceptfds;                 /* global except file descriptor set  */ 
  207. #endif IO
  208. } kernel_t;
  209.  
  210. #ifdef PTHREAD_KERNEL
  211. kernel_t pthread_kern;
  212. #else
  213. extern kernel_t pthread_kern;
  214. #endif
  215.  
  216. /* Internal Functions */
  217.  
  218. /*
  219.  * changed for speed-up and interface purposes -
  220.  * pthread_self() is now a function, but mac_pthread_self() is used internally
  221.  * #define pthread_self()  (pthread_kern.k_pthread_self == 0? \
  222.  *                          NO_PTHREAD : pthread_kern.k_pthread_self)
  223.  */
  224. #define mac_pthread_self() pthread_kern.k_pthread_self
  225. #define state_change       pthread_kern.k_state_change
  226. #define is_in_kernel       pthread_kern.k_is_in_kernel
  227. #define is_updating_timer  pthread_kern.k_is_updating_timer
  228. #define new_signals        pthread_kern.k_new_signals
  229. #define pending_signals    pthread_kern.k_pending_signals
  230. #define all_signals        pthread_kern.k_all_signals
  231. #define no_signals         pthread_kern.k_no_signals
  232. #define cantmask           pthread_kern.k_cantmask
  233. #define process_stack_base pthread_kern.k_process_stack_base
  234. #define ready              pthread_kern.k_ready
  235. #define all                pthread_kern.k_all
  236. #define handlerset         pthread_kern.k_handlerset
  237. #define set_warning        pthread_kern.k_set_warning
  238. #define clear_warning      pthread_kern.k_clear_warning
  239. #define prio_warning       pthread_kern.k_prio_warning
  240.  
  241. #define proc_mask       pthread_kern.k_proc_mask
  242. #define cur_heap           pthread_kern.k_cur_heap
  243. #define timeofday          pthread_kern.k_timeofday
  244.  
  245. #ifdef IO
  246. #define gwidth             pthread_kern.k_gwidth    
  247. #define greadfds         pthread_kern.k_greadfds  
  248. #define gwritefds        pthread_kern.k_gwritefds 
  249. #define gexceptfds       pthread_kern.k_gexceptfds
  250. #endif IO
  251.  
  252. /*
  253.  * Errno is mapped on process' _errno and swapped upon context switch
  254.  * #define set_errno(e)    (mac_pthread_self()->context[JB_ERRNO] = e)
  255.  * #define get_errno()     (mac_pthread_self()->context[JB_ERRNO])
  256.  */
  257.  
  258. #define set_errno(e)    (errno = (e))
  259. #define get_errno()     (errno)
  260.  
  261. #ifdef STAND_ALONE
  262. #ifdef PTHREAD_KERNEL
  263. int errno;
  264. #else !PTHREAD_KERNEL
  265. extern int errno;
  266. #endif !PTHREAD_KERNE
  267. #endif STAND_ALONE
  268.  
  269. /*
  270.  * context switching macros, implemented via setjmp/longjmp plus saving errno
  271.  */
  272. #define SAVE_CONTEXT(t) \
  273.   (((t)->errno = errno) == errno && \
  274.    sigsetjmp((t)->context, FALSE) && \
  275.    (errno = (t)->errno) == errno)
  276.  
  277. #define RESTORE_CONTEXT(t) siglongjmp((t)->context, TRUE)
  278. /*
  279.  * set/clear Pthread kernel flag
  280.  */
  281.  
  282. #if defined(DEBUG) && !defined(IO)
  283. #define SET_KERNEL_FLAG \
  284.   MACRO_BEGIN \
  285.     if (is_in_kernel) \
  286.       fprintf(stderr, set_warning); \
  287.     else \
  288.       is_in_kernel = TRUE; \
  289.   MACRO_END
  290. #else
  291. #define SET_KERNEL_FLAG is_in_kernel = TRUE
  292. #endif
  293.  
  294. #ifdef C_CONTEXT_SWITCH
  295.  
  296. #define SHARED_CLEAR_KERNEL_FLAG \
  297.   MACRO_BEGIN \
  298.     is_in_kernel = FALSE; \
  299.     if (state_change) { \
  300.       is_in_kernel = TRUE; \
  301.       if ((pthread_signonemptyset(&new_signals) || \
  302.        mac_pthread_self() != ready.head) && \
  303.           !SAVE_CONTEXT(mac_pthread_self())) \
  304.         pthread_sched(); \
  305.       state_change = FALSE; \
  306.       is_in_kernel = FALSE; \
  307.       while (pthread_signonemptyset(&new_signals)) { \
  308.         is_in_kernel = TRUE; \
  309.         pthread_sched_new_signals(mac_pthread_self(), TRUE); \
  310.         if (!SAVE_CONTEXT(mac_pthread_self())) \
  311.           pthread_sched(); \
  312.         state_change = FALSE; \
  313.         is_in_kernel = FALSE; \
  314.       } \
  315.     } \
  316.   MACRO_END
  317.  
  318. #else !C_CONTEXT_SWITCH
  319. #ifdef NO_INLINE
  320.  
  321. #define CLEAR_KERNEL_FLAG pthread_sched()
  322.  
  323. #else !NO_INLINE
  324.  
  325. #define SHARED_CLEAR_KERNEL_FLAG \
  326.   MACRO_BEGIN \
  327.     is_in_kernel = FALSE; \
  328.     if (state_change) \
  329.       pthread_sched(); \
  330.   MACRO_END
  331. #endif NO_INLINE
  332.  
  333. #endif C_CONTEXT_SWITCH
  334.  
  335.  
  336. #ifdef RR_SWITCH
  337. #define CLEAR_KERNEL_FLAG \
  338.   MACRO_BEGIN \
  339.     if ((mac_pthread_self()->queue == &ready) && (ready.head != ready.tail)) { \
  340.       pthread_q_deq(&ready,mac_pthread_self(),PRIMARY_QUEUE); \
  341.       pthread_q_enq_tail(&ready); \
  342.     } \
  343.     SHARED_CLEAR_KERNEL_FLAG; \
  344.   MACRO_END
  345.  
  346. #elif RAND_SWITCH
  347. #define CLEAR_KERNEL_FLAG \
  348.   MACRO_BEGIN \
  349.     if ((mac_pthread_self()->queue == &ready) && (ready.head != ready.tail) \
  350.         && ((int)random()&01)) { \
  351.       pthread_q_exchange_rand(&ready); \
  352.     } \
  353.     SHARED_CLEAR_KERNEL_FLAG; \
  354.   MACRO_END
  355.  
  356. #else
  357. #if defined(DEBUG) && !defined(IO)
  358. #define CLEAR_KERNEL_FLAG \
  359.   MACRO_BEGIN \
  360.     if (!is_in_kernel) \
  361.       fprintf(stderr, clear_warning); \
  362.     SHARED_CLEAR_KERNEL_FLAG; \
  363.     if (ready.head->attr.prio < ready.tail->attr.prio) \
  364.       fprintf(stderr, prio_warning); \
  365.   MACRO_END
  366.  
  367. #else !DEBUG || IO
  368. #define CLEAR_KERNEL_FLAG SHARED_CLEAR_KERNEL_FLAG
  369. #endif DEBUG && !IO
  370. #endif
  371.  
  372. #ifdef C_CONTEXT_SWITCH
  373. #define SIG_CLEAR_KERNEL_FLAG(b) \
  374.   MACRO_BEGIN \
  375.     if(!SAVE_CONTEXT(mac_pthread_self())) \
  376.       pthread_handle_pending_signals_wrapper(); \
  377.     state_change = FALSE; \
  378.     is_in_kernel = FALSE; \
  379.     while (pthread_signonemptyset(&new_signals)) { \
  380.       is_in_kernel = TRUE; \
  381.       pthread_sched_new_signals(mac_pthread_self(), TRUE); \
  382.       if (!SAVE_CONTEXT(mac_pthread_self())) \
  383.         pthread_sched(); \
  384.       state_change = FALSE; \
  385.       is_in_kernel = FALSE; \
  386.     } \
  387.   MACRO_END
  388. #else !C_CONTEXT_SWITCH
  389. #define SIG_CLEAR_KERNEL_FLAG(b) pthread_handle_pending_signals_wrapper(b)
  390. #endif C_CONTEXT_SWITCH
  391.  
  392. #ifdef SIM_KERNEL
  393. #define SIM_SYSCALL(cond) if (cond) getpid()
  394. #else !SIM_KERNEL
  395. #define SIM_SYSCALL(cond)
  396. #endif !SIM_KERNEL
  397.  
  398. #ifdef C_CONTEXT_SWITCH
  399.  
  400. struct kernel_stack {
  401.   char body[TEMPSTACK_SIZE];
  402.   char stack[SA(MINFRAME)];
  403. };
  404. #define KERNEL_STACK struct kernel_stack
  405. #define pthread_tempstack_top pthread_tempstack.stack
  406.  
  407. #else !C_CONTEXT_SWITCH
  408.  
  409. #define KERNEL_STACK char
  410. #define pthread_tempstack_top &pthread_tempstack
  411.  
  412. #endif !C_CONTEXT_SWITCH
  413.  
  414.  
  415. #ifndef    MACRO_BEGIN
  416.  
  417. #define    MACRO_BEGIN    do {
  418.  
  419. #ifndef    lint
  420. #define    MACRO_END    } while (0)
  421. #else    lint
  422. extern int _NEVER_;
  423. #define    MACRO_END    } while (_NEVER_)
  424. #endif    lint
  425.  
  426. #endif !MACRO_BEGIN
  427.  
  428. #endif /*!_pthread_pthread_internals_h*/
  429.