Commit | Line | Data |
---|---|---|
7bfd3b9e JB |
1 | /* classes: h_files */ |
2 | ||
3 | #ifndef COOP_DEFSH | |
4 | #define COOP_DEFSH | |
5 | ||
d90ca38d | 6 | /* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. |
7bfd3b9e JB |
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 as published by | |
10 | * the Free Software Foundation; either version 2, or (at your option) | |
11 | * any later version. | |
12 | * | |
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. | |
17 | * | |
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. */ |
7bfd3b9e JB |
46 | \f |
47 | ||
48 | # ifdef TIME_WITH_SYS_TIME | |
49 | # include <sys/time.h> | |
50 | # include <time.h> | |
51 | # else | |
52 | # ifdef HAVE_SYS_TIME_H | |
53 | # include <sys/time.h> | |
54 | # else | |
55 | # ifdef HAVE_TIME_H | |
56 | # include <time.h> | |
57 | # endif | |
58 | # endif | |
59 | # endif | |
60 | ||
44e8413c MD |
61 | #ifdef GUILE_ISELECT |
62 | #include "iselect.h" | |
63 | #endif | |
64 | ||
7bfd3b9e JB |
65 | /* This file is included by threads.h, which, in turn, is included by |
66 | libguile.h while coop-threads.h only is included by | |
67 | coop-threads.c. */ | |
68 | ||
69 | /* The coop_t struct must be declared here, since macros in this file | |
70 | refer to the data member. */ | |
71 | ||
72 | /* The notion of a thread is merged with the notion of a queue. | |
73 | Thread stuff: thread status (sp) and stuff to use during | |
74 | (re)initialization. Queue stuff: next thread in the queue | |
75 | (next). */ | |
76 | ||
77 | struct qt_t; | |
78 | ||
79 | typedef struct coop_t { | |
80 | struct qt_t *sp; /* QuickThreads handle. */ | |
81 | void *sto; /* `malloc'-allocated stack. */ | |
82 | ||
83 | struct coop_t *next; /* Next thread in the queue. */ | |
84 | ||
85 | struct coop_t *all_next; | |
86 | struct coop_t *all_prev; | |
87 | ||
88 | void *data; /* Thread local data */ | |
89 | ||
90 | void *base; /* Base of stack */ | |
91 | void *top; /* Top of stack */ | |
92 | ||
93 | void *joining; /* A queue of threads waiting to join this | |
94 | thread */ | |
95 | ||
44e8413c MD |
96 | #ifdef GUILE_ISELECT |
97 | int nfds; | |
98 | SELECT_TYPE *readfds; | |
99 | SELECT_TYPE *writefds; | |
100 | SELECT_TYPE *exceptfds; | |
101 | int timeoutp; | |
102 | struct timeval wakeup_time; /* Time to stop sleeping */ | |
c44bfbc9 | 103 | int _errno; |
44e8413c MD |
104 | int retval; |
105 | #else | |
7bfd3b9e | 106 | time_t wakeup_time; /* Time to stop sleeping */ |
44e8413c | 107 | #endif |
7bfd3b9e JB |
108 | |
109 | } coop_t; | |
110 | ||
c8bf4ecd MD |
111 | /* A queue is a circular list of threads. The queue head is a |
112 | designated list element. If this is a uniprocessor-only | |
113 | implementation we can store the `main' thread in this, but in a | |
114 | multiprocessor there are several `heavy' threads but only one run | |
115 | queue. A fancier implementation might have private run queues, | |
116 | which would lead to a simpler (trivial) implementation */ | |
117 | ||
118 | typedef struct coop_q_t { | |
119 | coop_t t; | |
120 | coop_t *tail; | |
121 | } coop_q_t; | |
122 | ||
123 | /* A Mutex variable is made up of a owner thread, and a queue of threads | |
124 | waiting on the mutex */ | |
125 | ||
126 | typedef struct coop_m { | |
127 | coop_t *owner; /* Mutex owner */ | |
128 | coop_q_t waiting; /* Queue of waiting threads */ | |
129 | } coop_m; | |
130 | ||
131 | typedef coop_m scm_mutex_t; | |
132 | ||
133 | extern int coop_mutex_init (coop_m*); | |
134 | extern int coop_mutex_lock (coop_m*); | |
135 | extern int coop_mutex_unlock (coop_m*); | |
136 | extern int coop_mutex_destroy (coop_m*); | |
137 | #define scm_mutex_init coop_mutex_init | |
138 | #define scm_mutex_lock coop_mutex_lock | |
139 | #define scm_mutex_unlock coop_mutex_unlock | |
140 | #define scm_mutex_destroy coop_mutex_destroy | |
141 | ||
142 | /* A Condition variable is made up of a list of threads waiting on the | |
143 | condition. */ | |
144 | ||
145 | typedef struct coop_c { | |
146 | coop_q_t waiting; /* Queue of waiting threads */ | |
147 | } coop_c; | |
148 | ||
149 | typedef coop_c scm_cond_t; | |
150 | ||
151 | extern int coop_condition_variable_init (coop_c*); | |
152 | extern int coop_condition_variable_wait_mutex (coop_c*, coop_m*); | |
153 | extern int coop_condition_variable_signal (coop_c*); | |
154 | extern int coop_condition_variable_destroy (coop_c*); | |
155 | #define scm_cond_init(cond, attr) coop_condition_variable_init (cond) | |
156 | #define scm_cond_wait coop_condition_variable_wait_mutex | |
157 | #define scm_cond_signal coop_condition_variable_signal | |
158 | #define scm_cond_destroy coop_condition_variable_destroy | |
159 | ||
7bfd3b9e JB |
160 | extern coop_t *coop_global_curr; /* Currently-executing thread. */ |
161 | ||
6d71500e | 162 | extern void coop_join (coop_t *t); |
7bfd3b9e JB |
163 | extern void coop_yield (void); |
164 | ||
165 | extern size_t scm_switch_counter; | |
166 | extern size_t scm_thread_count; | |
167 | ||
168 | \f | |
6d71500e JB |
169 | /* Some iselect functions. */ |
170 | ||
171 | /* I'm not sure whether these three declarations should be here. | |
172 | They're really defined in iselect.c, so you'd think they'd go in | |
173 | iselect.h, but they use coop_t, defined above, which uses things | |
174 | defined in iselect.h. Basically, we're making at best a flailing | |
175 | (and failing) attempt at modularity here, and I don't have time to | |
176 | rethink this at the moment. This code awaits a Hero. --JimB */ | |
177 | extern coop_t *coop_next_runnable_thread (void); | |
178 | extern coop_t *coop_wait_for_runnable_thread_now (struct timeval *); | |
179 | extern coop_t *coop_wait_for_runnable_thread (void); | |
180 | ||
181 | ||
182 | \f | |
7bfd3b9e JB |
183 | |
184 | /* Cooperative threads don't need to have these defined */ | |
185 | ||
186 | #define SCM_THREAD_CRITICAL_SECTION_START | |
187 | #define SCM_THREAD_CRITICAL_SECTION_END | |
188 | ||
189 | \f | |
190 | ||
191 | #define SCM_NO_CRITICAL_SECTION_OWNER 0 | |
192 | #define SCM_THREAD_SWITCH_COUNT 50 /* was 10 /mdj */ | |
193 | ||
194 | \f | |
195 | ||
196 | #define SCM_THREAD_DEFER | |
197 | #define SCM_THREAD_ALLOW | |
198 | #define SCM_THREAD_REDEFER | |
199 | #define SCM_THREAD_REALLOW_1 | |
200 | #define SCM_THREAD_REALLOW_2 | |
201 | ||
202 | #if 0 | |
203 | #define SCM_THREAD_SWITCHING_CODE \ | |
204 | { \ | |
205 | if (scm_thread_count > 1) \ | |
206 | coop_yield(); \ | |
207 | } \ | |
208 | ||
209 | #else | |
210 | #define SCM_THREAD_SWITCHING_CODE \ | |
211 | { \ | |
212 | if (scm_thread_count > 1) \ | |
213 | { \ | |
214 | scm_switch_counter--; \ | |
215 | if (scm_switch_counter == 0) \ | |
216 | { \ | |
217 | scm_switch_counter = SCM_THREAD_SWITCH_COUNT; \ | |
218 | coop_yield(); \ | |
219 | } \ | |
220 | } \ | |
221 | } \ | |
222 | ||
223 | #endif | |
224 | ||
225 | #define SCM_THREAD_LOCAL_DATA (coop_global_curr->data) | |
226 | #define SCM_SET_THREAD_LOCAL_DATA(ptr) (coop_global_curr->data = (ptr)) | |
227 | ||
228 | #endif /* COOP_DEFSH */ |