1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
/*
* Copyright (c) 1994 by Xerox Corporation. All rights reserved.
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
*
* Permission is hereby granted to use or copy this program
* for any purpose, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is granted,
* provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice.
*/
/*
* Support code for Solaris threads. Provides functionality we wish Sun
* had provided. Relies on some information we probably shouldn't rely on.
* Modified by Peter C. for Solaris Posix Threads.
*/
# include "private/gc_priv.h"
# if defined(GC_SOLARIS_PTHREADS)
# include <pthread.h>
# include <thread.h>
# include <signal.h>
# include <fcntl.h>
# include <sys/types.h>
# include <sys/mman.h>
# include <sys/time.h>
# include <sys/resource.h>
# include <sys/stat.h>
# include <sys/syscall.h>
# include <sys/procfs.h>
# include <sys/lwp.h>
# include <sys/reg.h>
# define _CLASSIC_XOPEN_TYPES
# include <unistd.h>
# include <errno.h>
# include "private/solaris_threads.h"
# include <stdio.h>
#undef pthread_join
#undef pthread_create
pthread_cond_t GC_prom_join_cv; /* Broadcast when any thread terminates */
pthread_cond_t GC_create_cv; /* Signalled when a new undetached */
/* thread starts. */
extern GC_bool GC_multithreaded;
/* We use the allocation lock to protect thread-related data structures. */
/* We stop the world using /proc primitives. This makes some */
/* minimal assumptions about the threads implementation. */
/* We don't play by the rules, since the rules make this */
/* impossible (as of Solaris 2.3). Also note that as of */
/* Solaris 2.3 the various thread and lwp suspension */
/* primitives failed to stop threads by the time the request */
/* is completed. */
int GC_pthread_join(pthread_t wait_for, void **status)
{
return GC_thr_join((thread_t)wait_for, NULL, status);
}
int GC_pthread_detach(pthread_t thread)
{
GC_thread t;
LOCK();
t=GC_lookup_thread(thread);
UNLOCK();
if (t) {
LOCK();
t->flags |= DETACHED;
UNLOCK();
return 0;
}
else
return pthread_detach(thread);
}
int
GC_pthread_create(pthread_t *new_thread,
const pthread_attr_t *attr_in,
void * (*thread_execp)(void *), void *arg)
{
int result;
GC_thread t;
pthread_t my_new_thread;
pthread_attr_t attr;
word my_flags = 0;
int flag;
void * stack = 0;
size_t stack_size = 0;
int n;
struct sched_param schedparam;
(void)pthread_attr_init(&attr);
if (attr_in != 0) {
(void)pthread_attr_getstacksize(attr_in, &stack_size);
(void)pthread_attr_getstackaddr(attr_in, &stack);
}
LOCK();
if (!GC_is_initialized) {
GC_init_inner();
}
GC_multithreaded++;
if (stack == 0) {
if (stack_size == 0)
stack_size = 1048576;
/* ^-- 1 MB (this was GC_min_stack_sz, but that
* violates the pthread_create documentation which
* says the default value if none is supplied is
* 1MB) */
else
stack_size += thr_min_stack();
stack = (void *)GC_stack_alloc(&stack_size);
if (stack == 0) {
GC_multithreaded--;
UNLOCK();
errno = ENOMEM;
return -1;
}
} else {
my_flags |= CLIENT_OWNS_STACK;
}
(void)pthread_attr_setstacksize(&attr, stack_size);
(void)pthread_attr_setstackaddr(&attr, stack);
if (attr_in != 0) {
(void)pthread_attr_getscope(attr_in, &n);
(void)pthread_attr_setscope(&attr, n);
(void)pthread_attr_getschedparam(attr_in, &schedparam);
(void)pthread_attr_setschedparam(&attr, &schedparam);
(void)pthread_attr_getschedpolicy(attr_in, &n);
(void)pthread_attr_setschedpolicy(&attr, n);
(void)pthread_attr_getinheritsched(attr_in, &n);
(void)pthread_attr_setinheritsched(&attr, n);
(void)pthread_attr_getdetachstate(attr_in, &flag);
if (flag == PTHREAD_CREATE_DETACHED) {
my_flags |= DETACHED;
}
(void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
}
/*
* thr_create can call malloc(), which if redirected will
* attempt to acquire the allocation lock.
* Unlock here to prevent deadlock.
*/
#if 0
#ifdef I386
UNLOCK();
#endif
#endif
result =
pthread_create(&my_new_thread, &attr, thread_execp, arg);
#if 0
#ifdef I386
LOCK();
#endif
#endif
if (result == 0) {
t = GC_new_thread(my_new_thread);
t -> flags = my_flags;
if (!(my_flags & DETACHED)) cond_init(&(t->join_cv), USYNC_THREAD, 0);
t -> stack = stack;
t -> stack_size = stack_size;
if (new_thread != 0) *new_thread = my_new_thread;
pthread_cond_signal(&GC_create_cv);
} else {
if (!(my_flags & CLIENT_OWNS_STACK)) {
GC_stack_free(stack, stack_size);
}
GC_multithreaded--;
}
UNLOCK();
pthread_attr_destroy(&attr);
return(result);
}
# else
#ifndef LINT
int GC_no_sunOS_pthreads;
#endif
# endif /* GC_SOLARIS_PTHREADS */
|