Commit | Line | Data |
---|---|---|
7bfd3b9e JB |
1 | /* classes: h_files */ |
2 | ||
0527e687 DH |
3 | #ifndef SCM_THREADS_H |
4 | #define SCM_THREADS_H | |
7bfd3b9e | 5 | |
756414cf | 6 | /* Copyright (C) 1996,1997,1998,2000,2001, 2002, 2003 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 | |
33b001fd MV |
86 | SCM_API void scm_threads_mark_stacks (void); |
87 | SCM_API void scm_init_threads (SCM_STACKITEM *); | |
5f05c406 | 88 | SCM_API void scm_init_thread_procs (void); |
7bfd3b9e | 89 | |
9bc4701c MD |
90 | /*----------------------------------------------------------------------*/ |
91 | /* Low-level C API */ | |
92 | ||
93 | /* The purpose of this API is seamless, simple and thread package | |
94 | independent interaction with Guile threads from the application. | |
28d52ebb MD |
95 | |
96 | Note that Guile also uses it to implement itself, just like | |
97 | with the rest of the application API. | |
9bc4701c MD |
98 | */ |
99 | ||
100 | /* MDJ 021209 <djurfeldt@nada.kth.se>: | |
101 | The separation of the plugin interface (currently in | |
102 | pthread-threads.h and null-threads.h) and the low-level C API needs | |
103 | to be completed in a sensible way. | |
104 | */ | |
105 | ||
106 | /* Deprecate this name and rename to scm_thread_create? | |
107 | Introduce the other two arguments in pthread_create to prepare for | |
108 | the future? | |
109 | */ | |
33b001fd MV |
110 | SCM_API SCM scm_spawn_thread (scm_t_catch_body body, void *body_data, |
111 | scm_t_catch_handler handler, void *handler_data); | |
df366c26 | 112 | |
9bc4701c MD |
113 | #define scm_thread_join scm_i_plugin_thread_join |
114 | #define scm_thread_detach scm_i_plugin_thread_detach | |
115 | #define scm_thread_self scm_i_plugin_thread_self | |
29717c89 | 116 | #define scm_thread_yield scm_i_plugin_thread_yield |
9bc4701c MD |
117 | |
118 | #define scm_mutex_init scm_i_plugin_mutex_init | |
119 | #define scm_mutex_destroy scm_i_plugin_mutex_destroy | |
120 | SCM_API int scm_mutex_lock (scm_t_mutex *m); | |
121 | #define scm_mutex_trylock scm_i_plugin_mutex_trylock | |
122 | #define scm_mutex_unlock scm_i_plugin_mutex_unlock | |
123 | ||
28d52ebb MD |
124 | /* Guile itself needs recursive mutexes. See for example the |
125 | implentation of scm_force in eval.c. | |
126 | ||
127 | Note that scm_rec_mutex_lock et al can be replaced by direct usage | |
128 | of the corresponding pthread functions if we use the pthread | |
129 | debugging API to access the stack top (in which case there is no | |
130 | longer any need to save the top of the stack before blocking). | |
131 | ||
132 | It's therefore highly motivated to use these calls in situations | |
133 | where Guile or the application needs recursive mutexes. | |
134 | */ | |
135 | #define scm_rec_mutex_init scm_i_plugin_rec_mutex_init | |
136 | #define scm_rec_mutex_destroy scm_i_plugin_rec_mutex_destroy | |
137 | /* It's a safer bet to use the following functions. | |
138 | The future of the _init functions is uncertain. | |
139 | */ | |
140 | SCM_API scm_t_rec_mutex *scm_make_rec_mutex (void); | |
141 | SCM_API void scm_rec_mutex_free (scm_t_rec_mutex *); | |
142 | SCM_API int scm_rec_mutex_lock (scm_t_rec_mutex *m); | |
143 | #define scm_rec_mutex_trylock scm_i_plugin_rec_mutex_trylock | |
144 | #define scm_rec_mutex_unlock scm_i_plugin_rec_mutex_unlock | |
145 | ||
9bc4701c MD |
146 | #define scm_cond_init scm_i_plugin_cond_init |
147 | #define scm_cond_destroy scm_i_plugin_cond_destroy | |
148 | SCM_API int scm_cond_wait (scm_t_cond *c, scm_t_mutex *m); | |
149 | SCM_API int scm_cond_timedwait (scm_t_cond *c, | |
150 | scm_t_mutex *m, | |
d3d605bb | 151 | const scm_t_timespec *t); |
9bc4701c MD |
152 | #define scm_cond_signal scm_i_plugin_cond_signal |
153 | #define scm_cond_broadcast scm_i_plugin_cond_broadcast | |
154 | ||
155 | #define scm_key_create scm_i_plugin_key_create | |
156 | #define scm_key_delete scm_i_plugin_key_delete | |
157 | #define scm_setspecific scm_i_plugin_setspecific | |
158 | #define scm_getspecific scm_i_plugin_getspecific | |
159 | ||
160 | #define scm_thread_select scm_internal_select | |
161 | ||
162 | /* The application must scm_leave_guile() before entering any piece of | |
163 | code which can | |
164 | 1. block, or | |
165 | 2. execute for any longer period of time without calling SCM_TICK | |
166 | ||
167 | Note, though, that it is *not* necessary to use these calls | |
168 | together with any call in this API. | |
169 | */ | |
170 | ||
171 | SCM_API void scm_enter_guile (void); | |
172 | SCM_API void scm_leave_guile (void); | |
173 | ||
174 | /* Better versions (although we need the former ones also in order to | |
175 | avoid forcing code restructuring in existing applications): */ | |
176 | /*fixme* Not implemented yet! */ | |
177 | SCM_API void *scm_in_guile (void (*func) (void*), void *data); | |
178 | SCM_API void *scm_outside_guile (void (*func) (void*), void *data); | |
179 | ||
d823b11b | 180 | /* These are versions of the ordinary sleep and usleep functions |
b74f4728 | 181 | that play nicely with the thread system. */ |
33b001fd MV |
182 | SCM_API unsigned long scm_thread_sleep (unsigned long); |
183 | SCM_API unsigned long scm_thread_usleep (unsigned long); | |
b74f4728 | 184 | |
9bc4701c MD |
185 | /* End of low-level C API */ |
186 | /*----------------------------------------------------------------------*/ | |
187 | ||
188 | typedef struct scm_thread scm_thread; | |
189 | ||
190 | SCM_API void scm_i_enter_guile (scm_thread *t); | |
191 | SCM_API scm_thread *scm_i_leave_guile (void); | |
192 | ||
d823b11b MV |
193 | /* Critical sections */ |
194 | ||
9bc4701c MD |
195 | /* This is the generic critical section for places where we are too |
196 | lazy to allocate a specific mutex. */ | |
28d52ebb MD |
197 | extern scm_t_mutex scm_i_critical_section_mutex; |
198 | ||
9bc4701c | 199 | #define SCM_CRITICAL_SECTION_START \ |
28d52ebb | 200 | scm_mutex_lock (&scm_i_critical_section_mutex) |
9bc4701c | 201 | #define SCM_CRITICAL_SECTION_END \ |
28d52ebb | 202 | scm_mutex_unlock (&scm_i_critical_section_mutex) |
d823b11b | 203 | |
9bc4701c | 204 | /* This is the temporary support for the old ALLOW/DEFER ints sections */ |
28d52ebb | 205 | extern scm_t_rec_mutex scm_i_defer_mutex; |
d823b11b | 206 | |
9bc4701c | 207 | extern int scm_i_thread_go_to_sleep; |
d823b11b | 208 | |
9bc4701c MD |
209 | void scm_i_thread_put_to_sleep (void); |
210 | void scm_i_thread_wake_up (void); | |
b0dc3d71 | 211 | void scm_i_thread_invalidate_freelists (void); |
9bc4701c MD |
212 | void scm_i_thread_sleep_for_gc (void); |
213 | void scm_threads_prehistory (void); | |
214 | void scm_threads_init_first_thread (void); | |
d823b11b MV |
215 | |
216 | #define SCM_THREAD_SWITCHING_CODE \ | |
217 | do { \ | |
9bc4701c MD |
218 | if (scm_i_thread_go_to_sleep) \ |
219 | scm_i_thread_sleep_for_gc (); \ | |
d823b11b | 220 | } while (0) |
b74f4728 | 221 | |
756414cf MD |
222 | SCM scm_i_create_thread (scm_t_catch_body body, void *body_data, |
223 | scm_t_catch_handler handler, void *handler_data, | |
224 | SCM protects); | |
225 | ||
6d71500e | 226 | /* The C versions of the Scheme-visible thread functions. */ |
d823b11b | 227 | SCM_API SCM scm_call_with_new_thread (SCM thunk, SCM handler); |
29717c89 | 228 | SCM_API SCM scm_yield (void); |
33b001fd MV |
229 | SCM_API SCM scm_join_thread (SCM t); |
230 | SCM_API SCM scm_make_mutex (void); | |
9bc4701c | 231 | SCM_API SCM scm_make_fair_mutex (void); |
33b001fd | 232 | SCM_API SCM scm_lock_mutex (SCM m); |
5f05c406 | 233 | SCM_API SCM scm_try_mutex (SCM m); |
33b001fd MV |
234 | SCM_API SCM scm_unlock_mutex (SCM m); |
235 | SCM_API SCM scm_make_condition_variable (void); | |
9bc4701c | 236 | SCM_API SCM scm_make_fair_condition_variable (void); |
33b001fd | 237 | SCM_API SCM scm_wait_condition_variable (SCM cond, SCM mutex); |
5f05c406 MV |
238 | SCM_API SCM scm_timed_wait_condition_variable (SCM cond, SCM mutex, |
239 | SCM abstime); | |
33b001fd | 240 | SCM_API SCM scm_signal_condition_variable (SCM cond); |
5f05c406 | 241 | SCM_API SCM scm_broadcast_condition_variable (SCM cond); |
6d71500e | 242 | |
f7eca35d MV |
243 | SCM_API SCM scm_current_thread (void); |
244 | SCM_API SCM scm_all_threads (void); | |
245 | ||
5f05c406 MV |
246 | SCM_API int scm_c_thread_exited_p (SCM thread); |
247 | SCM_API SCM scm_thread_exited_p (SCM thread); | |
248 | ||
f7eca35d MV |
249 | SCM_API scm_root_state *scm_i_thread_root (SCM thread); |
250 | ||
d3d605bb | 251 | #ifdef SCM_USE_PTHREAD_THREADS |
756414cf MD |
252 | #include "libguile/pthread-threads.h" |
253 | #else | |
254 | #include "libguile/null-threads.h" | |
255 | #endif | |
256 | ||
9bc4701c MD |
257 | #define SCM_CURRENT_THREAD \ |
258 | ((scm_thread *) scm_i_plugin_getspecific (scm_i_thread_key)) | |
259 | extern scm_t_key scm_i_thread_key; | |
260 | ||
261 | /* These macros have confusing names. | |
262 | They really refer to the root state of the running thread. */ | |
263 | #define SCM_THREAD_LOCAL_DATA (scm_i_plugin_getspecific (scm_i_root_state_key)) | |
d823b11b | 264 | #define SCM_SET_THREAD_LOCAL_DATA(x) scm_i_set_thread_data(x) |
9bc4701c MD |
265 | extern scm_t_key scm_i_root_state_key; |
266 | SCM_API void scm_i_set_thread_data (void *); | |
d823b11b | 267 | |
0527e687 | 268 | #endif /* SCM_THREADS_H */ |
89e00824 ML |
269 | |
270 | /* | |
271 | Local Variables: | |
272 | c-file-style: "gnu" | |
273 | End: | |
274 | */ |