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 | * |
73be1d9e MV |
8 | * This library is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License as published by the Free Software Foundation; either | |
11 | * version 2.1 of the License, or (at your option) any later version. | |
0527e687 | 12 | * |
73be1d9e | 13 | * This library is distributed in the hope that it will be useful, |
7bfd3b9e | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
73be1d9e MV |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Lesser General Public License for more details. | |
0527e687 | 17 | * |
73be1d9e MV |
18 | * You should have received a copy of the GNU Lesser General Public |
19 | * License along with this library; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | */ | |
d3a6bc94 | 22 | |
7bfd3b9e JB |
23 | \f |
24 | ||
25 | #include "libguile/__scm.h" | |
26 | #include "libguile/procs.h" | |
1651c824 | 27 | #include "libguile/throw.h" |
f7eca35d | 28 | #include "libguile/root.h" |
d823b11b | 29 | #include "libguile/iselect.h" |
29717c89 | 30 | #include "libguile/threads-plugin.h" |
b2728432 DH |
31 | \f |
32 | ||
7bfd3b9e | 33 | /* smob tags for the thread datatypes */ |
33b001fd MV |
34 | SCM_API scm_t_bits scm_tc16_thread; |
35 | SCM_API scm_t_bits scm_tc16_mutex; | |
9bc4701c | 36 | SCM_API scm_t_bits scm_tc16_fair_mutex; |
33b001fd | 37 | SCM_API scm_t_bits scm_tc16_condvar; |
9bc4701c | 38 | SCM_API scm_t_bits scm_tc16_fair_condvar; |
7bfd3b9e | 39 | |
f5710d53 MV |
40 | #define SCM_THREADP(x) SCM_SMOB_PREDICATE (scm_tc16_thread, x) |
41 | #define SCM_THREAD_DATA(x) ((scm_thread *) SCM_SMOB_DATA (x)) | |
7bfd3b9e | 42 | |
f5710d53 MV |
43 | #define SCM_MUTEXP(x) SCM_SMOB_PREDICATE (scm_tc16_mutex, x) |
44 | #define SCM_FAIR_MUTEX_P(x) SCM_SMOB_PREDICATE (scm_tc16_fair_mutex, x) | |
45 | #define SCM_MUTEX_DATA(x) ((void *) SCM_SMOB_DATA (x)) | |
7bfd3b9e | 46 | |
f5710d53 MV |
47 | #define SCM_CONDVARP(x) SCM_SMOB_PREDICATE (scm_tc16_condvar, x) |
48 | #define SCM_FAIR_CONDVAR_P(x) SCM_SMOB_PREDICATE (scm_tc16_fair_condvar, x) | |
49 | #define SCM_CONDVAR_DATA(x) ((void *) SCM_SMOB_DATA (x)) | |
7bfd3b9e | 50 | |
d823b11b MV |
51 | #define SCM_VALIDATE_THREAD(pos, a) \ |
52 | SCM_MAKE_VALIDATE_MSG (pos, a, THREADP, "thread") | |
53 | ||
54 | #define SCM_VALIDATE_MUTEX(pos, a) \ | |
9bc4701c MD |
55 | SCM_ASSERT_TYPE (SCM_MUTEXP (a) || SCM_FAIR_MUTEX_P (a), \ |
56 | a, pos, FUNC_NAME, "mutex"); | |
d823b11b MV |
57 | |
58 | #define SCM_VALIDATE_CONDVAR(pos, a) \ | |
9bc4701c MD |
59 | SCM_ASSERT_TYPE (SCM_CONDVARP (a) || SCM_FAIR_CONDVAR_P (a), \ |
60 | a, pos, FUNC_NAME, "condition variable"); | |
d823b11b | 61 | |
33b001fd MV |
62 | SCM_API void scm_threads_mark_stacks (void); |
63 | SCM_API void scm_init_threads (SCM_STACKITEM *); | |
5f05c406 | 64 | SCM_API void scm_init_thread_procs (void); |
7bfd3b9e | 65 | |
fcc5d734 SJ |
66 | #if SCM_USE_PTHREAD_THREADS |
67 | # include "libguile/pthread-threads.h" | |
68 | #else | |
69 | # include "libguile/null-threads.h" | |
70 | #endif | |
71 | ||
9bc4701c MD |
72 | /*----------------------------------------------------------------------*/ |
73 | /* Low-level C API */ | |
74 | ||
75 | /* The purpose of this API is seamless, simple and thread package | |
76 | independent interaction with Guile threads from the application. | |
28d52ebb MD |
77 | |
78 | Note that Guile also uses it to implement itself, just like | |
79 | with the rest of the application API. | |
9bc4701c MD |
80 | */ |
81 | ||
82 | /* MDJ 021209 <djurfeldt@nada.kth.se>: | |
83 | The separation of the plugin interface (currently in | |
84 | pthread-threads.h and null-threads.h) and the low-level C API needs | |
85 | to be completed in a sensible way. | |
86 | */ | |
87 | ||
88 | /* Deprecate this name and rename to scm_thread_create? | |
89 | Introduce the other two arguments in pthread_create to prepare for | |
90 | the future? | |
91 | */ | |
33b001fd MV |
92 | SCM_API SCM scm_spawn_thread (scm_t_catch_body body, void *body_data, |
93 | scm_t_catch_handler handler, void *handler_data); | |
92e64b87 | 94 | SCM_API scm_t_thread scm_c_scm2thread (SCM thread); |
df366c26 | 95 | |
9bc4701c MD |
96 | #define scm_thread_join scm_i_plugin_thread_join |
97 | #define scm_thread_detach scm_i_plugin_thread_detach | |
98 | #define scm_thread_self scm_i_plugin_thread_self | |
29717c89 | 99 | #define scm_thread_yield scm_i_plugin_thread_yield |
9bc4701c MD |
100 | |
101 | #define scm_mutex_init scm_i_plugin_mutex_init | |
102 | #define scm_mutex_destroy scm_i_plugin_mutex_destroy | |
103 | SCM_API int scm_mutex_lock (scm_t_mutex *m); | |
104 | #define scm_mutex_trylock scm_i_plugin_mutex_trylock | |
105 | #define scm_mutex_unlock scm_i_plugin_mutex_unlock | |
106 | ||
28d52ebb MD |
107 | /* Guile itself needs recursive mutexes. See for example the |
108 | implentation of scm_force in eval.c. | |
109 | ||
110 | Note that scm_rec_mutex_lock et al can be replaced by direct usage | |
111 | of the corresponding pthread functions if we use the pthread | |
112 | debugging API to access the stack top (in which case there is no | |
113 | longer any need to save the top of the stack before blocking). | |
114 | ||
115 | It's therefore highly motivated to use these calls in situations | |
116 | where Guile or the application needs recursive mutexes. | |
117 | */ | |
118 | #define scm_rec_mutex_init scm_i_plugin_rec_mutex_init | |
119 | #define scm_rec_mutex_destroy scm_i_plugin_rec_mutex_destroy | |
120 | /* It's a safer bet to use the following functions. | |
121 | The future of the _init functions is uncertain. | |
122 | */ | |
123 | SCM_API scm_t_rec_mutex *scm_make_rec_mutex (void); | |
124 | SCM_API void scm_rec_mutex_free (scm_t_rec_mutex *); | |
125 | SCM_API int scm_rec_mutex_lock (scm_t_rec_mutex *m); | |
126 | #define scm_rec_mutex_trylock scm_i_plugin_rec_mutex_trylock | |
127 | #define scm_rec_mutex_unlock scm_i_plugin_rec_mutex_unlock | |
128 | ||
9bc4701c MD |
129 | #define scm_cond_init scm_i_plugin_cond_init |
130 | #define scm_cond_destroy scm_i_plugin_cond_destroy | |
131 | SCM_API int scm_cond_wait (scm_t_cond *c, scm_t_mutex *m); | |
132 | SCM_API int scm_cond_timedwait (scm_t_cond *c, | |
133 | scm_t_mutex *m, | |
d3d605bb | 134 | const scm_t_timespec *t); |
9bc4701c MD |
135 | #define scm_cond_signal scm_i_plugin_cond_signal |
136 | #define scm_cond_broadcast scm_i_plugin_cond_broadcast | |
137 | ||
138 | #define scm_key_create scm_i_plugin_key_create | |
139 | #define scm_key_delete scm_i_plugin_key_delete | |
fcc5d734 SJ |
140 | SCM_API int scm_setspecific (scm_t_key k, void *s); |
141 | SCM_API void *scm_getspecific (scm_t_key k); | |
9bc4701c MD |
142 | |
143 | #define scm_thread_select scm_internal_select | |
144 | ||
145 | /* The application must scm_leave_guile() before entering any piece of | |
146 | code which can | |
147 | 1. block, or | |
148 | 2. execute for any longer period of time without calling SCM_TICK | |
149 | ||
150 | Note, though, that it is *not* necessary to use these calls | |
151 | together with any call in this API. | |
152 | */ | |
153 | ||
154 | SCM_API void scm_enter_guile (void); | |
155 | SCM_API void scm_leave_guile (void); | |
156 | ||
157 | /* Better versions (although we need the former ones also in order to | |
158 | avoid forcing code restructuring in existing applications): */ | |
159 | /*fixme* Not implemented yet! */ | |
160 | SCM_API void *scm_in_guile (void (*func) (void*), void *data); | |
161 | SCM_API void *scm_outside_guile (void (*func) (void*), void *data); | |
162 | ||
d823b11b | 163 | /* These are versions of the ordinary sleep and usleep functions |
b74f4728 | 164 | that play nicely with the thread system. */ |
33b001fd MV |
165 | SCM_API unsigned long scm_thread_sleep (unsigned long); |
166 | SCM_API unsigned long scm_thread_usleep (unsigned long); | |
b74f4728 | 167 | |
9bc4701c MD |
168 | /* End of low-level C API */ |
169 | /*----------------------------------------------------------------------*/ | |
170 | ||
171 | typedef struct scm_thread scm_thread; | |
172 | ||
173 | SCM_API void scm_i_enter_guile (scm_thread *t); | |
174 | SCM_API scm_thread *scm_i_leave_guile (void); | |
175 | ||
d823b11b MV |
176 | /* Critical sections */ |
177 | ||
9bc4701c MD |
178 | /* This is the generic critical section for places where we are too |
179 | lazy to allocate a specific mutex. */ | |
28d52ebb MD |
180 | extern scm_t_mutex scm_i_critical_section_mutex; |
181 | ||
9bc4701c | 182 | #define SCM_CRITICAL_SECTION_START \ |
28d52ebb | 183 | scm_mutex_lock (&scm_i_critical_section_mutex) |
9bc4701c | 184 | #define SCM_CRITICAL_SECTION_END \ |
28d52ebb | 185 | scm_mutex_unlock (&scm_i_critical_section_mutex) |
d823b11b | 186 | |
9bc4701c | 187 | /* This is the temporary support for the old ALLOW/DEFER ints sections */ |
28d52ebb | 188 | extern scm_t_rec_mutex scm_i_defer_mutex; |
d823b11b | 189 | |
9bc4701c | 190 | extern int scm_i_thread_go_to_sleep; |
d823b11b | 191 | |
9bc4701c MD |
192 | void scm_i_thread_put_to_sleep (void); |
193 | void scm_i_thread_wake_up (void); | |
b0dc3d71 | 194 | void scm_i_thread_invalidate_freelists (void); |
9bc4701c MD |
195 | void scm_i_thread_sleep_for_gc (void); |
196 | void scm_threads_prehistory (void); | |
197 | void scm_threads_init_first_thread (void); | |
d823b11b MV |
198 | |
199 | #define SCM_THREAD_SWITCHING_CODE \ | |
200 | do { \ | |
9bc4701c MD |
201 | if (scm_i_thread_go_to_sleep) \ |
202 | scm_i_thread_sleep_for_gc (); \ | |
d823b11b | 203 | } while (0) |
b74f4728 | 204 | |
756414cf MD |
205 | SCM scm_i_create_thread (scm_t_catch_body body, void *body_data, |
206 | scm_t_catch_handler handler, void *handler_data, | |
207 | SCM protects); | |
208 | ||
6d71500e | 209 | /* The C versions of the Scheme-visible thread functions. */ |
d823b11b | 210 | SCM_API SCM scm_call_with_new_thread (SCM thunk, SCM handler); |
29717c89 | 211 | SCM_API SCM scm_yield (void); |
33b001fd MV |
212 | SCM_API SCM scm_join_thread (SCM t); |
213 | SCM_API SCM scm_make_mutex (void); | |
9bc4701c | 214 | SCM_API SCM scm_make_fair_mutex (void); |
33b001fd | 215 | SCM_API SCM scm_lock_mutex (SCM m); |
5f05c406 | 216 | SCM_API SCM scm_try_mutex (SCM m); |
33b001fd MV |
217 | SCM_API SCM scm_unlock_mutex (SCM m); |
218 | SCM_API SCM scm_make_condition_variable (void); | |
9bc4701c | 219 | SCM_API SCM scm_make_fair_condition_variable (void); |
33b001fd | 220 | SCM_API SCM scm_wait_condition_variable (SCM cond, SCM mutex); |
5f05c406 MV |
221 | SCM_API SCM scm_timed_wait_condition_variable (SCM cond, SCM mutex, |
222 | SCM abstime); | |
33b001fd | 223 | SCM_API SCM scm_signal_condition_variable (SCM cond); |
5f05c406 | 224 | SCM_API SCM scm_broadcast_condition_variable (SCM cond); |
6d71500e | 225 | |
f7eca35d MV |
226 | SCM_API SCM scm_current_thread (void); |
227 | SCM_API SCM scm_all_threads (void); | |
228 | ||
5f05c406 MV |
229 | SCM_API int scm_c_thread_exited_p (SCM thread); |
230 | SCM_API SCM scm_thread_exited_p (SCM thread); | |
231 | ||
f7eca35d MV |
232 | SCM_API scm_root_state *scm_i_thread_root (SCM thread); |
233 | ||
9bc4701c MD |
234 | #define SCM_CURRENT_THREAD \ |
235 | ((scm_thread *) scm_i_plugin_getspecific (scm_i_thread_key)) | |
236 | extern scm_t_key scm_i_thread_key; | |
237 | ||
238 | /* These macros have confusing names. | |
239 | They really refer to the root state of the running thread. */ | |
fcc5d734 | 240 | #define SCM_THREAD_LOCAL_DATA (scm_getspecific (scm_i_root_state_key)) |
d823b11b | 241 | #define SCM_SET_THREAD_LOCAL_DATA(x) scm_i_set_thread_data(x) |
2e945bcc | 242 | SCM_API scm_t_key scm_i_root_state_key; |
9bc4701c | 243 | SCM_API void scm_i_set_thread_data (void *); |
d823b11b | 244 | |
0527e687 | 245 | #endif /* SCM_THREADS_H */ |
89e00824 ML |
246 | |
247 | /* | |
248 | Local Variables: | |
249 | c-file-style: "gnu" | |
250 | End: | |
251 | */ |