| 1 | /*
|
|---|
| 2 | * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
|
|---|
| 3 | * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
|
|---|
| 4 | * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
|
|---|
| 5 | *
|
|---|
| 6 | * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
|
|---|
| 7 | * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
|
|---|
| 8 | *
|
|---|
| 9 | * Permission is hereby granted to use or copy this program
|
|---|
| 10 | * for any purpose, provided the above notices are retained on all copies.
|
|---|
| 11 | * Permission to modify the code and to distribute modified code is granted,
|
|---|
| 12 | * provided the above notices are retained, and a notice that the code was
|
|---|
| 13 | * modified is included with the above copyright notice.
|
|---|
| 14 | */
|
|---|
| 15 | /*
|
|---|
| 16 | * Support code for Irix (>=6.2) Pthreads. This relies on properties
|
|---|
| 17 | * not guaranteed by the Pthread standard. It may or may not be portable
|
|---|
| 18 | * to other implementations.
|
|---|
| 19 | *
|
|---|
| 20 | * This now also includes an initial attempt at thread support for
|
|---|
| 21 | * HP/UX 11.
|
|---|
| 22 | *
|
|---|
| 23 | * Note that there is a lot of code duplication between linux_threads.c
|
|---|
| 24 | * and irix_threads.c; any changes made here may need to be reflected
|
|---|
| 25 | * there too.
|
|---|
| 26 | */
|
|---|
| 27 |
|
|---|
| 28 | # if defined(GC_IRIX_THREADS)
|
|---|
| 29 |
|
|---|
| 30 | # include "private/gc_priv.h"
|
|---|
| 31 | # include <pthread.h>
|
|---|
| 32 | # include <semaphore.h>
|
|---|
| 33 | # include <time.h>
|
|---|
| 34 | # include <errno.h>
|
|---|
| 35 | # include <unistd.h>
|
|---|
| 36 | # include <sys/mman.h>
|
|---|
| 37 | # include <sys/time.h>
|
|---|
| 38 |
|
|---|
| 39 | #undef pthread_create
|
|---|
| 40 | #undef pthread_sigmask
|
|---|
| 41 | #undef pthread_join
|
|---|
| 42 | #undef pthread_detach
|
|---|
| 43 |
|
|---|
| 44 | void GC_thr_init();
|
|---|
| 45 |
|
|---|
| 46 | #if 0
|
|---|
| 47 | void GC_print_sig_mask()
|
|---|
| 48 | {
|
|---|
| 49 | sigset_t blocked;
|
|---|
| 50 | int i;
|
|---|
| 51 |
|
|---|
| 52 | if (pthread_sigmask(SIG_BLOCK, NULL, &blocked) != 0)
|
|---|
| 53 | ABORT("pthread_sigmask");
|
|---|
| 54 | GC_printf0("Blocked: ");
|
|---|
| 55 | for (i = 1; i <= MAXSIG; i++) {
|
|---|
| 56 | if (sigismember(&blocked, i)) { GC_printf1("%ld ",(long) i); }
|
|---|
| 57 | }
|
|---|
| 58 | GC_printf0("\n");
|
|---|
| 59 | }
|
|---|
| 60 | #endif
|
|---|
| 61 |
|
|---|
| 62 | /* We use the allocation lock to protect thread-related data structures. */
|
|---|
| 63 |
|
|---|
| 64 | /* The set of all known threads. We intercept thread creation and */
|
|---|
| 65 | /* joins. We never actually create detached threads. We allocate all */
|
|---|
| 66 | /* new thread stacks ourselves. These allow us to maintain this */
|
|---|
| 67 | /* data structure. */
|
|---|
| 68 | /* Protected by GC_thr_lock. */
|
|---|
| 69 | /* Some of this should be declared volatile, but that's incosnsistent */
|
|---|
| 70 | /* with some library routine declarations. */
|
|---|
| 71 | typedef struct GC_Thread_Rep {
|
|---|
| 72 | struct GC_Thread_Rep * next; /* More recently allocated threads */
|
|---|
| 73 | /* with a given pthread id come */
|
|---|
| 74 | /* first. (All but the first are */
|
|---|
| 75 | /* guaranteed to be dead, but we may */
|
|---|
| 76 | /* not yet have registered the join.) */
|
|---|
| 77 | pthread_t id;
|
|---|
| 78 | word stop;
|
|---|
| 79 | # define NOT_STOPPED 0
|
|---|
| 80 | # define PLEASE_STOP 1
|
|---|
| 81 | # define STOPPED 2
|
|---|
| 82 | word flags;
|
|---|
| 83 | # define FINISHED 1 /* Thread has exited. */
|
|---|
| 84 | # define DETACHED 2 /* Thread is intended to be detached. */
|
|---|
| 85 | # define CLIENT_OWNS_STACK 4
|
|---|
| 86 | /* Stack was supplied by client. */
|
|---|
| 87 | ptr_t stack;
|
|---|
| 88 | ptr_t stack_ptr; /* Valid only when stopped. */
|
|---|
| 89 | /* But must be within stack region at */
|
|---|
| 90 | /* all times. */
|
|---|
| 91 | size_t stack_size; /* 0 for original thread. */
|
|---|
| 92 | void * status; /* Used only to avoid premature */
|
|---|
| 93 | /* reclamation of any data it might */
|
|---|
| 94 | /* reference. */
|
|---|
| 95 | } * GC_thread;
|
|---|
| 96 |
|
|---|
| 97 | GC_thread GC_lookup_thread(pthread_t id);
|
|---|
| 98 |
|
|---|
| 99 | /*
|
|---|
| 100 | * The only way to suspend threads given the pthread interface is to send
|
|---|
| 101 | * signals. Unfortunately, this means we have to reserve
|
|---|
| 102 | * a signal, and intercept client calls to change the signal mask.
|
|---|
| 103 | * We use SIG_SUSPEND, defined in gc_priv.h.
|
|---|
| 104 | */
|
|---|
| 105 |
|
|---|
| 106 | pthread_mutex_t GC_suspend_lock = PTHREAD_MUTEX_INITIALIZER;
|
|---|
|
|---|