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" |
b2728432 DH |
54 | \f |
55 | ||
7bfd3b9e | 56 | /* smob tags for the thread datatypes */ |
33b001fd MV |
57 | SCM_API scm_t_bits scm_tc16_thread; |
58 | SCM_API scm_t_bits scm_tc16_mutex; | |
9bc4701c | 59 | SCM_API scm_t_bits scm_tc16_fair_mutex; |
33b001fd | 60 | SCM_API scm_t_bits scm_tc16_condvar; |
9bc4701c | 61 | SCM_API scm_t_bits scm_tc16_fair_condvar; |
7bfd3b9e | 62 | |
9bc4701c MD |
63 | #define SCM_THREADP(x) SCM_TYP16_PREDICATE (scm_tc16_thread, x) |
64 | #define SCM_THREAD_DATA(x) ((scm_thread *) SCM_CELL_WORD_1 (x)) | |
7bfd3b9e | 65 | |
9bc4701c MD |
66 | #define SCM_MUTEXP(x) SCM_TYP16_PREDICATE (scm_tc16_mutex, x) |
67 | #define SCM_FAIR_MUTEX_P(x) SCM_TYP16_PREDICATE (scm_tc16_fair_mutex, x) | |
68 | #define SCM_MUTEX_DATA(x) ((void *) SCM_CELL_WORD_1 (x)) | |
7bfd3b9e | 69 | |
9bc4701c MD |
70 | #define SCM_CONDVARP(x) SCM_TYP16_PREDICATE (scm_tc16_condvar, x) |
71 | #define SCM_FAIR_CONDVAR_P(x) SCM_TYP16_PREDICATE (scm_tc16_fair_condvar, x) | |
72 | #define SCM_CONDVAR_DATA(x) ((void *) SCM_CELL_WORD_1 (x)) | |
7bfd3b9e | 73 | |
d823b11b MV |
74 | #define SCM_VALIDATE_THREAD(pos, a) \ |
75 | SCM_MAKE_VALIDATE_MSG (pos, a, THREADP, "thread") | |
76 | ||
77 | #define SCM_VALIDATE_MUTEX(pos, a) \ | |
9bc4701c MD |
78 | SCM_ASSERT_TYPE (SCM_MUTEXP (a) || SCM_FAIR_MUTEX_P (a), \ |
79 | a, pos, FUNC_NAME, "mutex"); | |
d823b11b MV |
80 | |
81 | #define SCM_VALIDATE_CONDVAR(pos, a) \ | |
9bc4701c MD |
82 | SCM_ASSERT_TYPE (SCM_CONDVARP (a) || SCM_FAIR_CONDVAR_P (a), \ |
83 | a, pos, FUNC_NAME, "condition variable"); | |
d823b11b | 84 | |
28d52ebb MD |
85 | #define SCM_VALIDATE_FUTURE(pos, obj) \ |
86 | SCM_ASSERT_TYPE (SCM_TYP16_PREDICATE (scm_tc16_future, obj), \ | |
87 | obj, pos, FUNC_NAME, "future"); | |
88 | #define SCM_F_FUTURE_COMPUTED (1L << 16) | |
89 | #define SCM_FUTURE_COMPUTED_P(future) \ | |
90 | (SCM_F_FUTURE_COMPUTED & SCM_CELL_WORD_0 (future)) | |
91 | #define SCM_SET_FUTURE_COMPUTED(future) \ | |
92 | SCM_SET_CELL_WORD_0 (future, scm_tc16_future | SCM_F_FUTURE_COMPUTED) | |
93 | #define SCM_FUTURE_MUTEX(future) \ | |
94 | ((scm_t_rec_mutex *) SCM_CELL_WORD_2 (future)) | |
95 | #define SCM_FUTURE_DATA SCM_CELL_OBJECT_1 | |
96 | #define SCM_SET_FUTURE_DATA SCM_SET_CELL_OBJECT_1 | |
97 | SCM_API scm_t_bits scm_tc16_future; | |
98 | ||
33b001fd MV |
99 | SCM_API void scm_threads_mark_stacks (void); |
100 | SCM_API void scm_init_threads (SCM_STACKITEM *); | |
5f05c406 | 101 | SCM_API void scm_init_thread_procs (void); |
7bfd3b9e | 102 | |
9bc4701c MD |
103 | /*----------------------------------------------------------------------*/ |
104 | /* Low-level C API */ | |
105 | ||
106 | /* The purpose of this API is seamless, simple and thread package | |
107 | independent interaction with Guile threads from the application. | |
28d52ebb MD |
108 | |
109 | Note that Guile also uses it to implement itself, just like | |
110 | with the rest of the application API. | |
9bc4701c MD |
111 | */ |
112 | ||
113 | /* MDJ 021209 <djurfeldt@nada.kth.se>: | |
114 | The separation of the plugin interface (currently in | |
115 | pthread-threads.h and null-threads.h) and the low-level C API needs | |
116 | to be completed in a sensible way. | |
117 | */ | |
118 | ||
119 | /* Deprecate this name and rename to scm_thread_create? | |
120 | Introduce the other two arguments in pthread_create to prepare for | |
121 | the future? | |
122 | */ | |
33b001fd MV |
123 | SCM_API SCM scm_spawn_thread (scm_t_catch_body body, void *body_data, |
124 | scm_t_catch_handler handler, void *handler_data); | |
df366c26 | 125 | |
9bc4701c MD |
126 | #define scm_thread_join scm_i_plugin_thread_join |
127 | #define scm_thread_detach scm_i_plugin_thread_detach | |
128 | #define scm_thread_self scm_i_plugin_thread_self | |
129 | ||
130 | #define scm_mutex_init scm_i_plugin_mutex_init | |
131 | #define scm_mutex_destroy scm_i_plugin_mutex_destroy | |
132 | SCM_API int scm_mutex_lock (scm_t_mutex *m); | |
133 | #define scm_mutex_trylock scm_i_plugin_mutex_trylock | |
134 | #define scm_mutex_unlock scm_i_plugin_mutex_unlock | |
135 | ||
28d52ebb MD |
136 | /* Guile itself needs recursive mutexes. See for example the |
137 | implentation of scm_force in eval.c. | |
138 | ||
139 | Note that scm_rec_mutex_lock et al can be replaced by direct usage | |
140 | of the corresponding pthread functions if we use the pthread | |
141 | debugging API to access the stack top (in which case there is no | |
142 | longer any need to save the top of the stack before blocking). | |
143 | ||
144 | It's therefore highly motivated to use these calls in situations | |
145 | where Guile or the application needs recursive mutexes. | |
146 | */ | |
147 | #define scm_rec_mutex_init scm_i_plugin_rec_mutex_init | |
148 | #define scm_rec_mutex_destroy scm_i_plugin_rec_mutex_destroy | |
149 | /* It's a safer bet to use the following functions. | |
150 | The future of the _init functions is uncertain. | |
151 | */ | |
152 | SCM_API scm_t_rec_mutex *scm_make_rec_mutex (void); | |
153 | SCM_API void scm_rec_mutex_free (scm_t_rec_mutex *); | |
154 | SCM_API int scm_rec_mutex_lock (scm_t_rec_mutex *m); | |
155 | #define scm_rec_mutex_trylock scm_i_plugin_rec_mutex_trylock | |
156 | #define scm_rec_mutex_unlock scm_i_plugin_rec_mutex_unlock | |
157 | ||
9bc4701c MD |
158 | #define scm_cond_init scm_i_plugin_cond_init |
159 | #define scm_cond_destroy scm_i_plugin_cond_destroy | |
160 | SCM_API int scm_cond_wait (scm_t_cond *c, scm_t_mutex *m); | |
161 | SCM_API int scm_cond_timedwait (scm_t_cond *c, | |
162 | scm_t_mutex *m, | |
163 | const struct timespec *t); | |
164 | #define scm_cond_signal scm_i_plugin_cond_signal | |
165 | #define scm_cond_broadcast scm_i_plugin_cond_broadcast | |
166 | ||
167 | #define scm_key_create scm_i_plugin_key_create | |
168 | #define scm_key_delete scm_i_plugin_key_delete | |
169 | #define scm_setspecific scm_i_plugin_setspecific | |
170 | #define scm_getspecific scm_i_plugin_getspecific | |
171 | ||
172 | #define scm_thread_select scm_internal_select | |
173 | ||
174 | /* The application must scm_leave_guile() before entering any piece of | |
175 | code which can | |
176 | 1. block, or | |
177 | 2. execute for any longer period of time without calling SCM_TICK | |
178 | ||
179 | Note, though, that it is *not* necessary to use these calls | |
180 | together with any call in this API. | |
181 | */ | |
182 | ||
183 | SCM_API void scm_enter_guile (void); | |
184 | SCM_API void scm_leave_guile (void); | |
185 | ||
186 | /* Better versions (although we need the former ones also in order to | |
187 | avoid forcing code restructuring in existing applications): */ | |
188 | /*fixme* Not implemented yet! */ | |
189 | SCM_API void *scm_in_guile (void (*func) (void*), void *data); | |
190 | SCM_API void *scm_outside_guile (void (*func) (void*), void *data); | |
191 | ||
d823b11b | 192 | /* These are versions of the ordinary sleep and usleep functions |
b74f4728 | 193 | that play nicely with the thread system. */ |
33b001fd MV |
194 | SCM_API unsigned long scm_thread_sleep (unsigned long); |
195 | SCM_API unsigned long scm_thread_usleep (unsigned long); | |
b74f4728 | 196 | |
9bc4701c MD |
197 | /* End of low-level C API */ |
198 | /*----------------------------------------------------------------------*/ | |
199 | ||
28d52ebb MD |
200 | extern SCM *scm_loc_sys_thread_handler; |
201 | ||
9bc4701c MD |
202 | typedef struct scm_thread scm_thread; |
203 | ||
204 | SCM_API void scm_i_enter_guile (scm_thread *t); | |
205 | SCM_API scm_thread *scm_i_leave_guile (void); | |
206 | ||
d823b11b MV |
207 | /* Critical sections */ |
208 | ||
9bc4701c MD |
209 | /* This is the generic critical section for places where we are too |
210 | lazy to allocate a specific mutex. */ | |
28d52ebb MD |
211 | extern scm_t_mutex scm_i_critical_section_mutex; |
212 | ||
9bc4701c | 213 | #define SCM_CRITICAL_SECTION_START \ |
28d52ebb | 214 | scm_mutex_lock (&scm_i_critical_section_mutex) |
9bc4701c | 215 | #define SCM_CRITICAL_SECTION_END \ |
28d52ebb | 216 | scm_mutex_unlock (&scm_i_critical_section_mutex) |
d823b11b | 217 | |
9bc4701c | 218 | /* This is the temporary support for the old ALLOW/DEFER ints sections */ |
28d52ebb | 219 | extern scm_t_rec_mutex scm_i_defer_mutex; |
d823b11b | 220 | |
9bc4701c | 221 | extern int scm_i_thread_go_to_sleep; |
d823b11b | 222 | |
9bc4701c MD |
223 | void scm_i_thread_put_to_sleep (void); |
224 | void scm_i_thread_wake_up (void); | |
b0dc3d71 | 225 | void scm_i_thread_invalidate_freelists (void); |
9bc4701c MD |
226 | void scm_i_thread_sleep_for_gc (void); |
227 | void scm_threads_prehistory (void); | |
228 | void scm_threads_init_first_thread (void); | |
d823b11b MV |
229 | |
230 | #define SCM_THREAD_SWITCHING_CODE \ | |
231 | do { \ | |
9bc4701c MD |
232 | if (scm_i_thread_go_to_sleep) \ |
233 | scm_i_thread_sleep_for_gc (); \ | |
d823b11b | 234 | } while (0) |
b74f4728 | 235 | |
6d71500e | 236 | /* The C versions of the Scheme-visible thread functions. */ |
d823b11b | 237 | SCM_API SCM scm_call_with_new_thread (SCM thunk, SCM handler); |
33b001fd | 238 | SCM_API SCM scm_join_thread (SCM t); |
28d52ebb MD |
239 | SCM_API SCM scm_i_make_future (SCM thunk); |
240 | SCM_API SCM scm_future_ref (SCM future); | |
33b001fd | 241 | SCM_API SCM scm_make_mutex (void); |
9bc4701c | 242 | SCM_API SCM scm_make_fair_mutex (void); |
33b001fd | 243 | SCM_API SCM scm_lock_mutex (SCM m); |
5f05c406 | 244 | SCM_API SCM scm_try_mutex (SCM m); |
33b001fd MV |
245 | SCM_API SCM scm_unlock_mutex (SCM m); |
246 | SCM_API SCM scm_make_condition_variable (void); | |
9bc4701c | 247 | SCM_API SCM scm_make_fair_condition_variable (void); |
33b001fd | 248 | SCM_API SCM scm_wait_condition_variable (SCM cond, SCM mutex); |
5f05c406 MV |
249 | SCM_API SCM scm_timed_wait_condition_variable (SCM cond, SCM mutex, |
250 | SCM abstime); | |
33b001fd | 251 | SCM_API SCM scm_signal_condition_variable (SCM cond); |
5f05c406 | 252 | SCM_API SCM scm_broadcast_condition_variable (SCM cond); |
6d71500e | 253 | |
f7eca35d MV |
254 | SCM_API SCM scm_current_thread (void); |
255 | SCM_API SCM scm_all_threads (void); | |
256 | ||
5f05c406 MV |
257 | SCM_API int scm_c_thread_exited_p (SCM thread); |
258 | SCM_API SCM scm_thread_exited_p (SCM thread); | |
259 | ||
f7eca35d MV |
260 | SCM_API scm_root_state *scm_i_thread_root (SCM thread); |
261 | ||
9bc4701c MD |
262 | #define SCM_CURRENT_THREAD \ |
263 | ((scm_thread *) scm_i_plugin_getspecific (scm_i_thread_key)) | |
264 | extern scm_t_key scm_i_thread_key; | |
265 | ||
266 | /* These macros have confusing names. | |
267 | They really refer to the root state of the running thread. */ | |
268 | #define SCM_THREAD_LOCAL_DATA (scm_i_plugin_getspecific (scm_i_root_state_key)) | |
d823b11b | 269 | #define SCM_SET_THREAD_LOCAL_DATA(x) scm_i_set_thread_data(x) |
9bc4701c MD |
270 | extern scm_t_key scm_i_root_state_key; |
271 | SCM_API void scm_i_set_thread_data (void *); | |
d823b11b | 272 | |
5f05c406 MV |
273 | #ifndef HAVE_STRUCT_TIMESPEC |
274 | /* POSIX.4 structure for a time value. This is like a `struct timeval' but | |
275 | has nanoseconds instead of microseconds. */ | |
276 | struct timespec | |
277 | { | |
278 | long int tv_sec; /* Seconds. */ | |
279 | long int tv_nsec; /* Nanoseconds. */ | |
280 | }; | |
281 | #endif | |
282 | ||
9bc4701c | 283 | #ifdef USE_PTHREAD_THREADS |
d823b11b | 284 | #include "libguile/pthread-threads.h" |
5f05c406 | 285 | #else |
212d33ec | 286 | #include "libguile/null-threads.h" |
7bfd3b9e JB |
287 | #endif |
288 | ||
0527e687 | 289 | #endif /* SCM_THREADS_H */ |
89e00824 ML |
290 | |
291 | /* | |
292 | Local Variables: | |
293 | c-file-style: "gnu" | |
294 | End: | |
295 | */ |