1 |
/* |
2 |
* HT Editor |
3 |
* systhread.cc |
4 |
* |
5 |
* Copyright (C) 2003 Sebastian Biallas (sb@biallas.net) |
6 |
* Copyright (C) 2004 Francois Revol (revol@free.fr) |
7 |
* |
8 |
* This program is free software; you can redistribute it and/or modify |
9 |
* it under the terms of the GNU General Public License version 2 as |
10 |
* published by the Free Software Foundation. |
11 |
* |
12 |
* This program is distributed in the hope that it will be useful, |
13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 |
* GNU General Public License for more details. |
16 |
* |
17 |
* You should have received a copy of the GNU General Public License |
18 |
* along with this program; if not, write to the Free Software |
19 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 |
*/ |
21 |
|
22 |
#include <cstdlib> |
23 |
#include <OS.h> |
24 |
#include "system/systhread.h" |
25 |
#include <stdio.h> |
26 |
#include "system/types.h" |
27 |
#include "tools/snprintf.h" |
28 |
|
29 |
//#define DEBUG_VERBOSE |
30 |
//#define DEBUG_ASSERTS |
31 |
|
32 |
#ifdef DEBUG_VERBOSE |
33 |
#define PPC_BTH_TRACE(msg...) ht_printf("[BEOS/THREAD] "msg) |
34 |
#else |
35 |
#define PPC_BTH_TRACE(msg...) |
36 |
#endif |
37 |
|
38 |
#ifdef DEBUG_ASSERTS |
39 |
#define ASSERT_SEM(s) assert_sem(s) |
40 |
#define ASSERT_THREAD(t) assert_thread(t) |
41 |
#else |
42 |
#define ASSERT_SEM(s) |
43 |
#define ASSERT_THREAD(t) |
44 |
#endif |
45 |
|
46 |
struct sys_beos_mutex { |
47 |
thread_id thread; |
48 |
sem_id sem; |
49 |
}; |
50 |
|
51 |
struct sys_beos_semaphore { |
52 |
sem_id sem; |
53 |
sem_id mutex; |
54 |
}; |
55 |
|
56 |
void assert_sem(sem_id s) |
57 |
{ |
58 |
int32 cookie = 0; |
59 |
sem_info si; |
60 |
while (get_next_sem_info(0, &cookie, &si) == B_OK) { |
61 |
if (si.sem == s) |
62 |
return; /* it belongs to the team, ok */ |
63 |
} |
64 |
debugger("trying to use a sem we don't own!!!"); |
65 |
} |
66 |
|
67 |
void assert_thread(thread_id t) |
68 |
{ |
69 |
int32 cookie = 0; |
70 |
thread_info ti; |
71 |
while (get_next_thread_info(0, &cookie, &ti) == B_OK) { |
72 |
if (ti.thread == t) |
73 |
return; /* it belongs to the team, ok */ |
74 |
} |
75 |
debugger("trying to use a thread we don't own!!!"); |
76 |
} |
77 |
|
78 |
int sys_create_mutex(sys_mutex *m) |
79 |
{ |
80 |
sys_beos_mutex *bm; |
81 |
PPC_BTH_TRACE("%s(%p)\n", __FUNCTION__, m); |
82 |
bm = (sys_beos_mutex *)malloc(sizeof (sys_beos_mutex)); |
83 |
bm->thread = 0; |
84 |
bm->sem = create_sem(1, "a PearPC mutex"); |
85 |
PPC_BTH_TRACE("%s: {T:%d, S:%d})\n", __FUNCTION__, bm->thread, bm->sem); |
86 |
if (bm->sem < B_OK) { |
87 |
free(bm); |
88 |
return bm->sem; |
89 |
} |
90 |
*m = bm; |
91 |
return B_OK; |
92 |
} |
93 |
|
94 |
int sys_create_semaphore(sys_semaphore *s) |
95 |
{ |
96 |
sys_beos_semaphore *bs; |
97 |
status_t err; |
98 |
PPC_BTH_TRACE("%s(%p)\n", __FUNCTION__, s); |
99 |
bs = (sys_beos_semaphore *)malloc(sizeof (sys_beos_semaphore)); |
100 |
if (!bs) |
101 |
return B_NO_MEMORY; |
102 |
err = bs->sem = create_sem(0, "a PearPC sem.sem"); |
103 |
if (err < B_OK) { |
104 |
free(bs); |
105 |
return err; |
106 |
} |
107 |
err = bs->mutex = create_sem(1, "a PearPC sem.mutex"); |
108 |
if (err < B_OK) { |
109 |
delete_sem(bs->sem); |
110 |
free(bs); |
111 |
return err; |
112 |
} |
113 |
PPC_BTH_TRACE("%s: {S:%d, M:%d})\n", __FUNCTION__, bs->sem, bs->mutex); |
114 |
*s = bs; |
115 |
return B_OK; |
116 |
} |
117 |
|
118 |
int sys_create_thread(sys_thread *t, int flags, sys_thread_function start_routine, void *arg) |
119 |
{ |
120 |
thread_id th; |
121 |
status_t err; |
122 |
PPC_BTH_TRACE("%s(%p, 0x%08x, %p, %p)\n", __FUNCTION__, t, flags, start_routine, arg); |
123 |
th = spawn_thread((thread_func)start_routine, "a PearPC thread", B_NORMAL_PRIORITY, arg); |
124 |
if (th < B_OK) |
125 |
return th; |
126 |
err = resume_thread(th); |
127 |
if (!err) |
128 |
*(thread_id *)t = th; |
129 |
PPC_BTH_TRACE("%s: T:%d\n", __FUNCTION__, th); |
130 |
return err; |
131 |
} |
132 |
|
133 |
void sys_destroy_mutex(sys_mutex m) |
134 |
{ |
135 |
sys_beos_mutex *bm = (sys_beos_mutex *)m; |
136 |
PPC_BTH_TRACE("%s(%p {T:%d, S:%d})\n", __FUNCTION__, m, bm->thread, bm->sem); |
137 |
ASSERT_SEM(bm->sem); |
138 |
delete_sem(bm->sem); |
139 |
free(m); |
140 |
} |
141 |
|
142 |
void sys_destroy_semaphore(sys_semaphore s) |
143 |
{ |
144 |
sys_beos_semaphore *bs = (sys_beos_semaphore *)s; |
145 |
PPC_BTH_TRACE("%s(%p {S:%d, M:%d})\n", __FUNCTION__, s, bs->sem, bs->mutex); |
146 |
ASSERT_SEM(bs->sem); |
147 |
delete_sem(bs->sem); |
148 |
ASSERT_SEM(bs->mutex); |
149 |
delete_sem(bs->mutex); |
150 |
free(s); |
151 |
} |
152 |
|
153 |
void sys_destroy_thread(sys_thread t) |
154 |
{ |
155 |
status_t err; |
156 |
thread_id th = (thread_id)t; |
157 |
PPC_BTH_TRACE("%s(T:%d)\n", __FUNCTION__, th); |
158 |
ASSERT_THREAD(th); |
159 |
//kill_thread(th); // just to make sure |
160 |
//wait_for_thread(th, &err); |
161 |
} |
162 |
|
163 |
int sys_lock_mutex(sys_mutex m) |
164 |
{ |
165 |
status_t err; |
166 |
sys_beos_mutex *bm = (sys_beos_mutex *)m; |
167 |
PPC_BTH_TRACE("%s(%p {T:%d, S:%d})\n", __FUNCTION__, m, bm->thread, bm->sem); |
168 |
if (bm->thread == find_thread(NULL)) |
169 |
return B_OK; |
170 |
ASSERT_SEM(bm->sem); |
171 |
err = acquire_sem(bm->sem); |
172 |
if (err) |
173 |
return err; |
174 |
bm->thread = find_thread(NULL); |
175 |
return B_OK; |
176 |
} |
177 |
|
178 |
int sys_trylock_mutex(sys_mutex m) |
179 |
{ |
180 |
status_t err; |
181 |
sys_beos_mutex *bm = (sys_beos_mutex *)m; |
182 |
PPC_BTH_TRACE("%s(%p {T:%d, S:%d})\n", __FUNCTION__, m, bm->thread, bm->sem); |
183 |
if (bm->thread == find_thread(NULL)) |
184 |
return B_OK; |
185 |
ASSERT_SEM(bm->sem); |
186 |
err = acquire_sem_etc(bm->sem, 1, B_RELATIVE_TIMEOUT, 0LL); |
187 |
if (err) |
188 |
return err; |
189 |
bm->thread = find_thread(NULL); |
190 |
return B_OK; |
191 |
} |
192 |
|
193 |
void sys_unlock_mutex(sys_mutex m) |
194 |
{ |
195 |
sys_beos_mutex *bm = (sys_beos_mutex *)m; |
196 |
PPC_BTH_TRACE("%s(%p {T:%d, S:%d})\n", __FUNCTION__, m, bm->thread, bm->sem); |
197 |
bm->thread = 0; |
198 |
ASSERT_SEM(bm->sem); |
199 |
release_sem(bm->sem); |
200 |
} |
201 |
|
202 |
void sys_signal_semaphore(sys_semaphore s) |
203 |
{ |
204 |
sys_beos_semaphore *bs = (sys_beos_semaphore *)s; |
205 |
PPC_BTH_TRACE("%s(%p {S:%d, M:%d})\n", __FUNCTION__, s, bs->sem, bs->mutex); |
206 |
ASSERT_SEM(bs->sem); |
207 |
release_sem(bs->sem); |
208 |
} |
209 |
|
210 |
void sys_signal_all_semaphore(sys_semaphore s) |
211 |
{ |
212 |
int32 count; |
213 |
sys_beos_semaphore *bs = (sys_beos_semaphore *)s; |
214 |
PPC_BTH_TRACE("%s(%p {S:%d, M:%d})\n", __FUNCTION__, s, bs->sem, bs->mutex); |
215 |
ASSERT_SEM(bs->sem); |
216 |
// XXX that's not safe! that should be a kernel atomic op! |
217 |
if (get_sem_count(bs->sem, &count) < B_OK) |
218 |
return; |
219 |
release_sem_etc(bs->sem, count, 0L); |
220 |
} |
221 |
|
222 |
void sys_wait_semaphore(sys_semaphore s) |
223 |
{ |
224 |
sys_beos_semaphore *bs = (sys_beos_semaphore *)s; |
225 |
PPC_BTH_TRACE("%s(%p {S:%d, M:%d})\n", __FUNCTION__, s, bs->sem, bs->mutex); |
226 |
ASSERT_SEM(bs->mutex); |
227 |
ASSERT_SEM(bs->sem); |
228 |
release_sem(bs->mutex); |
229 |
acquire_sem(bs->sem); |
230 |
acquire_sem(bs->mutex); |
231 |
} |
232 |
|
233 |
void sys_wait_semaphore_bounded(sys_semaphore s, int ms) |
234 |
{ |
235 |
sys_beos_semaphore *bs = (sys_beos_semaphore *)s; |
236 |
PPC_BTH_TRACE("%s(%p {S:%d, M:%d}, %dms)\n", __FUNCTION__, s, bs->sem, bs->mutex, ms); |
237 |
ASSERT_SEM(bs->mutex); |
238 |
ASSERT_SEM(bs->sem); |
239 |
release_sem(bs->mutex); |
240 |
acquire_sem_etc(bs->sem, 1, B_RELATIVE_TIMEOUT, (bigtime_t)ms*1000); |
241 |
acquire_sem(bs->mutex); |
242 |
} |
243 |
|
244 |
void sys_lock_semaphore(sys_semaphore s) |
245 |
{ |
246 |
sys_beos_semaphore *bs = (sys_beos_semaphore *)s; |
247 |
PPC_BTH_TRACE("%s(%p {S:%d, M:%d})\n", __FUNCTION__, s, bs->sem, bs->mutex); |
248 |
ASSERT_SEM(bs->mutex); |
249 |
acquire_sem(bs->mutex); |
250 |
} |
251 |
|
252 |
void sys_unlock_semaphore(sys_semaphore s) |
253 |
{ |
254 |
sys_beos_semaphore *bs = (sys_beos_semaphore *)s; |
255 |
PPC_BTH_TRACE("%s(%p {S:%d, M:%d})\n", __FUNCTION__, s, bs->sem, bs->mutex); |
256 |
ASSERT_SEM(bs->mutex); |
257 |
release_sem(bs->mutex); |
258 |
} |
259 |
|
260 |
void sys_exit_thread(void *ret) |
261 |
{ |
262 |
PPC_BTH_TRACE("%s(%p)\n", __FUNCTION__, ret); |
263 |
// in BeOS the exit code is supposed to be a success/errno |
264 |
// code, but that shouldn't matter, it's just an int32. |
265 |
// (as long as it can be casted to a void* (beware 64 bits...)) |
266 |
exit_thread((status_t)ret); |
267 |
} |
268 |
|
269 |
void *sys_join_thread(sys_thread t) |
270 |
{ |
271 |
void *ret = NULL; |
272 |
thread_id th = (thread_id)t; |
273 |
PPC_BTH_TRACE("%s(%d)\n", __FUNCTION__, th); |
274 |
ASSERT_THREAD(th); |
275 |
//kill_thread(th); // just to make sure |
276 |
wait_for_thread(th, (status_t *)&ret); |
277 |
return ret; |
278 |
} |