source: trunk/src/gcc/boehm-gc/irix_threads.c@ 1289

Last change on this file since 1289 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 21.4 KB
RevLine 
[2]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
44void GC_thr_init();
45
46#if 0
47void 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. */
71typedef 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
97GC_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
106pthread_mutex_t GC_suspend_lock = PTHREAD_MUTEX_INITIALIZER;
107 /* Number of threads stopped so far */
108pthread_cond_t GC_suspend_ack_cv = PTHREAD_COND_INITIALIZER;
109pthread_cond_t GC_continue_cv = PTHREAD_COND_INITIALIZER;
110
111void GC_suspend_handler(int sig)
112{
113 int dummy;
114 GC_thread me;
115 sigset_t all_sigs;
116 sigset_t old_sigs;
117 int i;
118
119 if (sig != SIG_SUSPEND) ABORT("Bad signal in suspend_handler");
120 me = GC_lookup_thread(pthread_self());
121 /* The lookup here is safe, since I'm doing this on behalf */
122 /* of a thread which holds the allocation lock in order */
123 /* to stop the world. Thus concurrent modification of the */
124 /* data structure is impossible. */
125 if (PLEASE_STOP != me -> stop) {
126 /* Misdirected signal. */
127 pthread_mutex_unlock(&GC_suspend_lock);
128 return;
129 }
130 pthread_mutex_lock(&GC_suspend_lock);
131 me -> stack_ptr = (ptr_t)(&dummy);
132 me -> stop = STOPPED;
133 pthread_cond_signal(&GC_suspend_ack_cv);
134 pthread_cond_wait(&GC_continue_cv, &GC_suspend_lock);
135 pthread_mutex_unlock(&GC_suspend_lock);
136 /* GC_printf1("Continuing 0x%x\n", pthread_self()); */
137}
138
139
140GC_bool GC_thr_initialized = FALSE;
141
142size_t GC_min_stack_sz;
143
144# define N_FREE_LISTS 25
145ptr_t GC_stack_free_lists[N_FREE_LISTS] = { 0 };
146 /* GC_stack_free_lists[i] is free list for stacks of */
147 /* size GC_min_stack_sz*2**i. */
148 /* Free lists are linked through first word. */
149
150/* Return a stack of size at least *stack_size. *stack_size is */
151/* replaced by the actual stack size. */
152/* Caller holds allocation lock. */
153ptr_t GC_stack_alloc(size_t * stack_size)
154{
155 register size_t requested_sz = *stack_size;
156 register size_t search_sz = GC_min_stack_sz;
157 register int index = 0; /* = log2(search_sz/GC_min_stack_sz) */
158 register ptr_t result;
159
160 while (search_sz < requested_sz) {
161 search_sz *= 2;
162 index++;
163 }