Commit | Line | Data |
---|---|---|
7bfd3b9e JB |
1 | /* classes: h_files */ |
2 | ||
0527e687 DH |
3 | #ifndef SCM_THREADS_H |
4 | #define SCM_THREADS_H | |
7bfd3b9e | 5 | |
f7eca35d | 6 | /* Copyright (C) 1996,1997,1998,2000,2001, 2002 Free Software Foundation, Inc. |
0527e687 | 7 | * |
7bfd3b9e JB |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2, or (at your option) | |
11 | * any later version. | |
0527e687 | 12 | * |
7bfd3b9e JB |
13 | * This program is distributed in the hope that it will be useful, |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
0527e687 | 17 | * |
7bfd3b9e JB |
18 | * You should have received a copy of the GNU General Public License |
19 | * along with this software; see the file COPYING. If not, write to | |
82892bed JB |
20 | * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
21 | * Boston, MA 02111-1307 USA | |
7bfd3b9e JB |
22 | * |
23 | * As a special exception, the Free Software Foundation gives permission | |
24 | * for additional uses of the text contained in its release of GUILE. | |
25 | * | |
26 | * The exception is that, if you link the GUILE library with other files | |
27 | * to produce an executable, this does not by itself cause the | |
28 | * resulting executable to be covered by the GNU General Public License. | |
29 | * Your use of that executable is in no way restricted on account of | |
30 | * linking the GUILE library code into it. | |
31 | * | |
32 | * This exception does not however invalidate any other reasons why | |
33 | * the executable file might be covered by the GNU General Public License. | |
34 | * | |
35 | * This exception applies only to the code released by the | |
36 | * Free Software Foundation under the name GUILE. If you copy | |
37 | * code from other Free Software Foundation releases into a copy of | |
38 | * GUILE, as the General Public License permits, the exception does | |
39 | * not apply to the code that you add in this way. To avoid misleading | |
40 | * anyone as to the status of such modified files, you must delete | |
41 | * this exception notice from them. | |
42 | * | |
43 | * If you write modifications of your own for GUILE, it is your choice | |
44 | * whether to permit this exception to apply to your modifications. | |
82892bed | 45 | * If you do not wish that, delete this exception notice. */ |
d3a6bc94 | 46 | |
7bfd3b9e JB |
47 | \f |
48 | ||
49 | #include "libguile/__scm.h" | |
50 | #include "libguile/procs.h" | |
1651c824 | 51 | #include "libguile/throw.h" |
f7eca35d | 52 | #include "libguile/root.h" |
d823b11b | 53 | #include "libguile/iselect.h" |
29717c89 | 54 | #include "libguile/threads-plugin.h" |
b2728432 DH |
55 | \f |
56 | ||
7bfd3b9e | 57 | /* smob tags for the thread datatypes */ |
33b001fd MV |
58 | SCM_API scm_t_bits scm_tc16_thread; |
59 | SCM_API scm_t_bits scm_tc16_mutex; | |
9bc4701c | 60 | SCM_API scm_t_bits scm_tc16_fair_mutex; |
33b001fd | 61 | SCM_API scm_t_bits scm_tc16_condvar; |
9bc4701c | 62 | SCM_API scm_t_bits scm_tc16_fair_condvar; |
7bfd3b9e | 63 | |
9bc4701c MD |
64 | #define SCM_THREADP(x) SCM_TYP16_PREDICATE (scm_tc16_thread, x) |
65 | #define SCM_THREAD_DATA(x) ((scm_thread *) SCM_CELL_WORD_1 (x)) | |
7bfd3b9e | 66 | |
9bc4701c MD |
67 | #define SCM_MUTEXP(x) SCM_TYP16_PREDICATE (scm_tc16_mutex, x) |
68 | #define SCM_FAIR_MUTEX_P(x) SCM_TYP16_PREDICATE (scm_tc16_fair_mutex, x) | |
69 | #define SCM_MUTEX_DATA(x) ((void *) SCM_CELL_WORD_1 (x)) | |
7bfd3b9e | 70 | |
9bc4701c MD |
71 | #define SCM_CONDVARP(x) SCM_TYP16_PREDICATE (scm_tc16_condvar, x) |
72 | #define SCM_FAIR_CONDVAR_P(x) SCM_TYP16_PREDICATE (scm_tc16_fair_condvar, x) | |
73 | #define SCM_CONDVAR_DATA(x) ((void *) SCM_CELL_WORD_1 (x)) | |
7bfd3b9e | 74 | |
d823b11b MV |
75 | #define SCM_VALIDATE_THREAD(pos, a) \ |
76 | SCM_MAKE_VALIDATE_MSG (pos, a, THREADP, "thread") | |
77 | ||
78 | #define SCM_VALIDATE_MUTEX(pos, a) \ | |
9bc4701c MD |
79 | SCM_ASSERT_TYPE (SCM_MUTEXP (a) || SCM_FAIR_MUTEX_P (a), \ |
80 | a, pos, FUNC_NAME, "mutex"); | |
d823b11b MV |
81 | |
82 | #define SCM_VALIDATE_CONDVAR(pos, a) \ | |
9bc4701c MD |
83 | SCM_ASSERT_TYPE (SCM_CONDVARP (a) || SCM_FAIR_CONDVAR_P (a), \ |
84 | a, pos, FUNC_NAME, "condition variable"); | |
d823b11b | 85 | |
28d52ebb MD |
86 | #define SCM_VALIDATE_FUTURE(pos, obj) \ |
87 | SCM_ASSERT_TYPE (SCM_TYP16_PREDICATE (scm_tc16_future, obj), \ | |
88 | obj, pos, FUNC_NAME, "future"); | |
89 | #define SCM_F_FUTURE_COMPUTED (1L << 16) | |
90 | #define SCM_FUTURE_COMPUTED_P(future) \ | |
91 | (SCM_F_FUTURE_COMPUTED & SCM_CELL_WORD_0 (future)) | |
92 | #define SCM_SET_FUTURE_COMPUTED(future) \ | |
93 | SCM_SET_CELL_WORD_0 (future, scm_tc16_future | SCM_F_FUTURE_COMPUTED) | |
94 | #define SCM_FUTURE_MUTEX(future) \ | |
95 | ((scm_t_rec_mutex *) SCM_CELL_WORD_2 (future)) | |
96 | #define SCM_FUTURE_DATA SCM_CELL_OBJECT_1 | |
97 | #define SCM_SET_FUTURE_DATA SCM_SET_CELL_OBJECT_1 | |
98 | SCM_API scm_t_bits scm_tc16_future; | |
99 | ||
33b001fd MV |
100 | SCM_API void scm_threads_mark_stacks (void); |
101 | SCM_API void scm_init_threads (SCM_STACKITEM *); | |
5f05c406 | 102 | SCM_API void scm_init_thread_procs (void); |
7bfd3b9e | 103 | |
9bc4701c MD |
104 | /*----------------------------------------------------------------------*/ |
105 | /* Low-level C API */ | |
106 | ||
107 | /* The purpose of this API is seamless, simple and thread package | |
108 | independent interaction with Guile threads from the application. | |
28d52ebb MD |
109 | |
110 | Note that Guile also uses it to implement itself, just like | |
111 | with the rest of the application API. | |
9bc4701c MD |
112 | */ |
113 | ||
114 | /* MDJ 021209 <djurfeldt@nada.kth.se>: | |
115 | The separation of the plugin interface (currently in | |
116 | pthread-threads.h and null-threads.h) and the low-level C API needs | |
117 | to be completed in a sensible way. | |
118 | */ | |
119 | ||
120 | /* Deprecate this name and rename to scm_thread_create? | |
121 | Introduce the other two arguments in pthread_create to prepare for | |
122 | the future? | |
123 | */ | |
33b001fd MV |
124 | SCM_API SCM scm_spawn_thread (scm_t_catch_body body, void *body_data, |
125 | scm_t_catch_handler handler, void *handler_data); | |
df366c26 | 126 | |
9bc4701c MD |
127 | #define scm_thread_join scm_i_plugin_thread_join |
128 | #define scm_thread_detach scm_i_plugin_thread_detach | |
129 | #define scm_thread_self scm_i_plugin_thread_self | |
29717c89 | 130 | #define scm_thread_yield scm_i_plugin_thread_yield |
9bc4701c MD |
131 | |
132 | #define scm_mutex_init scm_i_plugin_mutex_init | |
133 | #define scm_mutex_destroy scm_i_plugin_mutex_destroy | |
134 | SCM_API int scm_mutex_lock (scm_t_mutex *m); | |
135 | #define scm_mutex_trylock scm_i_plugin_mutex_trylock | |
136 | #define scm_mutex_unlock scm_i_plugin_mutex_unlock | |
137 | ||
28d52ebb MD |
138 | /* Guile itself needs recursive mutexes. See for example the |
139 | implentation of scm_force in eval.c. | |
140 | ||
141 | Note that scm_rec_mutex_lock et al can be replaced by direct usage | |
142 | of the corresponding pthread functions if we use the pthread | |
143 | debugging API to access the stack top (in which case there is no | |
144 | longer any need to save the top of the stack before blocking). | |
145 | ||
146 | It's therefore highly motivated to use these calls in situations | |
147 | where Guile or the application needs recursive mutexes. | |
148 | */ | |
149 | #define scm_rec_mutex_init scm_i_plugin_rec_mutex_init | |
150 | #define scm_rec_mutex_destroy scm_i_plugin_rec_mutex_destroy | |
151 | /* It's a safer bet to use the following functions. | |
152 | The future of the _init functions is uncertain. | |
153 | */ | |
154 | SCM_API scm_t_rec_mutex *scm_make_rec_mutex (void); | |
155 | SCM_API void scm_rec_mutex_free (scm_t_rec_mutex *); | |
156 | SCM_API int scm_rec_mutex_lock (scm_t_rec_mutex *m); | |
157 | #define scm_rec_mutex_trylock scm_i_plugin_rec_mutex_trylock | |
158 | #define scm_rec_mutex_unlock scm_i_plugin_rec_mutex_unlock | |
159 | ||
9bc4701c MD |
160 | #define scm_cond_init scm_i_plugin_cond_init |
161 | #define scm_cond_destroy scm_i_plugin_cond_destroy | |
162 | SCM_API int scm_cond_wait (scm_t_cond *c, scm_t_mutex *m); | |
163 | SCM_API int scm_cond_timedwait (scm_t_cond *c, | |
164 | scm_t_mutex *m, | |
165 | const struct timespec *t); | |
166 | #define scm_cond_signal scm_i_plugin_cond_signal | |
167 | #define scm_cond_broadcast scm_i_plugin_cond_broadcast | |
168 | ||
169 | #define scm_key_create scm_i_plugin_key_create | |
170 | #define scm_key_delete scm_i_plugin_key_delete | |
171 | #define scm_setspecific scm_i_plugin_setspecific | |
172 | #define scm_getspecific scm_i_plugin_getspecific | |
173 | ||
174 | #define scm_thread_select scm_internal_select | |
175 | ||
176 | /* The application must scm_leave_guile() before entering any piece of | |
177 | code which can | |
178 | 1. block, or | |
179 | 2. execute for any longer period of time without calling SCM_TICK | |
180 | ||
181 | Note, though, that it is *not* necessary to use these calls | |
182 | together with any call in this API. | |
183 | */ | |
184 | ||
185 | SCM_API void scm_enter_guile (void); | |
186 | SCM_API void scm_leave_guile (void); | |
187 | ||
188 | /* Better versions (although we need the former ones also in order to | |
189 | avoid forcing code restructuring in existing applications): */ | |
190 | /*fixme* Not implemented yet! */ | |
191 | SCM_API void *scm_in_guile (void (*func) (void*), void *data); | |
192 | SCM_API void *scm_outside_guile (void (*func) (void*), void *data); | |
193 | ||
d823b11b | 194 | /* These are versions of the ordinary sleep and usleep functions |
b74f4728 | 195 | that play nicely with the thread system. */ |
33b001fd MV |
196 | SCM_API unsigned long scm_thread_sleep (unsigned long); |
197 | SCM_API unsigned long scm_thread_usleep (unsigned long); | |
b74f4728 | 198 | |
9bc4701c MD |
199 | /* End of low-level C API */ |
200 | /*----------------------------------------------------------------------*/ | |
201 | ||
28d52ebb MD |
202 | extern SCM *scm_loc_sys_thread_handler; |
203 | ||
9bc4701c MD |
204 | typedef struct scm_thread scm_thread; |
205 | ||
206 | SCM_API void scm_i_enter_guile (scm_thread *t); | |
207 | SCM_API scm_thread *scm_i_leave_guile (void); | |
208 | ||
d823b11b MV |
209 | /* Critical sections */ |
210 | ||
9bc4701c MD |
211 | /* This is the generic critical section for places where we are too |
212 | lazy to allocate a specific mutex. */ | |
28d52ebb MD |
213 | extern scm_t_mutex scm_i_critical_section_mutex; |
214 | ||
9bc4701c | 215 | #define SCM_CRITICAL_SECTION_START \ |
28d52ebb | 216 | scm_mutex_lock (&scm_i_critical_section_mutex) |
9bc4701c | 217 | #define SCM_CRITICAL_SECTION_END \ |
28d52ebb | 218 | scm_mutex_unlock (&scm_i_critical_section_mutex) |
d823b11b | 219 | |
9bc4701c | 220 | /* This is the temporary support for the old ALLOW/DEFER ints sections */ |
28d52ebb | 221 | extern scm_t_rec_mutex scm_i_defer_mutex; |
d823b11b | 222 | |
9bc4701c | 223 | extern int scm_i_thread_go_to_sleep; |
d823b11b | 224 | |
9bc4701c MD |
225 | void scm_i_thread_put_to_sleep (void); |
226 | void scm_i_thread_wake_up (void); | |
b0dc3d71 | 227 | void scm_i_thread_invalidate_freelists (void); |
9bc4701c MD |
228 | void scm_i_thread_sleep_for_gc (void); |
229 | void scm_threads_prehistory (void); | |
230 | void scm_threads_init_first_thread (void); | |
d823b11b MV |
231 | |
232 | #define SCM_THREAD_SWITCHING_CODE \ | |
233 | do { \ | |
9bc4701c MD |
234 | if (scm_i_thread_go_to_sleep) \ |
235 | scm_i_thread_sleep_for_gc (); \ | |
d823b11b | 236 | } while (0) |
b74f4728 | 237 | |
6d71500e | 238 | /* The C versions of the Scheme-visible thread functions. */ |
d823b11b | 239 | SCM_API SCM scm_call_with_new_thread (SCM thunk, SCM handler); |
29717c89 | 240 | SCM_API SCM scm_yield (void); |
33b001fd | 241 | SCM_API SCM scm_join_thread (SCM t); |
28d52ebb MD |
242 | SCM_API SCM scm_i_make_future (SCM thunk); |
243 | SCM_API SCM scm_future_ref (SCM future); | |
33b001fd | 244 | SCM_API SCM scm_make_mutex (void); |
9bc4701c | 245 | SCM_API SCM scm_make_fair_mutex (void); |
33b001fd | 246 | SCM_API SCM scm_lock_mutex (SCM m); |
5f05c406 | 247 | SCM_API SCM scm_try_mutex (SCM m); |
33b001fd MV |
248 | SCM_API SCM scm_unlock_mutex (SCM m); |
249 | SCM_API SCM scm_make_condition_variable (void); | |
9bc4701c | 250 | SCM_API SCM scm_make_fair_condition_variable (void); |
33b001fd | 251 | SCM_API SCM scm_wait_condition_variable (SCM cond, SCM mutex); |
5f05c406 MV |
252 | SCM_API SCM scm_timed_wait_condition_variable (SCM cond, SCM mutex, |
253 | SCM abstime); | |
33b001fd | 254 | SCM_API SCM scm_signal_condition_variable (SCM cond); |
5f05c406 | 255 | SCM_API SCM scm_broadcast_condition_variable (SCM cond); |
6d71500e | 256 | |
f7eca35d MV |
257 | SCM_API SCM scm_current_thread (void); |
258 | SCM_API SCM scm_all_threads (void); | |
259 | ||
5f05c406 MV |
260 | SCM_API int scm_c_thread_exited_p (SCM thread); |
261 | SCM_API SCM scm_thread_exited_p (SCM thread); | |
262 | ||
f7eca35d MV |
263 | SCM_API scm_root_state *scm_i_thread_root (SCM thread); |
264 | ||
9bc4701c MD |
265 | #define SCM_CURRENT_THREAD \ |
266 | ((scm_thread *) scm_i_plugin_getspecific (scm_i_thread_key)) | |
267 | extern scm_t_key scm_i_thread_key; | |
268 | ||
269 | /* These macros have confusing names. | |
270 | They really refer to the root state of the running thread. */ | |
271 | #define SCM_THREAD_LOCAL_DATA (scm_i_plugin_getspecific (scm_i_root_state_key)) | |
d823b11b | 272 | #define SCM_SET_THREAD_LOCAL_DATA(x) scm_i_set_thread_data(x) |
9bc4701c MD |
273 | extern scm_t_key scm_i_root_state_key; |
274 | SCM_API void scm_i_set_thread_data (void *); | |
d823b11b | 275 | |
5f05c406 MV |
276 | #ifndef HAVE_STRUCT_TIMESPEC |
277 | /* POSIX.4 structure for a time value. This is like a `struct timeval' but | |
278 | has nanoseconds instead of microseconds. */ | |
279 | struct timespec | |
280 | { | |
281 | long int tv_sec; /* Seconds. */ | |
282 | long int tv_nsec; /* Nanoseconds. */ | |
283 | }; | |
284 | #endif | |
285 | ||
9bc4701c | 286 | #ifdef USE_PTHREAD_THREADS |
d823b11b | 287 | #include "libguile/pthread-threads.h" |
5f05c406 | 288 | #else |
212d33ec | 289 | #include "libguile/null-threads.h" |
7bfd3b9e JB |
290 | #endif |
291 | ||
0527e687 | 292 | #endif /* SCM_THREADS_H */ |
89e00824 ML |
293 | |
294 | /* | |
295 | Local Variables: | |
296 | c-file-style: "gnu" | |
297 | End: | |
298 | */ |