winlin

Merge branch 'srs.master'

@@ -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