home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / os / kludge03.tz / kludge03 / mk74 / user / threads / cthreads.h < prev    next >
C/C++ Source or Header  |  1992-05-23  |  14KB  |  557 lines

  1. /* 
  2.  * Mach Operating System
  3.  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
  4.  * All Rights Reserved.
  5.  * 
  6.  * Permission to use, copy, modify and distribute this software and its
  7.  * documentation is hereby granted, provided that both the copyright
  8.  * notice and this permission notice appear in all copies of the
  9.  * software, derivative works or modified versions, and any portions
  10.  * thereof, and that both notices appear in supporting documentation.
  11.  * 
  12.  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
  13.  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
  14.  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  15.  * 
  16.  * Carnegie Mellon requests users of this software to return to
  17.  * 
  18.  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
  19.  *  School of Computer Science
  20.  *  Carnegie Mellon University
  21.  *  Pittsburgh PA 15213-3890
  22.  * 
  23.  * any improvements or extensions that they make and grant Carnegie Mellon
  24.  * the rights to redistribute these changes.
  25.  */
  26. /*
  27.  * HISTORY
  28.  * $Log:    cthreads.h,v $
  29.  * Revision 2.12  92/05/22  18:38:36  jfriedl
  30.  *     From Mike Kupfer <kupfer@sprite.Berkeley.EDU>:
  31.  *     Add declaration for cthread_wire().
  32.  *     Merge in Jonathan Chew's changes for thread-local data.
  33.  *     Use MACRO_BEGIN and MACRO_END.
  34.  * 
  35.  * Revision 1.8  91/03/25  14:14:49  jjc
  36.  *     For compatibility with cthread_data:
  37.  *         1) Added private_data field to cthread structure
  38.  *            for use by POSIX thread specific data routines.
  39.  *         2) Conditionalized old data field used by cthread_data
  40.  *            under CTHREAD_DATA for binary compatibility.
  41.  *         3) Changed macros, cthread_set_data and cthread_data, 
  42.  *            into routines which use the POSIX routines for 
  43.  *            source compatibility.
  44.  *            Also, conditionalized under CTHREAD_DATA.
  45.  *     [91/03/18            jjc]
  46.  *     Added support for multiplexing the thread specific global
  47.  *     variable, cthread_data, using the POSIX threads interface
  48.  *     for thread private data.
  49.  *     [91/03/14            jjc]
  50.  *
  51.  * Revision 2.11  91/08/03  18:20:15  jsb
  52.  *     Removed the infamous line 122.
  53.  *     [91/08/01  22:40:24  jsb]
  54.  * 
  55.  * Revision 2.10  91/07/31  18:35:42  dbg
  56.  *     Fix the standard-C conditional: it's __STDC__.
  57.  * 
  58.  *     Allow for macro-redefinition of cthread_sp, spin_try_lock,
  59.  *     spin_unlock (from machine/cthreads.h).
  60.  *     [91/07/30  17:34:28  dbg]
  61.  * 
  62.  * Revision 2.9  91/05/14  17:56:42  mrt
  63.  *     Correcting copyright
  64.  * 
  65.  * Revision 2.8  91/02/14  14:19:52  mrt
  66.  *     Added new Mach copyright
  67.  *     [91/02/13  12:41:15  mrt]
  68.  * 
  69.  * Revision 2.7  90/11/05  14:37:12  rpd
  70.  *     Include machine/cthreads.h.  Added spin_lock_t.
  71.  *     [90/10/31            rwd]
  72.  * 
  73.  * Revision 2.6  90/10/12  13:07:24  rpd
  74.  *     Channge to allow for positive stack growth.
  75.  *     [90/10/10            rwd]
  76.  * 
  77.  * Revision 2.5  90/09/09  14:34:56  rpd
  78.  *     Remove mutex_special and debug_mutex.
  79.  *     [90/08/24            rwd]
  80.  * 
  81.  * Revision 2.4  90/08/07  14:31:14  rpd
  82.  *     Removed RCS keyword nonsense.
  83.  * 
  84.  * Revision 2.3  90/01/19  14:37:18  rwd
  85.  *     Add back pointer to cthread structure.
  86.  *     [90/01/03            rwd]
  87.  *     Change definition of cthread_init and change ur_cthread_self macro
  88.  *     to reflect movement of self pointer on stack.
  89.  *     [89/12/18  19:18:34  rwd]
  90.  * 
  91.  * Revision 2.2  89/12/08  19:53:49  rwd
  92.  *     Change spin_try_lock to int.
  93.  *     [89/11/30            rwd]
  94.  *     Changed mutex macros to deal with special mutexs
  95.  *     [89/11/26            rwd]
  96.  *     Make mutex_{set,clear}_special routines instead of macros.
  97.  *     [89/11/25            rwd]
  98.  *     Added mutex_special to specify a need to context switch on this
  99.  *     mutex.
  100.  *     [89/11/21            rwd]
  101.  * 
  102.  *     Made mutex_lock a macro trying to grab the spin_lock first.
  103.  *     [89/11/13            rwd]
  104.  *     Removed conditionals.  Mutexes are more like conditions now.
  105.  *     Changed for limited kernel thread version.
  106.  *     [89/10/23            rwd]
  107.  * 
  108.  * Revision 2.1  89/08/03  17:09:40  rwd
  109.  * Created.
  110.  * 
  111.  *
  112.  * 28-Oct-88  Eric Cooper (ecc) at Carnegie Mellon University
  113.  *    Implemented spin_lock() as test and test-and-set logic
  114.  *    (using mutex_try_lock()) in sync.c.  Changed ((char *) 0)
  115.  *    to 0, at Mike Jones's suggestion, and turned on ANSI-style
  116.  *    declarations in either C++ or _STDC_.
  117.  *
  118.  * 29-Sep-88  Eric Cooper (ecc) at Carnegie Mellon University
  119.  *    Changed NULL to ((char *) 0) to avoid dependency on <stdio.h>,
  120.  *    at Alessandro Forin's suggestion.
  121.  *
  122.  * 08-Sep-88  Alessandro Forin (af) at Carnegie Mellon University
  123.  *    Changed queue_t to cthread_queue_t and string_t to char *
  124.  *    to avoid conflicts.
  125.  *
  126.  * 01-Apr-88  Eric Cooper (ecc) at Carnegie Mellon University
  127.  *    Changed compound statement macros to use the
  128.  *    do { ... } while (0) trick, so that they work
  129.  *    in all statement contexts.
  130.  *
  131.  * 19-Feb-88  Eric Cooper (ecc) at Carnegie Mellon University
  132.  *    Made spin_unlock() and mutex_unlock() into procedure calls
  133.  *    rather than macros, so that even smart compilers can't reorder
  134.  *    the clearing of the lock.  Suggested by Jeff Eppinger.
  135.  *    Removed the now empty <machine>/cthreads.h.
  136.  * 
  137.  * 01-Dec-87  Eric Cooper (ecc) at Carnegie Mellon University
  138.  *    Changed cthread_self() to mask the current SP to find
  139.  *    the self pointer stored at the base of the stack.
  140.  *
  141.  * 22-Jul-87  Eric Cooper (ecc) at Carnegie Mellon University
  142.  *    Fixed bugs in mutex_set_name and condition_set_name
  143.  *    due to bad choice of macro formal parameter name.
  144.  *
  145.  * 21-Jul-87  Eric Cooper (ecc) at Carnegie Mellon University
  146.  *    Moved #include <machine/cthreads.h> to avoid referring
  147.  *    to types before they are declared (required by C++).
  148.  *
  149.  *  9-Jul-87  Michael Jones (mbj) at Carnegie Mellon University
  150.  *    Added conditional type declarations for C++.
  151.  *    Added _cthread_init_routine and _cthread_exit_routine variables
  152.  *    for automatic initialization and finalization by crt0.
  153.  */
  154. /*
  155.  *     File:     cthreads.h
  156.  *    Author: Eric Cooper, Carnegie Mellon University
  157.  *    Date:    Jul, 1987
  158.  *
  159.  *     Definitions for the C Threads package.
  160.  *
  161.  */
  162.  
  163.  
  164. #ifndef    _CTHREADS_
  165. #define    _CTHREADS_ 1
  166.  
  167. #include <machine/cthreads.h>
  168.  
  169. #if    c_plusplus || __STDC__
  170.  
  171. #ifndef    C_ARG_DECLS
  172. #define    C_ARG_DECLS(arglist)    arglist
  173. #endif    /* not C_ARG_DECLS */
  174.  
  175. typedef void *any_t;
  176.  
  177. #else    /* not (c_plusplus || __STDC__) */
  178.  
  179. #ifndef    C_ARG_DECLS
  180. #define    C_ARG_DECLS(arglist)    ()
  181. #endif    /* not C_ARG_DECLS */
  182.  
  183. typedef char *any_t;
  184.  
  185. #endif    /* not (c_plusplus || __STDC__) */
  186.  
  187. #include <mach/mach.h>
  188. #include <mach/machine/vm_param.h>
  189.  
  190. #ifndef    TRUE
  191. #define    TRUE    1
  192. #define    FALSE    0
  193. #endif    /* TRUE */
  194.  
  195. #ifndef MACRO_BEGIN
  196.  
  197. #ifdef    lint
  198. int    NEVER;
  199. #else    lint
  200. #define    NEVER 0
  201. #endif    lint
  202.  
  203. #define    MACRO_BEGIN    do {
  204. #define    MACRO_END    } while (NEVER)
  205.  
  206. #endif    MACRO_BEGIN
  207.  
  208. /*
  209.  * C Threads package initialization.
  210.  */
  211.  
  212. extern int cthread_init();
  213. extern any_t calloc C_ARG_DECLS((unsigned n, unsigned size));
  214.  
  215. /*
  216.  * Queues.
  217.  */
  218. typedef struct cthread_queue {
  219.     struct cthread_queue_item *head;
  220.     struct cthread_queue_item *tail;
  221. } *cthread_queue_t;
  222.  
  223. typedef struct cthread_queue_item {
  224.     struct cthread_queue_item *next;
  225. } *cthread_queue_item_t;
  226.  
  227. #define    NO_QUEUE_ITEM    ((cthread_queue_item_t) 0)
  228.  
  229. #define    QUEUE_INITIALIZER    { NO_QUEUE_ITEM, NO_QUEUE_ITEM }
  230.  
  231. #define    cthread_queue_alloc()    ((cthread_queue_t) calloc(1, sizeof(struct cthread_queue)))
  232. #define    cthread_queue_init(q)    ((q)->head = (q)->tail = 0)
  233. #define    cthread_queue_free(q)    free((any_t) (q))
  234.  
  235. #define    cthread_queue_enq(q, x) \
  236.     MACRO_BEGIN \
  237.         (x)->next = 0; \
  238.         if ((q)->tail == 0) \
  239.             (q)->head = (cthread_queue_item_t) (x); \
  240.         else \
  241.             (q)->tail->next = (cthread_queue_item_t) (x); \
  242.         (q)->tail = (cthread_queue_item_t) (x); \
  243.     MACRO_END
  244.  
  245. #define    cthread_queue_preq(q, x) \
  246.     MACRO_BEGIN \
  247.         if ((q)->tail == 0) \
  248.             (q)->tail = (cthread_queue_item_t) (x); \
  249.         ((cthread_queue_item_t) (x))->next = (q)->head; \
  250.         (q)->head = (cthread_queue_item_t) (x); \
  251.     MACRO_END
  252.  
  253. #define    cthread_queue_head(q, t)    ((t) ((q)->head))
  254.  
  255. #define    cthread_queue_deq(q, t, x) \
  256.     MACRO_BEGIN \
  257.     if (((x) = (t) ((q)->head)) != 0 && \
  258.         ((q)->head = (cthread_queue_item_t) ((x)->next)) == 0) \
  259.         (q)->tail = 0; \
  260.     MACRO_END
  261.  
  262. #define    cthread_queue_map(q, t, f) \
  263.     MACRO_BEGIN \
  264.         register cthread_queue_item_t x, next; \
  265.         for (x = (cthread_queue_item_t) ((q)->head); x != 0; x = next) { \
  266.             next = x->next; \
  267.             (*(f))((t) x); \
  268.         } \
  269.     MACRO_END
  270.  
  271. /*
  272.  * Spin locks.
  273.  */
  274. extern void
  275. spin_lock_solid C_ARG_DECLS((spin_lock_t *p));
  276.  
  277. #ifndef    spin_unlock
  278. extern void
  279. spin_unlock C_ARG_DECLS((spin_lock_t *p));
  280. #endif
  281.  
  282. #ifndef    spin_try_lock
  283. extern int
  284. spin_try_lock C_ARG_DECLS((spin_lock_t *p));
  285. #endif
  286.  
  287. #define spin_lock(p) if (!spin_try_lock(p)) spin_lock_solid(p); else
  288.  
  289. /*
  290.  * Mutex objects.
  291.  */
  292. typedef struct mutex {
  293.     spin_lock_t lock;
  294.     char *name;
  295.     struct cthread_queue queue;
  296.     spin_lock_t held;
  297. } *mutex_t;
  298.  
  299. #define    MUTEX_INITIALIZER    { SPIN_LOCK_INITIALIZER, 0, QUEUE_INITIALIZER, SPIN_LOCK_INITIALIZER}
  300.  
  301. #define    mutex_alloc()        ((mutex_t) calloc(1, sizeof(struct mutex)))
  302. #define    mutex_init(m) \
  303.     MACRO_BEGIN \
  304.     spin_lock_init(&(m)->lock); \
  305.     cthread_queue_init(&(m)->queue); \
  306.     spin_lock_init(&(m)->held); \
  307.     MACRO_END
  308. #define    mutex_set_name(m, x)    ((m)->name = (x))
  309. #define    mutex_name(m)        ((m)->name != 0 ? (m)->name : "?")
  310. #define    mutex_clear(m)        /* nop */???
  311. #define    mutex_free(m)        free((any_t) (m))
  312.  
  313. extern void
  314. mutex_lock_solid C_ARG_DECLS((mutex_t m));        /* blocking */
  315.  
  316. extern void
  317. mutex_unlock_solid C_ARG_DECLS((mutex_t m));
  318.  
  319. #define mutex_try_lock(m) spin_try_lock(&(m)->held)
  320. #define mutex_lock(m) \
  321.     MACRO_BEGIN \
  322.     if (!spin_try_lock(&(m)->held)) { \
  323.         mutex_lock_solid(m); \
  324.     } \
  325.     MACRO_END
  326. #define mutex_unlock(m) \
  327.     MACRO_BEGIN \
  328.     if (spin_unlock(&(m)->held), \
  329.         cthread_queue_head(&(m)->queue, int) != 0) { \
  330.         mutex_unlock_solid(m); \
  331.     } \
  332.     MACRO_END
  333.  
  334. /*
  335.  * Condition variables.
  336.  */
  337. typedef struct condition {
  338.     spin_lock_t lock;
  339.     struct cthread_queue queue;
  340.     char *name;
  341. } *condition_t;
  342.  
  343. #define    CONDITION_INITIALIZER        { SPIN_LOCK_INITIALIZER, QUEUE_INITIALIZER, 0 }
  344.  
  345. #define    condition_alloc()        ((condition_t) calloc(1, sizeof(struct condition)))
  346. #define    condition_init(c) \
  347.     MACRO_BEGIN \
  348.     spin_lock_init(&(c)->lock); \
  349.     cthread_queue_init(&(c)->queue); \
  350.     MACRO_END
  351. #define    condition_set_name(c, x)    ((c)->name = (x))
  352. #define    condition_name(c)        ((c)->name != 0 ? (c)->name : "?")
  353. #define    condition_clear(c) \
  354.     MACRO_BEGIN \
  355.     condition_broadcast(c); \
  356.     spin_lock(&(c)->lock); \
  357.     MACRO_END
  358. #define    condition_free(c) \
  359.     MACRO_BEGIN \
  360.     condition_clear(c); \
  361.     free((any_t) (c)); \
  362.     MACRO_END
  363.  
  364. #define    condition_signal(c) \
  365.     MACRO_BEGIN \
  366.     if ((c)->queue.head) { \
  367.         cond_signal(c); \
  368.     } \
  369.     MACRO_END
  370.  
  371. #define    condition_broadcast(c) \
  372.     MACRO_BEGIN \
  373.     if ((c)->queue.head) { \
  374.         cond_broadcast(c); \
  375.     } \
  376.     MACRO_END
  377.  
  378. extern void
  379. cond_signal C_ARG_DECLS((condition_t c));
  380.  
  381. extern void
  382. cond_broadcast C_ARG_DECLS((condition_t c));
  383.  
  384. extern void
  385. condition_wait C_ARG_DECLS((condition_t c, mutex_t m));
  386.  
  387. /*
  388.  * Threads.
  389.  */
  390.  
  391. typedef any_t (*cthread_fn_t) C_ARG_DECLS((any_t arg));
  392.  
  393. #include <setjmp.h>
  394.  
  395. typedef struct cthread {
  396.     struct cthread *next;
  397.     struct mutex lock;
  398.     struct condition done;
  399.     int state;
  400.     jmp_buf catch;
  401.     cthread_fn_t func;
  402.     any_t arg;
  403.     any_t result;
  404.     char *name;
  405. #ifdef    CTHREAD_DATA
  406.     any_t data;
  407. #endif    CTHREAD_DATA
  408.     any_t private_data;
  409.     struct ur_cthread *ur;
  410. } *cthread_t;
  411.  
  412. #define    NO_CTHREAD    ((cthread_t) 0)
  413.  
  414. extern cthread_t
  415. cthread_fork C_ARG_DECLS((cthread_fn_t func, any_t arg));
  416.  
  417. extern void
  418. cthread_detach C_ARG_DECLS((cthread_t t));
  419.  
  420. extern any_t
  421. cthread_join C_ARG_DECLS((cthread_t t));
  422.  
  423. extern void
  424. cthread_yield();
  425.  
  426. extern void
  427. cthread_exit C_ARG_DECLS((any_t result));
  428.  
  429. /*
  430.  * This structure must agree with struct cproc in cthread_internals.h
  431.  */
  432. typedef struct ur_cthread {
  433.     struct ur_cthread *next;
  434.     cthread_t incarnation;
  435. } *ur_cthread_t;
  436.  
  437. #ifndef    cthread_sp
  438. extern int
  439. cthread_sp();
  440. #endif
  441.  
  442. extern int cthread_stack_mask;
  443.  
  444. #ifdef    STACK_GROWTH_UP
  445. #define    ur_cthread_ptr(sp) \
  446.     (* (ur_cthread_t *) ((sp) & cthread_stack_mask))
  447. #else    STACK_GROWTH_UP
  448. #define    ur_cthread_ptr(sp) \
  449.     (* (ur_cthread_t *) ( ((sp) | cthread_stack_mask) + 1 \
  450.                   - sizeof(ur_cthread_t *)) )
  451. #endif    STACK_GROWTH_UP
  452.  
  453. #define    ur_cthread_self()    (ur_cthread_ptr(cthread_sp()))
  454.  
  455. #define    cthread_assoc(id, t)    ((((ur_cthread_t) (id))->incarnation = (t)), \
  456.                 ((t) ? ((t)->ur = (ur_cthread_t)(id)) : 0))
  457. #define    cthread_self()        (ur_cthread_self()->incarnation)
  458.  
  459. extern void
  460. cthread_set_name C_ARG_DECLS((cthread_t t, char *name));
  461.  
  462. extern char *
  463. cthread_name C_ARG_DECLS((cthread_t t));
  464.  
  465. extern int
  466. cthread_count();
  467.  
  468. extern void
  469. cthread_set_limit C_ARG_DECLS((int n));
  470.  
  471. extern int
  472. cthread_limit();
  473.  
  474. extern void
  475. cthread_wire C_ARG_DECLS((void));
  476.  
  477. #ifdef    CTHREAD_DATA
  478. /*
  479.  * Set or get thread specific "global" variable
  480.  *
  481.  * The thread given must be the calling thread (ie. thread_self).
  482.  * XXX This is for compatibility with the old cthread_data. XXX
  483.  */
  484. extern int
  485. cthread_set_data C_ARG_DECLS((cthread_t t, any_t x));
  486.  
  487. extern any_t
  488. cthread_data C_ARG_DECLS((cthread_t t));
  489. #endif    CTHREAD_DATA
  490.   
  491. /* 
  492.  * Support for POSIX thread specific data
  493.  *
  494.  * Multiplexes a thread specific "global" variable
  495.  * into many thread specific "global" variables.
  496.  */
  497. #define CTHREAD_DATA_VALUE_NULL        (any_t)0
  498. #define    CTHREAD_KEY_INVALID        (cthread_key_t)-1
  499.  
  500. typedef int    cthread_key_t;
  501.  
  502. /*
  503.  * Create key to private data visible to all threads in task.
  504.  * Different threads may use same key, but the values bound to the key are
  505.  * maintained on a thread specific basis.
  506.  */
  507. extern int
  508. cthread_keycreate C_ARG_DECLS((cthread_key_t *key));
  509.  
  510. /*
  511.  * Get value currently bound to key for calling thread
  512.  */
  513. extern int
  514. cthread_getspecific C_ARG_DECLS((cthread_key_t key, any_t *value));
  515.  
  516. /*
  517.  * Bind value to given key for calling thread
  518.  */
  519. extern int
  520. cthread_setspecific C_ARG_DECLS((cthread_key_t key, any_t value));
  521.  
  522. /*
  523.  * Debugging support.
  524.  */
  525. #ifdef    DEBUG
  526.  
  527. #ifndef    ASSERT
  528. /*
  529.  * Assertion macro, similar to <assert.h>
  530.  */
  531. #include <stdio.h>
  532. #define    ASSERT(p) \
  533.     MACRO_BEGIN \
  534.     if (!(p)) { \
  535.         fprintf(stderr, \
  536.             "File %s, line %d: assertion p failed.\n", \
  537.             __FILE__, __LINE__); \
  538.         abort(); \
  539.     } \
  540.     MACRO_END
  541.  
  542. #endif    ASSERT
  543.  
  544. #define    SHOULDNT_HAPPEN    0
  545.  
  546. extern int cthread_debug;
  547.  
  548. #else    DEBUG
  549.  
  550. #ifndef    ASSERT
  551. #define    ASSERT(p)
  552. #endif    ASSERT
  553.  
  554. #endif    DEBUG
  555.  
  556. #endif    _CTHREADS_
  557.