annotate gc/solaris_threads.c @ 51488:5de98dce4bd1

*** empty log message ***
author Dave Love <fx@gnu.org>
date Thu, 05 Jun 2003 17:49:22 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
51488
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
1 /*
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
2 * Copyright (c) 1994 by Xerox Corporation. All rights reserved.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
3 *
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
4 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
5 * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
6 *
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
7 * Permission is hereby granted to use or copy this program
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
8 * for any purpose, provided the above notices are retained on all copies.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
9 * Permission to modify the code and to distribute modified code is granted,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
10 * provided the above notices are retained, and a notice that the code was
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
11 * modified is included with the above copyright notice.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
12 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
13 /*
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
14 * Support code for Solaris threads. Provides functionality we wish Sun
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
15 * had provided. Relies on some information we probably shouldn't rely on.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
16 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
17 /* Boehm, September 14, 1994 4:44 pm PDT */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
18
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
19 # if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
20
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
21 # include "private/gc_priv.h"
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
22 # include "private/solaris_threads.h"
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
23 # include <thread.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
24 # include <synch.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
25 # include <signal.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
26 # include <fcntl.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
27 # include <sys/types.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
28 # include <sys/mman.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
29 # include <sys/time.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
30 # include <sys/resource.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
31 # include <sys/stat.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
32 # include <sys/syscall.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
33 # include <sys/procfs.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
34 # include <sys/lwp.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
35 # include <sys/reg.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
36 # define _CLASSIC_XOPEN_TYPES
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
37 # include <unistd.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
38 # include <errno.h>
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
39
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
40 #ifdef HANDLE_FORK
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
41 --> Not yet supported. Try porting the code from linux_threads.c.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
42 #endif
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
43
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
44 /*
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
45 * This is the default size of the LWP arrays. If there are more LWPs
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
46 * than this when a stop-the-world GC happens, set_max_lwps will be
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
47 * called to cope.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
48 * This must be higher than the number of LWPs at startup time.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
49 * The threads library creates a thread early on, so the min. is 3
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
50 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
51 # define DEFAULT_MAX_LWPS 4
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
52
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
53 #undef thr_join
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
54 #undef thr_create
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
55 #undef thr_suspend
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
56 #undef thr_continue
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
57
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
58 cond_t GC_prom_join_cv; /* Broadcast when any thread terminates */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
59 cond_t GC_create_cv; /* Signalled when a new undetached */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
60 /* thread starts. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
61
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
62
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
63 #ifdef MMAP_STACKS
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
64 static int GC_zfd;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
65 #endif /* MMAP_STACKS */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
66
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
67 /* We use the allocation lock to protect thread-related data structures. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
68
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
69 /* We stop the world using /proc primitives. This makes some */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
70 /* minimal assumptions about the threads implementation. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
71 /* We don't play by the rules, since the rules make this */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
72 /* impossible (as of Solaris 2.3). Also note that as of */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
73 /* Solaris 2.3 the various thread and lwp suspension */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
74 /* primitives failed to stop threads by the time the request */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
75 /* is completed. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
76
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
77
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
78 static sigset_t old_mask;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
79
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
80 /* Sleep for n milliseconds, n < 1000 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
81 void GC_msec_sleep(int n)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
82 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
83 struct timespec ts;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
84
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
85 ts.tv_sec = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
86 ts.tv_nsec = 1000000*n;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
87 if (syscall(SYS_nanosleep, &ts, 0) < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
88 ABORT("nanosleep failed");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
89 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
90 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
91 /* Turn off preemption; gross but effective. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
92 /* Caller has allocation lock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
93 /* Actually this is not needed under Solaris 2.3 and */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
94 /* 2.4, but hopefully that'll change. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
95 void preempt_off()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
96 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
97 sigset_t set;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
98
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
99 (void)sigfillset(&set);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
100 sigdelset(&set, SIGABRT);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
101 syscall(SYS_sigprocmask, SIG_SETMASK, &set, &old_mask);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
102 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
103
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
104 void preempt_on()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
105 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
106 syscall(SYS_sigprocmask, SIG_SETMASK, &old_mask, NULL);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
107 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
108
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
109 int GC_main_proc_fd = -1;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
110
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
111
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
112 struct lwp_cache_entry {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
113 lwpid_t lc_id;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
114 int lc_descr; /* /proc file descriptor. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
115 } GC_lwp_cache_default[DEFAULT_MAX_LWPS];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
116
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
117 static int max_lwps = DEFAULT_MAX_LWPS;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
118 static struct lwp_cache_entry *GC_lwp_cache = GC_lwp_cache_default;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
119
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
120 static prgregset_t GC_lwp_registers_default[DEFAULT_MAX_LWPS];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
121 static prgregset_t *GC_lwp_registers = GC_lwp_registers_default;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
122
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
123 /* Return a file descriptor for the /proc entry corresponding */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
124 /* to the given lwp. The file descriptor may be stale if the */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
125 /* lwp exited and a new one was forked. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
126 static int open_lwp(lwpid_t id)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
127 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
128 int result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
129 static int next_victim = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
130 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
131
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
132 for (i = 0; i < max_lwps; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
133 if (GC_lwp_cache[i].lc_id == id) return(GC_lwp_cache[i].lc_descr);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
134 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
135 result = syscall(SYS_ioctl, GC_main_proc_fd, PIOCOPENLWP, &id);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
136 /*
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
137 * If PIOCOPENLWP fails, try closing fds in the cache until it succeeds.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
138 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
139 if (result < 0 && errno == EMFILE) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
140 for (i = 0; i < max_lwps; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
141 if (GC_lwp_cache[i].lc_id != 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
142 (void)syscall(SYS_close, GC_lwp_cache[i].lc_descr);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
143 result = syscall(SYS_ioctl, GC_main_proc_fd, PIOCOPENLWP, &id);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
144 if (result >= 0 || (result < 0 && errno != EMFILE))
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
145 break;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
146 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
147 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
148 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
149 if (result < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
150 if (errno == EMFILE) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
151 ABORT("Too many open files");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
152 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
153 return(-1) /* exited? */;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
154 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
155 if (GC_lwp_cache[next_victim].lc_id != 0)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
156 (void)syscall(SYS_close, GC_lwp_cache[next_victim].lc_descr);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
157 GC_lwp_cache[next_victim].lc_id = id;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
158 GC_lwp_cache[next_victim].lc_descr = result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
159 if (++next_victim >= max_lwps)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
160 next_victim = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
161 return(result);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
162 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
163
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
164 static void uncache_lwp(lwpid_t id)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
165 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
166 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
167
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
168 for (i = 0; i < max_lwps; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
169 if (GC_lwp_cache[i].lc_id == id) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
170 (void)syscall(SYS_close, GC_lwp_cache[id].lc_descr);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
171 GC_lwp_cache[i].lc_id = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
172 break;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
173 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
174 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
175 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
176 /* Sequence of current lwp ids */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
177 static lwpid_t GC_current_ids_default[DEFAULT_MAX_LWPS + 1];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
178 static lwpid_t *GC_current_ids = GC_current_ids_default;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
179
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
180 /* Temporary used below (can be big if large number of LWPs) */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
181 static lwpid_t last_ids_default[DEFAULT_MAX_LWPS + 1];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
182 static lwpid_t *last_ids = last_ids_default;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
183
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
184
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
185 #define ROUNDUP(n) WORDS_TO_BYTES(ROUNDED_UP_WORDS(n))
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
186
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
187 static void set_max_lwps(GC_word n)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
188 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
189 char *mem;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
190 char *oldmem;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
191 int required_bytes = ROUNDUP(n * sizeof(struct lwp_cache_entry))
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
192 + ROUNDUP(n * sizeof(prgregset_t))
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
193 + ROUNDUP((n + 1) * sizeof(lwpid_t))
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
194 + ROUNDUP((n + 1) * sizeof(lwpid_t));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
195
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
196 GC_expand_hp_inner(divHBLKSZ((word)required_bytes));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
197 oldmem = mem = GC_scratch_alloc(required_bytes);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
198 if (0 == mem) ABORT("No space for lwp data structures");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
199
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
200 /*
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
201 * We can either flush the old lwp cache or copy it over. Do the latter.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
202 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
203 memcpy(mem, GC_lwp_cache, max_lwps * sizeof(struct lwp_cache_entry));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
204 GC_lwp_cache = (struct lwp_cache_entry*)mem;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
205 mem += ROUNDUP(n * sizeof(struct lwp_cache_entry));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
206
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
207 BZERO(GC_lwp_registers, max_lwps * sizeof(GC_lwp_registers[0]));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
208 GC_lwp_registers = (prgregset_t *)mem;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
209 mem += ROUNDUP(n * sizeof(prgregset_t));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
210
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
211
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
212 GC_current_ids = (lwpid_t *)mem;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
213 mem += ROUNDUP((n + 1) * sizeof(lwpid_t));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
214
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
215 last_ids = (lwpid_t *)mem;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
216 mem += ROUNDUP((n + 1)* sizeof(lwpid_t));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
217
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
218 if (mem > oldmem + required_bytes)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
219 ABORT("set_max_lwps buffer overflow");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
220
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
221 max_lwps = n;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
222 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
223
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
224
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
225 /* Stop all lwps in process. Assumes preemption is off. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
226 /* Caller has allocation lock (and any other locks he may */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
227 /* need). */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
228 static void stop_all_lwps()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
229 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
230 int lwp_fd;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
231 char buf[30];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
232 prstatus_t status;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
233 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
234 GC_bool changed;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
235 lwpid_t me = _lwp_self();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
236
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
237 if (GC_main_proc_fd == -1) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
238 sprintf(buf, "/proc/%d", getpid());
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
239 GC_main_proc_fd = syscall(SYS_open, buf, O_RDONLY);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
240 if (GC_main_proc_fd < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
241 if (errno == EMFILE)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
242 ABORT("/proc open failed: too many open files");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
243 GC_printf1("/proc open failed: errno %d", errno);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
244 abort();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
245 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
246 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
247 BZERO(GC_lwp_registers, sizeof (prgregset_t) * max_lwps);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
248 for (i = 0; i < max_lwps; i++)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
249 last_ids[i] = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
250 for (;;) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
251 if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCSTATUS, &status) < 0)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
252 ABORT("Main PIOCSTATUS failed");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
253 if (status.pr_nlwp < 1)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
254 ABORT("Invalid number of lwps returned by PIOCSTATUS");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
255 if (status.pr_nlwp >= max_lwps) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
256 set_max_lwps(status.pr_nlwp*2 + 10);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
257 /*
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
258 * The data in the old GC_current_ids and
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
259 * GC_lwp_registers has been trashed. Cleaning out last_ids
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
260 * will make sure every LWP gets re-examined.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
261 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
262 for (i = 0; i < max_lwps; i++)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
263 last_ids[i] = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
264 continue;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
265 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
266 if (syscall(SYS_ioctl, GC_main_proc_fd, PIOCLWPIDS, GC_current_ids) < 0)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
267 ABORT("PIOCLWPIDS failed");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
268 changed = FALSE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
269 for (i = 0; GC_current_ids[i] != 0 && i < max_lwps; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
270 if (GC_current_ids[i] != last_ids[i]) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
271 changed = TRUE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
272 if (GC_current_ids[i] != me) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
273 /* PIOCSTOP doesn't work without a writable */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
274 /* descriptor. And that makes the process */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
275 /* undebuggable. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
276 if (_lwp_suspend(GC_current_ids[i]) < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
277 /* Could happen if the lwp exited */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
278 uncache_lwp(GC_current_ids[i]);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
279 GC_current_ids[i] = me; /* ignore */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
280 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
281 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
282 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
283 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
284 /*
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
285 * In the unlikely event something does a fork between the
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
286 * PIOCSTATUS and the PIOCLWPIDS.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
287 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
288 if (i >= max_lwps)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
289 continue;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
290 /* All lwps in GC_current_ids != me have been suspended. Note */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
291 /* that _lwp_suspend is idempotent. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
292 for (i = 0; GC_current_ids[i] != 0; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
293 if (GC_current_ids[i] != last_ids[i]) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
294 if (GC_current_ids[i] != me) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
295 lwp_fd = open_lwp(GC_current_ids[i]);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
296 if (lwp_fd == -1)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
297 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
298 GC_current_ids[i] = me;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
299 continue;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
300 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
301 /* LWP should be stopped. Empirically it sometimes */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
302 /* isn't, and more frequently the PR_STOPPED flag */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
303 /* is not set. Wait for PR_STOPPED. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
304 if (syscall(SYS_ioctl, lwp_fd,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
305 PIOCSTATUS, &status) < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
306 /* Possible if the descriptor was stale, or */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
307 /* we encountered the 2.3 _lwp_suspend bug. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
308 uncache_lwp(GC_current_ids[i]);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
309 GC_current_ids[i] = me; /* handle next time. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
310 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
311 while (!(status.pr_flags & PR_STOPPED)) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
312 GC_msec_sleep(1);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
313 if (syscall(SYS_ioctl, lwp_fd,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
314 PIOCSTATUS, &status) < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
315 ABORT("Repeated PIOCSTATUS failed");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
316 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
317 if (status.pr_flags & PR_STOPPED) break;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
318
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
319 GC_msec_sleep(20);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
320 if (syscall(SYS_ioctl, lwp_fd,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
321 PIOCSTATUS, &status) < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
322 ABORT("Repeated PIOCSTATUS failed");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
323 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
324 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
325 if (status.pr_who != GC_current_ids[i]) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
326 /* can happen if thread was on death row */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
327 uncache_lwp(GC_current_ids[i]);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
328 GC_current_ids[i] = me; /* handle next time. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
329 continue;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
330 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
331 /* Save registers where collector can */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
332 /* find them. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
333 BCOPY(status.pr_reg, GC_lwp_registers[i],
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
334 sizeof (prgregset_t));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
335 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
336 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
337 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
338 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
339 if (!changed) break;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
340 for (i = 0; i < max_lwps; i++) last_ids[i] = GC_current_ids[i];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
341 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
342 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
343
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
344 /* Restart all lwps in process. Assumes preemption is off. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
345 static void restart_all_lwps()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
346 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
347 int lwp_fd;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
348 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
349 GC_bool changed;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
350 lwpid_t me = _lwp_self();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
351 # define PARANOID
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
352
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
353 for (i = 0; GC_current_ids[i] != 0; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
354 # ifdef PARANOID
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
355 if (GC_current_ids[i] != me) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
356 int lwp_fd = open_lwp(GC_current_ids[i]);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
357 prstatus_t status;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
358
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
359 if (lwp_fd < 0) ABORT("open_lwp failed");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
360 if (syscall(SYS_ioctl, lwp_fd,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
361 PIOCSTATUS, &status) < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
362 ABORT("PIOCSTATUS failed in restart_all_lwps");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
363 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
364 if (memcmp(status.pr_reg, GC_lwp_registers[i],
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
365 sizeof (prgregset_t)) != 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
366 int j;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
367
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
368 for(j = 0; j < NPRGREG; j++)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
369 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
370 GC_printf3("%i: %x -> %x\n", j,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
371 GC_lwp_registers[i][j],
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
372 status.pr_reg[j]);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
373 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
374 ABORT("Register contents changed");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
375 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
376 if (!status.pr_flags & PR_STOPPED) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
377 ABORT("lwp no longer stopped");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
378 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
379 #ifdef SPARC
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
380 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
381 gwindows_t windows;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
382 if (syscall(SYS_ioctl, lwp_fd,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
383 PIOCGWIN, &windows) < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
384 ABORT("PIOCSTATUS failed in restart_all_lwps");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
385 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
386 if (windows.wbcnt > 0) ABORT("unsaved register windows");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
387 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
388 #endif
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
389 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
390 # endif /* PARANOID */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
391 if (GC_current_ids[i] == me) continue;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
392 if (_lwp_continue(GC_current_ids[i]) < 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
393 ABORT("Failed to restart lwp");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
394 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
395 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
396 if (i >= max_lwps) ABORT("Too many lwps");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
397 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
398
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
399 GC_bool GC_multithreaded = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
400
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
401 void GC_stop_world()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
402 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
403 preempt_off();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
404 if (GC_multithreaded)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
405 stop_all_lwps();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
406 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
407
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
408 void GC_start_world()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
409 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
410 if (GC_multithreaded)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
411 restart_all_lwps();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
412 preempt_on();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
413 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
414
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
415 void GC_thr_init(void);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
416
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
417 GC_bool GC_thr_initialized = FALSE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
418
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
419 size_t GC_min_stack_sz;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
420
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
421
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
422 /*
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
423 * stack_head is stored at the top of free stacks
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
424 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
425 struct stack_head {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
426 struct stack_head *next;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
427 ptr_t base;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
428 thread_t owner;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
429 };
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
430
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
431 # define N_FREE_LISTS 25
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
432 struct stack_head *GC_stack_free_lists[N_FREE_LISTS] = { 0 };
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
433 /* GC_stack_free_lists[i] is free list for stacks of */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
434 /* size GC_min_stack_sz*2**i. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
435 /* Free lists are linked through stack_head stored */ /* at top of stack. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
436
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
437 /* Return a stack of size at least *stack_size. *stack_size is */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
438 /* replaced by the actual stack size. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
439 /* Caller holds allocation lock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
440 ptr_t GC_stack_alloc(size_t * stack_size)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
441 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
442 register size_t requested_sz = *stack_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
443 register size_t search_sz = GC_min_stack_sz;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
444 register int index = 0; /* = log2(search_sz/GC_min_stack_sz) */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
445 register ptr_t base;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
446 register struct stack_head *result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
447
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
448 while (search_sz < requested_sz) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
449 search_sz *= 2;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
450 index++;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
451 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
452 if ((result = GC_stack_free_lists[index]) == 0
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
453 && (result = GC_stack_free_lists[index+1]) != 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
454 /* Try next size up. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
455 search_sz *= 2; index++;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
456 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
457 if (result != 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
458 base = GC_stack_free_lists[index]->base;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
459 GC_stack_free_lists[index] = GC_stack_free_lists[index]->next;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
460 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
461 #ifdef MMAP_STACKS
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
462 base = (ptr_t)mmap(0, search_sz + GC_page_size,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
463 PROT_READ|PROT_WRITE, MAP_PRIVATE |MAP_NORESERVE,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
464 GC_zfd, 0);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
465 if (base == (ptr_t)-1)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
466 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
467 *stack_size = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
468 return NULL;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
469 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
470
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
471 mprotect(base, GC_page_size, PROT_NONE);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
472 /* Should this use divHBLKSZ(search_sz + GC_page_size) ? -- cf */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
473 GC_is_fresh((struct hblk *)base, divHBLKSZ(search_sz));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
474 base += GC_page_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
475
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
476 #else
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
477 base = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_size);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
478 if (base == NULL)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
479 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
480 *stack_size = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
481 return NULL;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
482 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
483
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
484 base = (ptr_t)(((word)base + GC_page_size) & ~(GC_page_size - 1));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
485 /* Protect hottest page to detect overflow. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
486 # ifdef SOLARIS23_MPROTECT_BUG_FIXED
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
487 mprotect(base, GC_page_size, PROT_NONE);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
488 # endif
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
489 GC_is_fresh((struct hblk *)base, divHBLKSZ(search_sz));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
490
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
491 base += GC_page_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
492 #endif
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
493 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
494 *stack_size = search_sz;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
495 return(base);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
496 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
497
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
498 /* Caller holds allocationlock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
499 void GC_stack_free(ptr_t stack, size_t size)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
500 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
501 register int index = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
502 register size_t search_sz = GC_min_stack_sz;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
503 register struct stack_head *head;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
504
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
505 #ifdef MMAP_STACKS
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
506 /* Zero pointers */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
507 mmap(stack, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_NORESERVE|MAP_FIXED,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
508 GC_zfd, 0);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
509 #endif
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
510 while (search_sz < size) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
511 search_sz *= 2;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
512 index++;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
513 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
514 if (search_sz != size) ABORT("Bad stack size");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
515
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
516 head = (struct stack_head *)(stack + search_sz - sizeof(struct stack_head));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
517 head->next = GC_stack_free_lists[index];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
518 head->base = stack;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
519 GC_stack_free_lists[index] = head;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
520 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
521
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
522 void GC_my_stack_limits();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
523
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
524 /* Notify virtual dirty bit implementation that known empty parts of */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
525 /* stacks do not contain useful data. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
526 /* Caller holds allocation lock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
527 void GC_old_stacks_are_fresh()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
528 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
529 /* No point in doing this for MMAP stacks - and pointers are zero'd out */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
530 /* by the mmap in GC_stack_free */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
531 #ifndef MMAP_STACKS
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
532 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
533 register struct stack_head *s;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
534 register ptr_t p;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
535 register size_t sz;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
536 register struct hblk * h;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
537 int dummy;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
538
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
539 for (i = 0, sz= GC_min_stack_sz; i < N_FREE_LISTS;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
540 i++, sz *= 2) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
541 for (s = GC_stack_free_lists[i]; s != 0; s = s->next) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
542 p = s->base;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
543 h = (struct hblk *)(((word)p + HBLKSIZE-1) & ~(HBLKSIZE-1));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
544 if ((ptr_t)h == p) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
545 GC_is_fresh((struct hblk *)p, divHBLKSZ(sz));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
546 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
547 GC_is_fresh((struct hblk *)p, divHBLKSZ(sz) - 1);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
548 BZERO(p, (ptr_t)h - p);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
549 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
550 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
551 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
552 #endif /* MMAP_STACKS */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
553 GC_my_stack_limits();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
554 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
555
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
556 /* The set of all known threads. We intercept thread creation and */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
557 /* joins. We never actually create detached threads. We allocate all */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
558 /* new thread stacks ourselves. These allow us to maintain this */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
559 /* data structure. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
560
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
561 # define THREAD_TABLE_SZ 128 /* Must be power of 2 */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
562 volatile GC_thread GC_threads[THREAD_TABLE_SZ];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
563
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
564 void GC_push_thread_structures GC_PROTO((void))
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
565 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
566 GC_push_all((ptr_t)(GC_threads), (ptr_t)(GC_threads)+sizeof(GC_threads));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
567 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
568
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
569 /* Add a thread to GC_threads. We assume it wasn't already there. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
570 /* Caller holds allocation lock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
571 GC_thread GC_new_thread(thread_t id)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
572 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
573 int hv = ((word)id) % THREAD_TABLE_SZ;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
574 GC_thread result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
575 static struct GC_Thread_Rep first_thread;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
576 static GC_bool first_thread_used = FALSE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
577
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
578 if (!first_thread_used) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
579 result = &first_thread;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
580 first_thread_used = TRUE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
581 /* Dont acquire allocation lock, since we may already hold it. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
582 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
583 result = (struct GC_Thread_Rep *)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
584 GC_INTERNAL_MALLOC(sizeof(struct GC_Thread_Rep), NORMAL);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
585 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
586 if (result == 0) return(0);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
587 result -> id = id;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
588 result -> next = GC_threads[hv];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
589 GC_threads[hv] = result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
590 /* result -> finished = 0; */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
591 (void) cond_init(&(result->join_cv), USYNC_THREAD, 0);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
592 return(result);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
593 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
594
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
595 /* Delete a thread from GC_threads. We assume it is there. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
596 /* (The code intentionally traps if it wasn't.) */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
597 /* Caller holds allocation lock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
598 void GC_delete_thread(thread_t id)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
599 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
600 int hv = ((word)id) % THREAD_TABLE_SZ;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
601 register GC_thread p = GC_threads[hv];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
602 register GC_thread prev = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
603
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
604 while (p -> id != id) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
605 prev = p;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
606 p = p -> next;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
607 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
608 if (prev == 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
609 GC_threads[hv] = p -> next;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
610 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
611 prev -> next = p -> next;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
612 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
613 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
614
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
615 /* Return the GC_thread correpsonding to a given thread_t. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
616 /* Returns 0 if it's not there. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
617 /* Caller holds allocation lock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
618 GC_thread GC_lookup_thread(thread_t id)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
619 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
620 int hv = ((word)id) % THREAD_TABLE_SZ;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
621 register GC_thread p = GC_threads[hv];
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
622
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
623 while (p != 0 && p -> id != id) p = p -> next;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
624 return(p);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
625 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
626
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
627 /* Solaris 2/Intel uses an initial stack size limit slightly bigger than the
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
628 SPARC default of 8 MB. Account for this to warn only if the user has
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
629 raised the limit beyond the default.
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
630
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
631 This is identical to DFLSSIZ defined in <sys/vm_machparam.h>. This file
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
632 is installed in /usr/platform/`uname -m`/include, which is not in the
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
633 default include directory list, so copy the definition here. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
634 #ifdef I386
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
635 # define MAX_ORIG_STACK_SIZE (8 * 1024 * 1024 + ((USRSTACK) & 0x3FFFFF))
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
636 #else
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
637 # define MAX_ORIG_STACK_SIZE (8 * 1024 * 1024)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
638 #endif
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
639
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
640 word GC_get_orig_stack_size() {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
641 struct rlimit rl;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
642 static int warned = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
643 int result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
644
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
645 if (getrlimit(RLIMIT_STACK, &rl) != 0) ABORT("getrlimit failed");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
646 result = (word)rl.rlim_cur & ~(HBLKSIZE-1);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
647 if (result > MAX_ORIG_STACK_SIZE) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
648 if (!warned) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
649 WARN("Large stack limit(%ld): only scanning 8 MB\n", result);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
650 warned = 1;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
651 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
652 result = MAX_ORIG_STACK_SIZE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
653 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
654 return result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
655 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
656
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
657 /* Notify dirty bit implementation of unused parts of my stack. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
658 /* Caller holds allocation lock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
659 void GC_my_stack_limits()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
660 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
661 int dummy;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
662 register ptr_t hottest = (ptr_t)((word)(&dummy) & ~(HBLKSIZE-1));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
663 register GC_thread me = GC_lookup_thread(thr_self());
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
664 register size_t stack_size = me -> stack_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
665 register ptr_t stack;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
666
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
667 if (stack_size == 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
668 /* original thread */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
669 /* Empirically, what should be the stack page with lowest */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
670 /* address is actually inaccessible. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
671 stack_size = GC_get_orig_stack_size() - GC_page_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
672 stack = GC_stackbottom - stack_size + GC_page_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
673 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
674 stack = me -> stack;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
675 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
676 if (stack > hottest || stack + stack_size < hottest) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
677 ABORT("sp out of bounds");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
678 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
679 GC_is_fresh((struct hblk *)stack, divHBLKSZ(hottest - stack));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
680 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
681
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
682
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
683 /* We hold allocation lock. Should do exactly the right thing if the */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
684 /* world is stopped. Should not fail if it isn't. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
685 void GC_push_all_stacks()
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
686 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
687 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
688 register GC_thread p;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
689 register ptr_t sp = GC_approx_sp();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
690 register ptr_t bottom, top;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
691 struct rlimit rl;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
692
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
693 # define PUSH(bottom,top) \
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
694 if (GC_dirty_maintained) { \
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
695 GC_push_selected((bottom), (top), GC_page_was_ever_dirty, \
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
696 GC_push_all_stack); \
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
697 } else { \
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
698 GC_push_all_stack((bottom), (top)); \
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
699 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
700 GC_push_all_stack((ptr_t)GC_lwp_registers,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
701 (ptr_t)GC_lwp_registers
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
702 + max_lwps * sizeof(GC_lwp_registers[0]));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
703 for (i = 0; i < THREAD_TABLE_SZ; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
704 for (p = GC_threads[i]; p != 0; p = p -> next) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
705 if (p -> stack_size != 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
706 bottom = p -> stack;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
707 top = p -> stack + p -> stack_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
708 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
709 /* The original stack. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
710 bottom = GC_stackbottom - GC_get_orig_stack_size() + GC_page_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
711 top = GC_stackbottom;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
712 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
713 if ((word)sp > (word)bottom && (word)sp < (word)top) bottom = sp;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
714 PUSH(bottom, top);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
715 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
716 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
717 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
718
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
719
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
720 int GC_is_thread_stack(ptr_t addr)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
721 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
722 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
723 register GC_thread p;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
724 register ptr_t bottom, top;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
725
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
726 for (i = 0; i < THREAD_TABLE_SZ; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
727 for (p = GC_threads[i]; p != 0; p = p -> next) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
728 if (p -> stack_size != 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
729 if (p -> stack <= addr &&
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
730 addr < p -> stack + p -> stack_size)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
731 return 1;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
732 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
733 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
734 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
735 return 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
736 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
737
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
738 /* The only thread that ever really performs a thr_join. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
739 void * GC_thr_daemon(void * dummy)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
740 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
741 void *status;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
742 thread_t departed;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
743 register GC_thread t;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
744 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
745 register int result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
746
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
747 for(;;) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
748 start:
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
749 result = thr_join((thread_t)0, &departed, &status);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
750 LOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
751 if (result != 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
752 /* No more threads; wait for create. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
753 for (i = 0; i < THREAD_TABLE_SZ; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
754 for (t = GC_threads[i]; t != 0; t = t -> next) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
755 if (!(t -> flags & (DETACHED | FINISHED))) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
756 UNLOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
757 goto start; /* Thread started just before we */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
758 /* acquired the lock. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
759 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
760 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
761 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
762 cond_wait(&GC_create_cv, &GC_allocate_ml);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
763 UNLOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
764 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
765 t = GC_lookup_thread(departed);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
766 GC_multithreaded--;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
767 if (!(t -> flags & CLIENT_OWNS_STACK)) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
768 GC_stack_free(t -> stack, t -> stack_size);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
769 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
770 if (t -> flags & DETACHED) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
771 GC_delete_thread(departed);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
772 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
773 t -> status = status;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
774 t -> flags |= FINISHED;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
775 cond_signal(&(t -> join_cv));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
776 cond_broadcast(&GC_prom_join_cv);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
777 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
778 UNLOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
779 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
780 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
781 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
782
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
783 /* We hold the allocation lock, or caller ensures that 2 instances */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
784 /* cannot be invoked concurrently. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
785 void GC_thr_init(void)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
786 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
787 GC_thread t;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
788 thread_t tid;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
789
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
790 if (GC_thr_initialized)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
791 return;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
792 GC_thr_initialized = TRUE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
793 GC_min_stack_sz = ((thr_min_stack() + 32*1024 + HBLKSIZE-1)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
794 & ~(HBLKSIZE - 1));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
795 #ifdef MMAP_STACKS
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
796 GC_zfd = open("/dev/zero", O_RDONLY);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
797 if (GC_zfd == -1)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
798 ABORT("Can't open /dev/zero");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
799 #endif /* MMAP_STACKS */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
800 cond_init(&GC_prom_join_cv, USYNC_THREAD, 0);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
801 cond_init(&GC_create_cv, USYNC_THREAD, 0);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
802 /* Add the initial thread, so we can stop it. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
803 t = GC_new_thread(thr_self());
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
804 t -> stack_size = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
805 t -> flags = DETACHED | CLIENT_OWNS_STACK;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
806 if (thr_create(0 /* stack */, 0 /* stack_size */, GC_thr_daemon,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
807 0 /* arg */, THR_DETACHED | THR_DAEMON,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
808 &tid /* thread_id */) != 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
809 ABORT("Cant fork daemon");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
810 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
811 thr_setprio(tid, 126);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
812 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
813
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
814 /* We acquire the allocation lock to prevent races with */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
815 /* stopping/starting world. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
816 /* This is no more correct than the underlying Solaris 2.X */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
817 /* implementation. Under 2.3 THIS IS BROKEN. */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
818 int GC_thr_suspend(thread_t target_thread)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
819 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
820 GC_thread t;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
821 int result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
822
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
823 LOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
824 result = thr_suspend(target_thread);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
825 if (result == 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
826 t = GC_lookup_thread(target_thread);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
827 if (t == 0) ABORT("thread unknown to GC");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
828 t -> flags |= SUSPNDED;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
829 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
830 UNLOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
831 return(result);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
832 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
833
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
834 int GC_thr_continue(thread_t target_thread)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
835 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
836 GC_thread t;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
837 int result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
838
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
839 LOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
840 result = thr_continue(target_thread);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
841 if (result == 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
842 t = GC_lookup_thread(target_thread);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
843 if (t == 0) ABORT("thread unknown to GC");
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
844 t -> flags &= ~SUSPNDED;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
845 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
846 UNLOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
847 return(result);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
848 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
849
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
850 int GC_thr_join(thread_t wait_for, thread_t *departed, void **status)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
851 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
852 register GC_thread t;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
853 int result = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
854
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
855 LOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
856 if (wait_for == 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
857 register int i;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
858 register GC_bool thread_exists;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
859
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
860 for (;;) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
861 thread_exists = FALSE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
862 for (i = 0; i < THREAD_TABLE_SZ; i++) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
863 for (t = GC_threads[i]; t != 0; t = t -> next) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
864 if (!(t -> flags & DETACHED)) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
865 if (t -> flags & FINISHED) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
866 goto found;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
867 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
868 thread_exists = TRUE;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
869 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
870 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
871 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
872 if (!thread_exists) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
873 result = ESRCH;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
874 goto out;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
875 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
876 cond_wait(&GC_prom_join_cv, &GC_allocate_ml);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
877 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
878 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
879 t = GC_lookup_thread(wait_for);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
880 if (t == 0 || t -> flags & DETACHED) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
881 result = ESRCH;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
882 goto out;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
883 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
884 if (wait_for == thr_self()) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
885 result = EDEADLK;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
886 goto out;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
887 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
888 while (!(t -> flags & FINISHED)) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
889 cond_wait(&(t -> join_cv), &GC_allocate_ml);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
890 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
891
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
892 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
893 found:
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
894 if (status) *status = t -> status;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
895 if (departed) *departed = t -> id;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
896 cond_destroy(&(t -> join_cv));
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
897 GC_delete_thread(t -> id);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
898 out:
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
899 UNLOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
900 return(result);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
901 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
902
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
903
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
904 int
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
905 GC_thr_create(void *stack_base, size_t stack_size,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
906 void *(*start_routine)(void *), void *arg, long flags,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
907 thread_t *new_thread)
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
908 {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
909 int result;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
910 GC_thread t;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
911 thread_t my_new_thread;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
912 word my_flags = 0;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
913 void * stack = stack_base;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
914
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
915 LOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
916 if (!GC_is_initialized) GC_init_inner();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
917 GC_multithreaded++;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
918 if (stack == 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
919 if (stack_size == 0) stack_size = 1024*1024;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
920 stack = (void *)GC_stack_alloc(&stack_size);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
921 if (stack == 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
922 GC_multithreaded--;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
923 UNLOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
924 return(ENOMEM);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
925 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
926 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
927 my_flags |= CLIENT_OWNS_STACK;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
928 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
929 if (flags & THR_DETACHED) my_flags |= DETACHED;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
930 if (flags & THR_SUSPENDED) my_flags |= SUSPNDED;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
931 result = thr_create(stack, stack_size, start_routine,
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
932 arg, flags & ~THR_DETACHED, &my_new_thread);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
933 if (result == 0) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
934 t = GC_new_thread(my_new_thread);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
935 t -> flags = my_flags;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
936 if (!(my_flags & DETACHED)) cond_init(&(t -> join_cv), USYNC_THREAD, 0);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
937 t -> stack = stack;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
938 t -> stack_size = stack_size;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
939 if (new_thread != 0) *new_thread = my_new_thread;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
940 cond_signal(&GC_create_cv);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
941 } else {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
942 GC_multithreaded--;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
943 if (!(my_flags & CLIENT_OWNS_STACK)) {
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
944 GC_stack_free(stack, stack_size);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
945 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
946 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
947 UNLOCK();
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
948 return(result);
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
949 }
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
950
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
951 # else /* !GC_SOLARIS_THREADS */
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
952
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
953 #ifndef LINT
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
954 int GC_no_sunOS_threads;
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
955 #endif
5de98dce4bd1 *** empty log message ***
Dave Love <fx@gnu.org>
parents:
diff changeset
956 #endif