正在显示
1 个修改的文件
包含
511 行增加
和
499 行删除
@@ -47,7 +47,6 @@ | @@ -47,7 +47,6 @@ | ||
47 | #include <errno.h> | 47 | #include <errno.h> |
48 | #include "common.h" | 48 | #include "common.h" |
49 | 49 | ||
50 | - | ||
51 | /* Global data */ | 50 | /* Global data */ |
52 | _st_vp_t _st_this_vp; /* This VP */ | 51 | _st_vp_t _st_this_vp; /* This VP */ |
53 | _st_thread_t *_st_this_thread; /* Current thread */ | 52 | _st_thread_t *_st_this_thread; /* Current thread */ |
@@ -56,575 +55,586 @@ int _st_active_count = 0; /* Active thread count */ | @@ -56,575 +55,586 @@ int _st_active_count = 0; /* Active thread count */ | ||
56 | time_t _st_curr_time = 0; /* Current time as returned by time(2) */ | 55 | time_t _st_curr_time = 0; /* Current time as returned by time(2) */ |
57 | st_utime_t _st_last_tset; /* Last time it was fetched */ | 56 | st_utime_t _st_last_tset; /* Last time it was fetched */ |
58 | 57 | ||
59 | - | ||
60 | int st_poll(struct pollfd *pds, int npds, st_utime_t timeout) | 58 | int st_poll(struct pollfd *pds, int npds, st_utime_t timeout) |
61 | { | 59 | { |
62 | - struct pollfd *pd; | ||
63 | - struct pollfd *epd = pds + npds; | ||
64 | - _st_pollq_t pq; | ||
65 | - _st_thread_t *me = _ST_CURRENT_THREAD(); | ||
66 | - int n; | ||
67 | - | ||
68 | - if (me->flags & _ST_FL_INTERRUPT) { | ||
69 | - me->flags &= ~_ST_FL_INTERRUPT; | ||
70 | - errno = EINTR; | ||
71 | - return -1; | ||
72 | - } | ||
73 | - | ||
74 | - if ((*_st_eventsys->pollset_add)(pds, npds) < 0) | ||
75 | - return -1; | ||
76 | - | ||
77 | - pq.pds = pds; | ||
78 | - pq.npds = npds; | ||
79 | - pq.thread = me; | ||
80 | - pq.on_ioq = 1; | ||
81 | - _ST_ADD_IOQ(pq); | ||
82 | - if (timeout != ST_UTIME_NO_TIMEOUT) | ||
83 | - _ST_ADD_SLEEPQ(me, timeout); | ||
84 | - me->state = _ST_ST_IO_WAIT; | ||
85 | - | ||
86 | - _ST_SWITCH_CONTEXT(me); | ||
87 | - | ||
88 | - n = 0; | ||
89 | - if (pq.on_ioq) { | ||
90 | - /* If we timed out, the pollq might still be on the ioq. Remove it */ | ||
91 | - _ST_DEL_IOQ(pq); | ||
92 | - (*_st_eventsys->pollset_del)(pds, npds); | ||
93 | - } else { | ||
94 | - /* Count the number of ready descriptors */ | ||
95 | - for (pd = pds; pd < epd; pd++) { | ||
96 | - if (pd->revents) | ||
97 | - n++; | ||
98 | - } | ||
99 | - } | ||
100 | - | ||
101 | - if (me->flags & _ST_FL_INTERRUPT) { | ||
102 | - me->flags &= ~_ST_FL_INTERRUPT; | ||
103 | - errno = EINTR; | ||
104 | - return -1; | ||
105 | - } | ||
106 | - | ||
107 | - return n; | 60 | + struct pollfd *pd; |
61 | + struct pollfd *epd = pds + npds; | ||
62 | + _st_pollq_t pq; | ||
63 | + _st_thread_t *me = _ST_CURRENT_THREAD(); | ||
64 | + int n; | ||
65 | + | ||
66 | + if (me->flags & _ST_FL_INTERRUPT) { | ||
67 | + me->flags &= ~_ST_FL_INTERRUPT; | ||
68 | + errno = EINTR; | ||
69 | + return -1; | ||
70 | + } | ||
71 | + | ||
72 | + if ((*_st_eventsys->pollset_add)(pds, npds) < 0) { | ||
73 | + return -1; | ||
74 | + } | ||
75 | + | ||
76 | + pq.pds = pds; | ||
77 | + pq.npds = npds; | ||
78 | + pq.thread = me; | ||
79 | + pq.on_ioq = 1; | ||
80 | + _ST_ADD_IOQ(pq); | ||
81 | + if (timeout != ST_UTIME_NO_TIMEOUT) { | ||
82 | + _ST_ADD_SLEEPQ(me, timeout); | ||
83 | + } | ||
84 | + me->state = _ST_ST_IO_WAIT; | ||
85 | + | ||
86 | + _ST_SWITCH_CONTEXT(me); | ||
87 | + | ||
88 | + n = 0; | ||
89 | + if (pq.on_ioq) { | ||
90 | + /* If we timed out, the pollq might still be on the ioq. Remove it */ | ||
91 | + _ST_DEL_IOQ(pq); | ||
92 | + (*_st_eventsys->pollset_del)(pds, npds); | ||
93 | + } else { | ||
94 | + /* Count the number of ready descriptors */ | ||
95 | + for (pd = pds; pd < epd; pd++) { | ||
96 | + if (pd->revents) { | ||
97 | + n++; | ||
98 | + } | ||
99 | + } | ||
100 | + } | ||
101 | + | ||
102 | + if (me->flags & _ST_FL_INTERRUPT) { | ||
103 | + me->flags &= ~_ST_FL_INTERRUPT; | ||
104 | + errno = EINTR; | ||
105 | + return -1; | ||
106 | + } | ||
107 | + | ||
108 | + return n; | ||
108 | } | 109 | } |
109 | 110 | ||
110 | - | ||
111 | void _st_vp_schedule(void) | 111 | void _st_vp_schedule(void) |
112 | { | 112 | { |
113 | - _st_thread_t *thread; | ||
114 | - | ||
115 | - if (_ST_RUNQ.next != &_ST_RUNQ) { | ||
116 | - /* Pull thread off of the run queue */ | ||
117 | - thread = _ST_THREAD_PTR(_ST_RUNQ.next); | ||
118 | - _ST_DEL_RUNQ(thread); | ||
119 | - } else { | ||
120 | - /* If there are no threads to run, switch to the idle thread */ | ||
121 | - thread = _st_this_vp.idle_thread; | ||
122 | - } | ||
123 | - ST_ASSERT(thread->state == _ST_ST_RUNNABLE); | ||
124 | - | ||
125 | - /* Resume the thread */ | ||
126 | - thread->state = _ST_ST_RUNNING; | ||
127 | - _ST_RESTORE_CONTEXT(thread); | 113 | + _st_thread_t *thread; |
114 | + | ||
115 | + if (_ST_RUNQ.next != &_ST_RUNQ) { | ||
116 | + /* Pull thread off of the run queue */ | ||
117 | + thread = _ST_THREAD_PTR(_ST_RUNQ.next); | ||
118 | + _ST_DEL_RUNQ(thread); | ||
119 | + } else { | ||
120 | + /* If there are no threads to run, switch to the idle thread */ | ||
121 | + thread = _st_this_vp.idle_thread; | ||
122 | + } | ||
123 | + ST_ASSERT(thread->state == _ST_ST_RUNNABLE); | ||
124 | + | ||
125 | + /* Resume the thread */ | ||
126 | + thread->state = _ST_ST_RUNNING; | ||
127 | + _ST_RESTORE_CONTEXT(thread); | ||
128 | } | 128 | } |
129 | 129 | ||
130 | - | ||
131 | /* | 130 | /* |
132 | * Initialize this Virtual Processor | 131 | * Initialize this Virtual Processor |
133 | */ | 132 | */ |
134 | int st_init(void) | 133 | int st_init(void) |
135 | { | 134 | { |
136 | - _st_thread_t *thread; | ||
137 | - | ||
138 | - if (_st_active_count) { | ||
139 | - /* Already initialized */ | ||
140 | - return 0; | ||
141 | - } | ||
142 | - | ||
143 | - /* We can ignore return value here */ | ||
144 | - st_set_eventsys(ST_EVENTSYS_DEFAULT); | ||
145 | - | ||
146 | - if (_st_io_init() < 0) | ||
147 | - return -1; | ||
148 | - | ||
149 | - memset(&_st_this_vp, 0, sizeof(_st_vp_t)); | ||
150 | - | ||
151 | - ST_INIT_CLIST(&_ST_RUNQ); | ||
152 | - ST_INIT_CLIST(&_ST_IOQ); | ||
153 | - ST_INIT_CLIST(&_ST_ZOMBIEQ); | 135 | + _st_thread_t *thread; |
136 | + | ||
137 | + if (_st_active_count) { | ||
138 | + /* Already initialized */ | ||
139 | + return 0; | ||
140 | + } | ||
141 | + | ||
142 | + /* We can ignore return value here */ | ||
143 | + st_set_eventsys(ST_EVENTSYS_DEFAULT); | ||
144 | + | ||
145 | + if (_st_io_init() < 0) { | ||
146 | + return -1; | ||
147 | + } | ||
148 | + | ||
149 | + memset(&_st_this_vp, 0, sizeof(_st_vp_t)); | ||
150 | + | ||
151 | + ST_INIT_CLIST(&_ST_RUNQ); | ||
152 | + ST_INIT_CLIST(&_ST_IOQ); | ||
153 | + ST_INIT_CLIST(&_ST_ZOMBIEQ); | ||
154 | #ifdef DEBUG | 154 | #ifdef DEBUG |
155 | - ST_INIT_CLIST(&_ST_THREADQ); | 155 | + ST_INIT_CLIST(&_ST_THREADQ); |
156 | #endif | 156 | #endif |
157 | - | ||
158 | - if ((*_st_eventsys->init)() < 0) | ||
159 | - return -1; | ||
160 | - | ||
161 | - _st_this_vp.pagesize = getpagesize(); | ||
162 | - _st_this_vp.last_clock = st_utime(); | ||
163 | - | ||
164 | - /* | ||
165 | - * Create idle thread | ||
166 | - */ | ||
167 | - _st_this_vp.idle_thread = st_thread_create(_st_idle_thread_start, | ||
168 | - NULL, 0, 0); | ||
169 | - if (!_st_this_vp.idle_thread) | ||
170 | - return -1; | ||
171 | - _st_this_vp.idle_thread->flags = _ST_FL_IDLE_THREAD; | ||
172 | - _st_active_count--; | ||
173 | - _ST_DEL_RUNQ(_st_this_vp.idle_thread); | ||
174 | - | ||
175 | - /* | ||
176 | - * Initialize primordial thread | ||
177 | - */ | ||
178 | - thread = (_st_thread_t *) calloc(1, sizeof(_st_thread_t) + | ||
179 | - (ST_KEYS_MAX * sizeof(void *))); | ||
180 | - if (!thread) | ||
181 | - return -1; | ||
182 | - thread->private_data = (void **) (thread + 1); | ||
183 | - thread->state = _ST_ST_RUNNING; | ||
184 | - thread->flags = _ST_FL_PRIMORDIAL; | ||
185 | - _ST_SET_CURRENT_THREAD(thread); | ||
186 | - _st_active_count++; | 157 | + |
158 | + if ((*_st_eventsys->init)() < 0) { | ||
159 | + return -1; | ||
160 | + } | ||
161 | + | ||
162 | + _st_this_vp.pagesize = getpagesize(); | ||
163 | + _st_this_vp.last_clock = st_utime(); | ||
164 | + | ||
165 | + /* | ||
166 | + * Create idle thread | ||
167 | + */ | ||
168 | + _st_this_vp.idle_thread = st_thread_create(_st_idle_thread_start, NULL, 0, 0); | ||
169 | + if (!_st_this_vp.idle_thread) { | ||
170 | + return -1; | ||
171 | + } | ||
172 | + _st_this_vp.idle_thread->flags = _ST_FL_IDLE_THREAD; | ||
173 | + _st_active_count--; | ||
174 | + _ST_DEL_RUNQ(_st_this_vp.idle_thread); | ||
175 | + | ||
176 | + /* | ||
177 | + * Initialize primordial thread | ||
178 | + */ | ||
179 | + thread = (_st_thread_t *) calloc(1, sizeof(_st_thread_t) + | ||
180 | + (ST_KEYS_MAX * sizeof(void *))); | ||
181 | + if (!thread) { | ||
182 | + return -1; | ||
183 | + } | ||
184 | + thread->private_data = (void **) (thread + 1); | ||
185 | + thread->state = _ST_ST_RUNNING; | ||
186 | + thread->flags = _ST_FL_PRIMORDIAL; | ||
187 | + _ST_SET_CURRENT_THREAD(thread); | ||
188 | + _st_active_count++; | ||
187 | #ifdef DEBUG | 189 | #ifdef DEBUG |
188 | - _ST_ADD_THREADQ(thread); | 190 | + _ST_ADD_THREADQ(thread); |
189 | #endif | 191 | #endif |
190 | - | ||
191 | - return 0; | 192 | + |
193 | + return 0; | ||
192 | } | 194 | } |
193 | 195 | ||
194 | - | ||
195 | #ifdef ST_SWITCH_CB | 196 | #ifdef ST_SWITCH_CB |
196 | st_switch_cb_t st_set_switch_in_cb(st_switch_cb_t cb) | 197 | st_switch_cb_t st_set_switch_in_cb(st_switch_cb_t cb) |
197 | { | 198 | { |
198 | - st_switch_cb_t ocb = _st_this_vp.switch_in_cb; | ||
199 | - _st_this_vp.switch_in_cb = cb; | ||
200 | - return ocb; | 199 | + st_switch_cb_t ocb = _st_this_vp.switch_in_cb; |
200 | + _st_this_vp.switch_in_cb = cb; | ||
201 | + return ocb; | ||
201 | } | 202 | } |
202 | 203 | ||
203 | st_switch_cb_t st_set_switch_out_cb(st_switch_cb_t cb) | 204 | st_switch_cb_t st_set_switch_out_cb(st_switch_cb_t cb) |
204 | { | 205 | { |
205 | - st_switch_cb_t ocb = _st_this_vp.switch_out_cb; | ||
206 | - _st_this_vp.switch_out_cb = cb; | ||
207 | - return ocb; | 206 | + st_switch_cb_t ocb = _st_this_vp.switch_out_cb; |
207 | + _st_this_vp.switch_out_cb = cb; | ||
208 | + return ocb; | ||
208 | } | 209 | } |
209 | #endif | 210 | #endif |
210 | 211 | ||
211 | - | ||
212 | /* | 212 | /* |
213 | * Start function for the idle thread | 213 | * Start function for the idle thread |
214 | */ | 214 | */ |
215 | /* ARGSUSED */ | 215 | /* ARGSUSED */ |
216 | void *_st_idle_thread_start(void *arg) | 216 | void *_st_idle_thread_start(void *arg) |
217 | { | 217 | { |
218 | - _st_thread_t *me = _ST_CURRENT_THREAD(); | ||
219 | - | ||
220 | - while (_st_active_count > 0) { | ||
221 | - /* Idle vp till I/O is ready or the smallest timeout expired */ | ||
222 | - _ST_VP_IDLE(); | ||
223 | - | ||
224 | - /* Check sleep queue for expired threads */ | ||
225 | - _st_vp_check_clock(); | ||
226 | - | ||
227 | - me->state = _ST_ST_RUNNABLE; | ||
228 | - _ST_SWITCH_CONTEXT(me); | ||
229 | - } | ||
230 | - | ||
231 | - /* No more threads */ | ||
232 | - exit(0); | ||
233 | - | ||
234 | - /* NOTREACHED */ | ||
235 | - return NULL; | 218 | + _st_thread_t *me = _ST_CURRENT_THREAD(); |
219 | + | ||
220 | + while (_st_active_count > 0) { | ||
221 | + /* Idle vp till I/O is ready or the smallest timeout expired */ | ||
222 | + _ST_VP_IDLE(); | ||
223 | + | ||
224 | + /* Check sleep queue for expired threads */ | ||
225 | + _st_vp_check_clock(); | ||
226 | + | ||
227 | + me->state = _ST_ST_RUNNABLE; | ||
228 | + _ST_SWITCH_CONTEXT(me); | ||
229 | + } | ||
230 | + | ||
231 | + /* No more threads */ | ||
232 | + exit(0); | ||
233 | + | ||
234 | + /* NOTREACHED */ | ||
235 | + return NULL; | ||
236 | } | 236 | } |
237 | 237 | ||
238 | - | ||
239 | void st_thread_exit(void *retval) | 238 | void st_thread_exit(void *retval) |
240 | { | 239 | { |
241 | - _st_thread_t *thread = _ST_CURRENT_THREAD(); | ||
242 | - | ||
243 | - thread->retval = retval; | ||
244 | - _st_thread_cleanup(thread); | ||
245 | - _st_active_count--; | ||
246 | - if (thread->term) { | ||
247 | - /* Put thread on the zombie queue */ | ||
248 | - thread->state = _ST_ST_ZOMBIE; | ||
249 | - _ST_ADD_ZOMBIEQ(thread); | ||
250 | - | ||
251 | - /* Notify on our termination condition variable */ | ||
252 | - st_cond_signal(thread->term); | ||
253 | - | ||
254 | - /* Switch context and come back later */ | ||
255 | - _ST_SWITCH_CONTEXT(thread); | ||
256 | - | ||
257 | - /* Continue the cleanup */ | ||
258 | - st_cond_destroy(thread->term); | ||
259 | - thread->term = NULL; | ||
260 | - } | ||
261 | - | 240 | + _st_thread_t *thread = _ST_CURRENT_THREAD(); |
241 | + | ||
242 | + thread->retval = retval; | ||
243 | + _st_thread_cleanup(thread); | ||
244 | + _st_active_count--; | ||
245 | + if (thread->term) { | ||
246 | + /* Put thread on the zombie queue */ | ||
247 | + thread->state = _ST_ST_ZOMBIE; | ||
248 | + _ST_ADD_ZOMBIEQ(thread); | ||
249 | + | ||
250 | + /* Notify on our termination condition variable */ | ||
251 | + st_cond_signal(thread->term); | ||
252 | + | ||
253 | + /* Switch context and come back later */ | ||
254 | + _ST_SWITCH_CONTEXT(thread); | ||
255 | + | ||
256 | + /* Continue the cleanup */ | ||
257 | + st_cond_destroy(thread->term); | ||
258 | + thread->term = NULL; | ||
259 | + } | ||
260 | + | ||
262 | #ifdef DEBUG | 261 | #ifdef DEBUG |
263 | - _ST_DEL_THREADQ(thread); | 262 | + _ST_DEL_THREADQ(thread); |
264 | #endif | 263 | #endif |
265 | - | ||
266 | - if (!(thread->flags & _ST_FL_PRIMORDIAL)) | ||
267 | - _st_stack_free(thread->stack); | ||
268 | - | ||
269 | - /* Find another thread to run */ | ||
270 | - _ST_SWITCH_CONTEXT(thread); | ||
271 | - /* Not going to land here */ | 264 | + |
265 | + if (!(thread->flags & _ST_FL_PRIMORDIAL)) { | ||
266 | + _st_stack_free(thread->stack); | ||
267 | + } | ||
268 | + | ||
269 | + /* Find another thread to run */ | ||
270 | + _ST_SWITCH_CONTEXT(thread); | ||
271 | + /* Not going to land here */ | ||
272 | } | 272 | } |
273 | 273 | ||
274 | - | ||
275 | int st_thread_join(_st_thread_t *thread, void **retvalp) | 274 | int st_thread_join(_st_thread_t *thread, void **retvalp) |
276 | { | 275 | { |
277 | - _st_cond_t *term = thread->term; | ||
278 | - | ||
279 | - /* Can't join a non-joinable thread */ | ||
280 | - if (term == NULL) { | ||
281 | - errno = EINVAL; | ||
282 | - return -1; | ||
283 | - } | ||
284 | - if (_ST_CURRENT_THREAD() == thread) { | ||
285 | - errno = EDEADLK; | ||
286 | - return -1; | ||
287 | - } | ||
288 | - | ||
289 | - /* Multiple threads can't wait on the same joinable thread */ | ||
290 | - if (term->wait_q.next != &term->wait_q) { | ||
291 | - errno = EINVAL; | ||
292 | - return -1; | ||
293 | - } | ||
294 | - | ||
295 | - while (thread->state != _ST_ST_ZOMBIE) { | ||
296 | - if (st_cond_timedwait(term, ST_UTIME_NO_TIMEOUT) != 0) | ||
297 | - return -1; | ||
298 | - } | ||
299 | - | ||
300 | - if (retvalp) | ||
301 | - *retvalp = thread->retval; | ||
302 | - | ||
303 | - /* | ||
304 | - * Remove target thread from the zombie queue and make it runnable. | ||
305 | - * When it gets scheduled later, it will do the clean up. | ||
306 | - */ | ||
307 | - thread->state = _ST_ST_RUNNABLE; | ||
308 | - _ST_DEL_ZOMBIEQ(thread); | ||
309 | - _ST_ADD_RUNQ(thread); | ||
310 | - | ||
311 | - return 0; | 276 | + _st_cond_t *term = thread->term; |
277 | + | ||
278 | + /* Can't join a non-joinable thread */ | ||
279 | + if (term == NULL) { | ||
280 | + errno = EINVAL; | ||
281 | + return -1; | ||
282 | + } | ||
283 | + if (_ST_CURRENT_THREAD() == thread) { | ||
284 | + errno = EDEADLK; | ||
285 | + return -1; | ||
286 | + } | ||
287 | + | ||
288 | + /* Multiple threads can't wait on the same joinable thread */ | ||
289 | + if (term->wait_q.next != &term->wait_q) { | ||
290 | + errno = EINVAL; | ||
291 | + return -1; | ||
292 | + } | ||
293 | + | ||
294 | + while (thread->state != _ST_ST_ZOMBIE) { | ||
295 | + if (st_cond_timedwait(term, ST_UTIME_NO_TIMEOUT) != 0) { | ||
296 | + return -1; | ||
297 | + } | ||
298 | + } | ||
299 | + | ||
300 | + if (retvalp) { | ||
301 | + *retvalp = thread->retval; | ||
302 | + } | ||
303 | + | ||
304 | + /* | ||
305 | + * Remove target thread from the zombie queue and make it runnable. | ||
306 | + * When it gets scheduled later, it will do the clean up. | ||
307 | + */ | ||
308 | + thread->state = _ST_ST_RUNNABLE; | ||
309 | + _ST_DEL_ZOMBIEQ(thread); | ||
310 | + _ST_ADD_RUNQ(thread); | ||
311 | + | ||
312 | + return 0; | ||
312 | } | 313 | } |
313 | 314 | ||
314 | - | ||
315 | void _st_thread_main(void) | 315 | void _st_thread_main(void) |
316 | { | 316 | { |
317 | - _st_thread_t *thread = _ST_CURRENT_THREAD(); | ||
318 | - | ||
319 | - /* | ||
320 | - * Cap the stack by zeroing out the saved return address register | ||
321 | - * value. This allows some debugging/profiling tools to know when | ||
322 | - * to stop unwinding the stack. It's a no-op on most platforms. | ||
323 | - */ | ||
324 | - MD_CAP_STACK(&thread); | ||
325 | - | ||
326 | - /* Run thread main */ | ||
327 | - thread->retval = (*thread->start)(thread->arg); | ||
328 | - | ||
329 | - /* All done, time to go away */ | ||
330 | - st_thread_exit(thread->retval); | 317 | + _st_thread_t *thread = _ST_CURRENT_THREAD(); |
318 | + | ||
319 | + /* | ||
320 | + * Cap the stack by zeroing out the saved return address register | ||
321 | + * value. This allows some debugging/profiling tools to know when | ||
322 | + * to stop unwinding the stack. It's a no-op on most platforms. | ||
323 | + */ | ||
324 | + MD_CAP_STACK(&thread); | ||
325 | + | ||
326 | + /* Run thread main */ | ||
327 | + thread->retval = (*thread->start)(thread->arg); | ||
328 | + | ||
329 | + /* All done, time to go away */ | ||
330 | + st_thread_exit(thread->retval); | ||
331 | } | 331 | } |
332 | 332 | ||
333 | - | ||
334 | /* | 333 | /* |
335 | * Insert "thread" into the timeout heap, in the position | 334 | * Insert "thread" into the timeout heap, in the position |
336 | * specified by thread->heap_index. See docs/timeout_heap.txt | 335 | * specified by thread->heap_index. See docs/timeout_heap.txt |
337 | * for details about the timeout heap. | 336 | * for details about the timeout heap. |
338 | */ | 337 | */ |
339 | -static _st_thread_t **heap_insert(_st_thread_t *thread) { | ||
340 | - int target = thread->heap_index; | ||
341 | - int s = target; | ||
342 | - _st_thread_t **p = &_ST_SLEEPQ; | ||
343 | - int bits = 0; | ||
344 | - int bit; | ||
345 | - int index = 1; | ||
346 | - | ||
347 | - while (s) { | ||
348 | - s >>= 1; | ||
349 | - bits++; | ||
350 | - } | ||
351 | - for (bit = bits - 2; bit >= 0; bit--) { | ||
352 | - if (thread->due < (*p)->due) { | ||
353 | - _st_thread_t *t = *p; | ||
354 | - thread->left = t->left; | ||
355 | - thread->right = t->right; | ||
356 | - *p = thread; | ||
357 | - thread->heap_index = index; | ||
358 | - thread = t; | ||
359 | - } | ||
360 | - index <<= 1; | ||
361 | - if (target & (1 << bit)) { | ||
362 | - p = &((*p)->right); | ||
363 | - index |= 1; | ||
364 | - } else { | ||
365 | - p = &((*p)->left); | 338 | +static _st_thread_t **heap_insert(_st_thread_t *thread) |
339 | +{ | ||
340 | + int target = thread->heap_index; | ||
341 | + int s = target; | ||
342 | + _st_thread_t **p = &_ST_SLEEPQ; | ||
343 | + int bits = 0; | ||
344 | + int bit; | ||
345 | + int index = 1; | ||
346 | + | ||
347 | + while (s) { | ||
348 | + s >>= 1; | ||
349 | + bits++; | ||
366 | } | 350 | } |
367 | - } | ||
368 | - thread->heap_index = index; | ||
369 | - *p = thread; | ||
370 | - thread->left = thread->right = NULL; | ||
371 | - return p; | 351 | + |
352 | + for (bit = bits - 2; bit >= 0; bit--) { | ||
353 | + if (thread->due < (*p)->due) { | ||
354 | + _st_thread_t *t = *p; | ||
355 | + thread->left = t->left; | ||
356 | + thread->right = t->right; | ||
357 | + *p = thread; | ||
358 | + thread->heap_index = index; | ||
359 | + thread = t; | ||
360 | + } | ||
361 | + index <<= 1; | ||
362 | + if (target & (1 << bit)) { | ||
363 | + p = &((*p)->right); | ||
364 | + index |= 1; | ||
365 | + } else { | ||
366 | + p = &((*p)->left); | ||
367 | + } | ||
368 | + } | ||
369 | + | ||
370 | + thread->heap_index = index; | ||
371 | + *p = thread; | ||
372 | + thread->left = thread->right = NULL; | ||
373 | + | ||
374 | + return p; | ||
372 | } | 375 | } |
373 | 376 | ||
374 | - | ||
375 | /* | 377 | /* |
376 | * Delete "thread" from the timeout heap. | 378 | * Delete "thread" from the timeout heap. |
377 | */ | 379 | */ |
378 | -static void heap_delete(_st_thread_t *thread) { | ||
379 | - _st_thread_t *t, **p; | ||
380 | - int bits = 0; | ||
381 | - int s, bit; | ||
382 | - | ||
383 | - /* First find and unlink the last heap element */ | ||
384 | - p = &_ST_SLEEPQ; | ||
385 | - s = _ST_SLEEPQ_SIZE; | ||
386 | - while (s) { | ||
387 | - s >>= 1; | ||
388 | - bits++; | ||
389 | - } | ||
390 | - for (bit = bits - 2; bit >= 0; bit--) { | ||
391 | - if (_ST_SLEEPQ_SIZE & (1 << bit)) { | ||
392 | - p = &((*p)->right); | ||
393 | - } else { | ||
394 | - p = &((*p)->left); | 380 | +static void heap_delete(_st_thread_t *thread) |
381 | +{ | ||
382 | + _st_thread_t *t, **p; | ||
383 | + int bits = 0; | ||
384 | + int s, bit; | ||
385 | + | ||
386 | + /* First find and unlink the last heap element */ | ||
387 | + p = &_ST_SLEEPQ; | ||
388 | + s = _ST_SLEEPQ_SIZE; | ||
389 | + while (s) { | ||
390 | + s >>= 1; | ||
391 | + bits++; | ||
395 | } | 392 | } |
396 | - } | ||
397 | - t = *p; | ||
398 | - *p = NULL; | ||
399 | - --_ST_SLEEPQ_SIZE; | ||
400 | - if (t != thread) { | ||
401 | - /* | ||
402 | - * Insert the unlinked last element in place of the element we are deleting | ||
403 | - */ | ||
404 | - t->heap_index = thread->heap_index; | ||
405 | - p = heap_insert(t); | 393 | + |
394 | + for (bit = bits - 2; bit >= 0; bit--) { | ||
395 | + if (_ST_SLEEPQ_SIZE & (1 << bit)) { | ||
396 | + p = &((*p)->right); | ||
397 | + } else { | ||
398 | + p = &((*p)->left); | ||
399 | + } | ||
400 | + } | ||
401 | + | ||
406 | t = *p; | 402 | t = *p; |
407 | - t->left = thread->left; | ||
408 | - t->right = thread->right; | ||
409 | - | ||
410 | - /* | ||
411 | - * Reestablish the heap invariant. | ||
412 | - */ | ||
413 | - for (;;) { | ||
414 | - _st_thread_t *y; /* The younger child */ | ||
415 | - int index_tmp; | ||
416 | - if (t->left == NULL) | ||
417 | - break; | ||
418 | - else if (t->right == NULL) | ||
419 | - y = t->left; | ||
420 | - else if (t->left->due < t->right->due) | ||
421 | - y = t->left; | ||
422 | - else | ||
423 | - y = t->right; | ||
424 | - if (t->due > y->due) { | ||
425 | - _st_thread_t *tl = y->left; | ||
426 | - _st_thread_t *tr = y->right; | ||
427 | - *p = y; | ||
428 | - if (y == t->left) { | ||
429 | - y->left = t; | ||
430 | - y->right = t->right; | ||
431 | - p = &y->left; | ||
432 | - } else { | ||
433 | - y->left = t->left; | ||
434 | - y->right = t; | ||
435 | - p = &y->right; | ||
436 | - } | ||
437 | - t->left = tl; | ||
438 | - t->right = tr; | ||
439 | - index_tmp = t->heap_index; | ||
440 | - t->heap_index = y->heap_index; | ||
441 | - y->heap_index = index_tmp; | ||
442 | - } else { | ||
443 | - break; | ||
444 | - } | ||
445 | - } | ||
446 | - } | ||
447 | - thread->left = thread->right = NULL; | 403 | + *p = NULL; |
404 | + --_ST_SLEEPQ_SIZE; | ||
405 | + if (t != thread) { | ||
406 | + /* | ||
407 | + * Insert the unlinked last element in place of the element we are deleting | ||
408 | + */ | ||
409 | + t->heap_index = thread->heap_index; | ||
410 | + p = heap_insert(t); | ||
411 | + t = *p; | ||
412 | + t->left = thread->left; | ||
413 | + t->right = thread->right; | ||
414 | + | ||
415 | + /* | ||
416 | + * Reestablish the heap invariant. | ||
417 | + */ | ||
418 | + for (;;) { | ||
419 | + _st_thread_t *y; /* The younger child */ | ||
420 | + int index_tmp; | ||
421 | + | ||
422 | + if (t->left == NULL) { | ||
423 | + break; | ||
424 | + } else if (t->right == NULL) { | ||
425 | + y = t->left; | ||
426 | + } else if (t->left->due < t->right->due) { | ||
427 | + y = t->left; | ||
428 | + } else { | ||
429 | + y = t->right; | ||
430 | + } | ||
431 | + | ||
432 | + if (t->due > y->due) { | ||
433 | + _st_thread_t *tl = y->left; | ||
434 | + _st_thread_t *tr = y->right; | ||
435 | + *p = y; | ||
436 | + if (y == t->left) { | ||
437 | + y->left = t; | ||
438 | + y->right = t->right; | ||
439 | + p = &y->left; | ||
440 | + } else { | ||
441 | + y->left = t->left; | ||
442 | + y->right = t; | ||
443 | + p = &y->right; | ||
444 | + } | ||
445 | + t->left = tl; | ||
446 | + t->right = tr; | ||
447 | + index_tmp = t->heap_index; | ||
448 | + t->heap_index = y->heap_index; | ||
449 | + y->heap_index = index_tmp; | ||
450 | + } else { | ||
451 | + break; | ||
452 | + } | ||
453 | + } | ||
454 | + } | ||
455 | + | ||
456 | + thread->left = thread->right = NULL; | ||
448 | } | 457 | } |
449 | 458 | ||
450 | - | ||
451 | void _st_add_sleep_q(_st_thread_t *thread, st_utime_t timeout) | 459 | void _st_add_sleep_q(_st_thread_t *thread, st_utime_t timeout) |
452 | { | 460 | { |
453 | - thread->due = _ST_LAST_CLOCK + timeout; | ||
454 | - thread->flags |= _ST_FL_ON_SLEEPQ; | ||
455 | - thread->heap_index = ++_ST_SLEEPQ_SIZE; | ||
456 | - heap_insert(thread); | 461 | + thread->due = _ST_LAST_CLOCK + timeout; |
462 | + thread->flags |= _ST_FL_ON_SLEEPQ; | ||
463 | + thread->heap_index = ++_ST_SLEEPQ_SIZE; | ||
464 | + heap_insert(thread); | ||
457 | } | 465 | } |
458 | 466 | ||
459 | - | ||
460 | void _st_del_sleep_q(_st_thread_t *thread) | 467 | void _st_del_sleep_q(_st_thread_t *thread) |
461 | { | 468 | { |
462 | - heap_delete(thread); | ||
463 | - thread->flags &= ~_ST_FL_ON_SLEEPQ; | 469 | + heap_delete(thread); |
470 | + thread->flags &= ~_ST_FL_ON_SLEEPQ; | ||
464 | } | 471 | } |
465 | 472 | ||
466 | - | ||
467 | void _st_vp_check_clock(void) | 473 | void _st_vp_check_clock(void) |
468 | { | 474 | { |
469 | - _st_thread_t *thread; | ||
470 | - st_utime_t elapsed, now; | ||
471 | - | ||
472 | - now = st_utime(); | ||
473 | - elapsed = now - _ST_LAST_CLOCK; | ||
474 | - _ST_LAST_CLOCK = now; | ||
475 | - | ||
476 | - if (_st_curr_time && now - _st_last_tset > 999000) { | ||
477 | - _st_curr_time = time(NULL); | ||
478 | - _st_last_tset = now; | ||
479 | - } | ||
480 | - | ||
481 | - while (_ST_SLEEPQ != NULL) { | ||
482 | - thread = _ST_SLEEPQ; | ||
483 | - ST_ASSERT(thread->flags & _ST_FL_ON_SLEEPQ); | ||
484 | - if (thread->due > now) | ||
485 | - break; | ||
486 | - _ST_DEL_SLEEPQ(thread); | ||
487 | - | ||
488 | - /* If thread is waiting on condition variable, set the time out flag */ | ||
489 | - if (thread->state == _ST_ST_COND_WAIT) | ||
490 | - thread->flags |= _ST_FL_TIMEDOUT; | ||
491 | - | ||
492 | - /* Make thread runnable */ | ||
493 | - ST_ASSERT(!(thread->flags & _ST_FL_IDLE_THREAD)); | ||
494 | - thread->state = _ST_ST_RUNNABLE; | ||
495 | - _ST_ADD_RUNQ(thread); | ||
496 | - } | 475 | + _st_thread_t *thread; |
476 | + st_utime_t elapsed, now; | ||
477 | + | ||
478 | + now = st_utime(); | ||
479 | + elapsed = now - _ST_LAST_CLOCK; | ||
480 | + _ST_LAST_CLOCK = now; | ||
481 | + | ||
482 | + if (_st_curr_time && now - _st_last_tset > 999000) { | ||
483 | + _st_curr_time = time(NULL); | ||
484 | + _st_last_tset = now; | ||
485 | + } | ||
486 | + | ||
487 | + while (_ST_SLEEPQ != NULL) { | ||
488 | + thread = _ST_SLEEPQ; | ||
489 | + ST_ASSERT(thread->flags & _ST_FL_ON_SLEEPQ); | ||
490 | + if (thread->due > now) { | ||
491 | + break; | ||
492 | + } | ||
493 | + _ST_DEL_SLEEPQ(thread); | ||
494 | + | ||
495 | + /* If thread is waiting on condition variable, set the time out flag */ | ||
496 | + if (thread->state == _ST_ST_COND_WAIT) { | ||
497 | + thread->flags |= _ST_FL_TIMEDOUT; | ||
498 | + } | ||
499 | + | ||
500 | + /* Make thread runnable */ | ||
501 | + ST_ASSERT(!(thread->flags & _ST_FL_IDLE_THREAD)); | ||
502 | + thread->state = _ST_ST_RUNNABLE; | ||
503 | + _ST_ADD_RUNQ(thread); | ||
504 | + } | ||
497 | } | 505 | } |
498 | 506 | ||
499 | - | ||
500 | void st_thread_interrupt(_st_thread_t *thread) | 507 | void st_thread_interrupt(_st_thread_t *thread) |
501 | { | 508 | { |
502 | - /* If thread is already dead */ | ||
503 | - if (thread->state == _ST_ST_ZOMBIE) | ||
504 | - return; | ||
505 | - | ||
506 | - thread->flags |= _ST_FL_INTERRUPT; | ||
507 | - | ||
508 | - if (thread->state == _ST_ST_RUNNING || thread->state == _ST_ST_RUNNABLE) | ||
509 | - return; | ||
510 | - | ||
511 | - if (thread->flags & _ST_FL_ON_SLEEPQ) | ||
512 | - _ST_DEL_SLEEPQ(thread); | ||
513 | - | ||
514 | - /* Make thread runnable */ | ||
515 | - thread->state = _ST_ST_RUNNABLE; | ||
516 | - _ST_ADD_RUNQ(thread); | 509 | + /* If thread is already dead */ |
510 | + if (thread->state == _ST_ST_ZOMBIE) { | ||
511 | + return; | ||
512 | + } | ||
513 | + | ||
514 | + thread->flags |= _ST_FL_INTERRUPT; | ||
515 | + | ||
516 | + if (thread->state == _ST_ST_RUNNING || thread->state == _ST_ST_RUNNABLE) { | ||
517 | + return; | ||
518 | + } | ||
519 | + | ||
520 | + if (thread->flags & _ST_FL_ON_SLEEPQ) { | ||
521 | + _ST_DEL_SLEEPQ(thread); | ||
522 | + } | ||
523 | + | ||
524 | + /* Make thread runnable */ | ||
525 | + thread->state = _ST_ST_RUNNABLE; | ||
526 | + _ST_ADD_RUNQ(thread); | ||
517 | } | 527 | } |
518 | 528 | ||
519 | - | ||
520 | -_st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, | ||
521 | - int joinable, int stk_size) | 529 | +_st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinable, int stk_size) |
522 | { | 530 | { |
523 | - _st_thread_t *thread; | ||
524 | - _st_stack_t *stack; | ||
525 | - void **ptds; | ||
526 | - char *sp; | 531 | + _st_thread_t *thread; |
532 | + _st_stack_t *stack; | ||
533 | + void **ptds; | ||
534 | + char *sp; | ||
527 | #ifdef __ia64__ | 535 | #ifdef __ia64__ |
528 | - char *bsp; | 536 | + char *bsp; |
529 | #endif | 537 | #endif |
530 | - | ||
531 | - /* Adjust stack size */ | ||
532 | - if (stk_size == 0) | ||
533 | - stk_size = ST_DEFAULT_STACK_SIZE; | ||
534 | - stk_size = ((stk_size + _ST_PAGE_SIZE - 1) / _ST_PAGE_SIZE) * _ST_PAGE_SIZE; | ||
535 | - stack = _st_stack_new(stk_size); | ||
536 | - if (!stack) | ||
537 | - return NULL; | ||
538 | - | ||
539 | - /* Allocate thread object and per-thread data off the stack */ | 538 | + |
539 | + /* Adjust stack size */ | ||
540 | + if (stk_size == 0) { | ||
541 | + stk_size = ST_DEFAULT_STACK_SIZE; | ||
542 | + } | ||
543 | + stk_size = ((stk_size + _ST_PAGE_SIZE - 1) / _ST_PAGE_SIZE) * _ST_PAGE_SIZE; | ||
544 | + stack = _st_stack_new(stk_size); | ||
545 | + if (!stack) { | ||
546 | + return NULL; | ||
547 | + } | ||
548 | + | ||
549 | + /* Allocate thread object and per-thread data off the stack */ | ||
540 | #if defined (MD_STACK_GROWS_DOWN) | 550 | #if defined (MD_STACK_GROWS_DOWN) |
541 | - sp = stack->stk_top; | ||
542 | -#ifdef __ia64__ | ||
543 | - /* | ||
544 | - * The stack segment is split in the middle. The upper half is used | ||
545 | - * as backing store for the register stack which grows upward. | ||
546 | - * The lower half is used for the traditional memory stack which | ||
547 | - * grows downward. Both stacks start in the middle and grow outward | ||
548 | - * from each other. | ||
549 | - */ | ||
550 | - sp -= (stk_size >> 1); | ||
551 | - bsp = sp; | ||
552 | - /* Make register stack 64-byte aligned */ | ||
553 | - if ((unsigned long)bsp & 0x3f) | ||
554 | - bsp = bsp + (0x40 - ((unsigned long)bsp & 0x3f)); | ||
555 | - stack->bsp = bsp + _ST_STACK_PAD_SIZE; | ||
556 | -#endif | ||
557 | - sp = sp - (ST_KEYS_MAX * sizeof(void *)); | ||
558 | - ptds = (void **) sp; | ||
559 | - sp = sp - sizeof(_st_thread_t); | ||
560 | - thread = (_st_thread_t *) sp; | ||
561 | - | ||
562 | - /* Make stack 64-byte aligned */ | ||
563 | - if ((unsigned long)sp & 0x3f) | ||
564 | - sp = sp - ((unsigned long)sp & 0x3f); | ||
565 | - stack->sp = sp - _ST_STACK_PAD_SIZE; | 551 | + sp = stack->stk_top; |
552 | + #ifdef __ia64__ | ||
553 | + /* | ||
554 | + * The stack segment is split in the middle. The upper half is used | ||
555 | + * as backing store for the register stack which grows upward. | ||
556 | + * The lower half is used for the traditional memory stack which | ||
557 | + * grows downward. Both stacks start in the middle and grow outward | ||
558 | + * from each other. | ||
559 | + */ | ||
560 | + sp -= (stk_size >> 1); | ||
561 | + bsp = sp; | ||
562 | + /* Make register stack 64-byte aligned */ | ||
563 | + if ((unsigned long)bsp & 0x3f) { | ||
564 | + bsp = bsp + (0x40 - ((unsigned long)bsp & 0x3f)); | ||
565 | + } | ||
566 | + stack->bsp = bsp + _ST_STACK_PAD_SIZE; | ||
567 | + #endif | ||
568 | + sp = sp - (ST_KEYS_MAX * sizeof(void *)); | ||
569 | + ptds = (void **) sp; | ||
570 | + sp = sp - sizeof(_st_thread_t); | ||
571 | + thread = (_st_thread_t *) sp; | ||
572 | + | ||
573 | + /* Make stack 64-byte aligned */ | ||
574 | + if ((unsigned long)sp & 0x3f) { | ||
575 | + sp = sp - ((unsigned long)sp & 0x3f); | ||
576 | + } | ||
577 | + stack->sp = sp - _ST_STACK_PAD_SIZE; | ||
566 | #elif defined (MD_STACK_GROWS_UP) | 578 | #elif defined (MD_STACK_GROWS_UP) |
567 | - sp = stack->stk_bottom; | ||
568 | - thread = (_st_thread_t *) sp; | ||
569 | - sp = sp + sizeof(_st_thread_t); | ||
570 | - ptds = (void **) sp; | ||
571 | - sp = sp + (ST_KEYS_MAX * sizeof(void *)); | ||
572 | - | ||
573 | - /* Make stack 64-byte aligned */ | ||
574 | - if ((unsigned long)sp & 0x3f) | ||
575 | - sp = sp + (0x40 - ((unsigned long)sp & 0x3f)); | ||
576 | - stack->sp = sp + _ST_STACK_PAD_SIZE; | 579 | + sp = stack->stk_bottom; |
580 | + thread = (_st_thread_t *) sp; | ||
581 | + sp = sp + sizeof(_st_thread_t); | ||
582 | + ptds = (void **) sp; | ||
583 | + sp = sp + (ST_KEYS_MAX * sizeof(void *)); | ||
584 | + | ||
585 | + /* Make stack 64-byte aligned */ | ||
586 | + if ((unsigned long)sp & 0x3f) { | ||
587 | + sp = sp + (0x40 - ((unsigned long)sp & 0x3f)); | ||
588 | + } | ||
589 | + stack->sp = sp + _ST_STACK_PAD_SIZE; | ||
577 | #else | 590 | #else |
578 | -#error Unknown OS | 591 | + #error Unknown OS |
579 | #endif | 592 | #endif |
580 | - | ||
581 | - memset(thread, 0, sizeof(_st_thread_t)); | ||
582 | - memset(ptds, 0, ST_KEYS_MAX * sizeof(void *)); | ||
583 | - | ||
584 | - /* Initialize thread */ | ||
585 | - thread->private_data = ptds; | ||
586 | - thread->stack = stack; | ||
587 | - thread->start = start; | ||
588 | - thread->arg = arg; | ||
589 | - | 593 | + |
594 | + memset(thread, 0, sizeof(_st_thread_t)); | ||
595 | + memset(ptds, 0, ST_KEYS_MAX * sizeof(void *)); | ||
596 | + | ||
597 | + /* Initialize thread */ | ||
598 | + thread->private_data = ptds; | ||
599 | + thread->stack = stack; | ||
600 | + thread->start = start; | ||
601 | + thread->arg = arg; | ||
602 | + | ||
590 | #ifndef __ia64__ | 603 | #ifndef __ia64__ |
591 | - _ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main); | 604 | + _ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main); |
592 | #else | 605 | #else |
593 | - _ST_INIT_CONTEXT(thread, stack->sp, stack->bsp, _st_thread_main); | 606 | + _ST_INIT_CONTEXT(thread, stack->sp, stack->bsp, _st_thread_main); |
594 | #endif | 607 | #endif |
595 | - | ||
596 | - /* If thread is joinable, allocate a termination condition variable */ | ||
597 | - if (joinable) { | ||
598 | - thread->term = st_cond_new(); | ||
599 | - if (thread->term == NULL) { | ||
600 | - _st_stack_free(thread->stack); | ||
601 | - return NULL; | ||
602 | - } | ||
603 | - } | ||
604 | - | ||
605 | - /* Make thread runnable */ | ||
606 | - thread->state = _ST_ST_RUNNABLE; | ||
607 | - _st_active_count++; | ||
608 | - _ST_ADD_RUNQ(thread); | 608 | + |
609 | + /* If thread is joinable, allocate a termination condition variable */ | ||
610 | + if (joinable) { | ||
611 | + thread->term = st_cond_new(); | ||
612 | + if (thread->term == NULL) { | ||
613 | + _st_stack_free(thread->stack); | ||
614 | + return NULL; | ||
615 | + } | ||
616 | + } | ||
617 | + | ||
618 | + /* Make thread runnable */ | ||
619 | + thread->state = _ST_ST_RUNNABLE; | ||
620 | + _st_active_count++; | ||
621 | + _ST_ADD_RUNQ(thread); | ||
609 | #ifdef DEBUG | 622 | #ifdef DEBUG |
610 | - _ST_ADD_THREADQ(thread); | 623 | + _ST_ADD_THREADQ(thread); |
611 | #endif | 624 | #endif |
612 | - | ||
613 | - return thread; | 625 | + |
626 | + return thread; | ||
614 | } | 627 | } |
615 | 628 | ||
616 | - | ||
617 | _st_thread_t *st_thread_self(void) | 629 | _st_thread_t *st_thread_self(void) |
618 | { | 630 | { |
619 | - return _ST_CURRENT_THREAD(); | 631 | + return _ST_CURRENT_THREAD(); |
620 | } | 632 | } |
621 | 633 | ||
622 | - | ||
623 | #ifdef DEBUG | 634 | #ifdef DEBUG |
624 | /* ARGSUSED */ | 635 | /* ARGSUSED */ |
625 | void _st_show_thread_stack(_st_thread_t *thread, const char *messg) | 636 | void _st_show_thread_stack(_st_thread_t *thread, const char *messg) |
626 | { | 637 | { |
627 | - | ||
628 | } | 638 | } |
629 | 639 | ||
630 | /* To be set from debugger */ | 640 | /* To be set from debugger */ |
@@ -632,41 +642,43 @@ int _st_iterate_threads_flag = 0; | @@ -632,41 +642,43 @@ int _st_iterate_threads_flag = 0; | ||
632 | 642 | ||
633 | void _st_iterate_threads(void) | 643 | void _st_iterate_threads(void) |
634 | { | 644 | { |
635 | - static _st_thread_t *thread = NULL; | ||
636 | - static jmp_buf orig_jb, save_jb; | ||
637 | - _st_clist_t *q; | ||
638 | - | ||
639 | - if (!_st_iterate_threads_flag) { | 645 | + static _st_thread_t *thread = NULL; |
646 | + static jmp_buf orig_jb, save_jb; | ||
647 | + _st_clist_t *q; | ||
648 | + | ||
649 | + if (!_st_iterate_threads_flag) { | ||
650 | + if (thread) { | ||
651 | + memcpy(thread->context, save_jb, sizeof(jmp_buf)); | ||
652 | + MD_LONGJMP(orig_jb, 1); | ||
653 | + } | ||
654 | + return; | ||
655 | + } | ||
656 | + | ||
640 | if (thread) { | 657 | if (thread) { |
641 | - memcpy(thread->context, save_jb, sizeof(jmp_buf)); | ||
642 | - MD_LONGJMP(orig_jb, 1); | 658 | + memcpy(thread->context, save_jb, sizeof(jmp_buf)); |
659 | + _st_show_thread_stack(thread, NULL); | ||
660 | + } else { | ||
661 | + if (MD_SETJMP(orig_jb)) { | ||
662 | + _st_iterate_threads_flag = 0; | ||
663 | + thread = NULL; | ||
664 | + _st_show_thread_stack(thread, "Iteration completed"); | ||
665 | + return; | ||
666 | + } | ||
667 | + thread = _ST_CURRENT_THREAD(); | ||
668 | + _st_show_thread_stack(thread, "Iteration started"); | ||
643 | } | 669 | } |
644 | - return; | ||
645 | - } | ||
646 | - | ||
647 | - if (thread) { | ||
648 | - memcpy(thread->context, save_jb, sizeof(jmp_buf)); | ||
649 | - _st_show_thread_stack(thread, NULL); | ||
650 | - } else { | ||
651 | - if (MD_SETJMP(orig_jb)) { | ||
652 | - _st_iterate_threads_flag = 0; | ||
653 | - thread = NULL; | ||
654 | - _st_show_thread_stack(thread, "Iteration completed"); | ||
655 | - return; | ||
656 | - } | ||
657 | - thread = _ST_CURRENT_THREAD(); | ||
658 | - _st_show_thread_stack(thread, "Iteration started"); | ||
659 | - } | ||
660 | - | ||
661 | - q = thread->tlink.next; | ||
662 | - if (q == &_ST_THREADQ) | ||
663 | - q = q->next; | ||
664 | - ST_ASSERT(q != &_ST_THREADQ); | ||
665 | - thread = _ST_THREAD_THREADQ_PTR(q); | ||
666 | - if (thread == _ST_CURRENT_THREAD()) | ||
667 | - MD_LONGJMP(orig_jb, 1); | ||
668 | - memcpy(save_jb, thread->context, sizeof(jmp_buf)); | ||
669 | - MD_LONGJMP(thread->context, 1); | 670 | + |
671 | + q = thread->tlink.next; | ||
672 | + if (q == &_ST_THREADQ) { | ||
673 | + q = q->next; | ||
674 | + } | ||
675 | + ST_ASSERT(q != &_ST_THREADQ); | ||
676 | + thread = _ST_THREAD_THREADQ_PTR(q); | ||
677 | + if (thread == _ST_CURRENT_THREAD()) { | ||
678 | + MD_LONGJMP(orig_jb, 1); | ||
679 | + } | ||
680 | + memcpy(save_jb, thread->context, sizeof(jmp_buf)); | ||
681 | + MD_LONGJMP(thread->context, 1); | ||
670 | } | 682 | } |
671 | #endif /* DEBUG */ | 683 | #endif /* DEBUG */ |
672 | 684 |
-
请 注册 或 登录 后发表评论