73 |
|
|
74 |
q->t.all_prev = NULL; |
q->t.all_prev = NULL; |
75 |
q->t.all_next = NULL; |
q->t.all_next = NULL; |
|
#ifdef GUILE_ISELECT |
|
76 |
q->t.nfds = 0; |
q->t.nfds = 0; |
77 |
q->t.readfds = NULL; |
q->t.readfds = NULL; |
78 |
q->t.writefds = NULL; |
q->t.writefds = NULL; |
79 |
q->t.exceptfds = NULL; |
q->t.exceptfds = NULL; |
80 |
q->t.timeoutp = 0; |
q->t.timeoutp = 0; |
|
#endif |
|
81 |
} |
} |
82 |
|
|
83 |
|
|
129 |
t->all_next->all_prev = t->all_prev; |
t->all_next->all_prev = t->all_prev; |
130 |
} |
} |
131 |
|
|
|
#ifdef GUILE_ISELECT |
|
132 |
/* Insert thread t into the ordered queue q. |
/* Insert thread t into the ordered queue q. |
133 |
q is ordered after wakeup_time. Threads which aren't sleeping but |
q is ordered after wakeup_time. Threads which aren't sleeping but |
134 |
waiting for I/O go last into the queue. */ |
waiting for I/O go last into the queue. */ |
149 |
if (t->next == &q->t) |
if (t->next == &q->t) |
150 |
q->tail = t; |
q->tail = t; |
151 |
} |
} |
|
#endif |
|
152 |
|
|
153 |
|
|
154 |
|
|
155 |
/* Thread routines. */ |
/* Thread routines. */ |
156 |
|
|
157 |
coop_q_t coop_global_runq; /* A queue of runable threads. */ |
coop_q_t coop_global_runq; /* A queue of runable threads. */ |
158 |
coop_q_t coop_global_sleepq; /* A queue of sleeping threads. */ |
coop_q_t coop_global_sleepq; /* A queue of sleeping threads. */ |
227 |
and there are sleeping threads - wait until one wakes up. Otherwise, |
and there are sleeping threads - wait until one wakes up. Otherwise, |
228 |
return NULL. */ |
return NULL. */ |
229 |
|
|
|
#ifndef GUILE_ISELECT |
|
230 |
coop_t * |
coop_t * |
231 |
coop_next_runnable_thread() |
coop_next_runnable_thread() |
232 |
{ |
{ |
256 |
|
|
257 |
return t; |
return t; |
258 |
} |
} |
|
#endif |
|
259 |
|
|
260 |
void |
void |
261 |
coop_start() |
coop_start() |
328 |
/* Record the current top-of-stack before going to sleep */ |
/* Record the current top-of-stack before going to sleep */ |
329 |
coop_global_curr->top = &old; |
coop_global_curr->top = &old; |
330 |
|
|
|
#ifdef GUILE_ISELECT |
|
331 |
newthread = coop_wait_for_runnable_thread(); |
newthread = coop_wait_for_runnable_thread(); |
332 |
if (newthread == coop_global_curr) |
if (newthread == coop_global_curr) |
333 |
coop_abort (); |
coop_abort (); |
|
#else |
|
|
newthread = coop_next_runnable_thread(); |
|
|
#endif |
|
334 |
old = coop_global_curr; |
old = coop_global_curr; |
335 |
coop_global_curr = newthread; |
coop_global_curr = newthread; |
336 |
QT_BLOCK (coop_yieldhelp, old, &(m->waiting), newthread->sp); |
QT_BLOCK (coop_yieldhelp, old, &(m->waiting), newthread->sp); |
408 |
{ |
{ |
409 |
m->owner = NULL; |
m->owner = NULL; |
410 |
/*fixme* Should we really wait here? Isn't it OK just to proceed? */ |
/*fixme* Should we really wait here? Isn't it OK just to proceed? */ |
|
#ifdef GUILE_ISELECT |
|
411 |
newthread = coop_wait_for_runnable_thread(); |
newthread = coop_wait_for_runnable_thread(); |
412 |
if (newthread == coop_global_curr) |
if (newthread == coop_global_curr) |
413 |
coop_abort (); |
coop_abort (); |
|
#else |
|
|
newthread = coop_next_runnable_thread(); |
|
|
#endif |
|
414 |
} |
} |
415 |
coop_global_curr->top = &old; |
coop_global_curr->top = &old; |
416 |
old = coop_global_curr; |
old = coop_global_curr; |
444 |
else |
else |
445 |
{ |
{ |
446 |
m->owner = NULL; |
m->owner = NULL; |
|
#ifdef GUILE_ISELECT |
|
447 |
coop_global_curr->timeoutp = 1; |
coop_global_curr->timeoutp = 1; |
448 |
coop_global_curr->wakeup_time.tv_sec = abstime->tv_sec; |
coop_global_curr->wakeup_time.tv_sec = abstime->tv_sec; |
449 |
coop_global_curr->wakeup_time.tv_usec = abstime->tv_nsec / 1000; |
coop_global_curr->wakeup_time.tv_usec = abstime->tv_nsec / 1000; |
450 |
coop_timeout_qinsert (&coop_global_sleepq, coop_global_curr); |
coop_timeout_qinsert (&coop_global_sleepq, coop_global_curr); |
451 |
t = coop_wait_for_runnable_thread(); |
t = coop_wait_for_runnable_thread(); |
|
#else |
|
|
/*fixme* Implement!*/ |
|
|
t = coop_next_runnable_thread(); |
|
|
#endif |
|
452 |
} |
} |
453 |
if (t != coop_global_curr) |
if (t != coop_global_curr) |
454 |
{ |
{ |
694 |
free (coop_global_curr->joining); |
free (coop_global_curr->joining); |
695 |
} |
} |
696 |
|
|
|
#ifdef GUILE_ISELECT |
|
697 |
scm_I_am_dead = 1; |
scm_I_am_dead = 1; |
698 |
do { |
do { |
699 |
newthread = coop_wait_for_runnable_thread(); |
newthread = coop_wait_for_runnable_thread(); |
700 |
} while (newthread == coop_global_curr); |
} while (newthread == coop_global_curr); |
701 |
scm_I_am_dead = 0; |
scm_I_am_dead = 0; |
|
#else |
|
|
newthread = coop_next_runnable_thread(); |
|
|
#endif |
|
702 |
coop_all_qremove (&coop_global_allq, coop_global_curr); |
coop_all_qremove (&coop_global_allq, coop_global_curr); |
703 |
old = coop_global_curr; |
old = coop_global_curr; |
704 |
coop_global_curr = newthread; |
coop_global_curr = newthread; |
736 |
coop_qinit((coop_q_t *) t->joining); |
coop_qinit((coop_q_t *) t->joining); |
737 |
} |
} |
738 |
|
|
|
#ifdef GUILE_ISELECT |
|
739 |
newthread = coop_wait_for_runnable_thread(); |
newthread = coop_wait_for_runnable_thread(); |
740 |
if (newthread == coop_global_curr) |
if (newthread == coop_global_curr) |
741 |
return; |
return; |
|
#else |
|
|
newthread = coop_next_runnable_thread(); |
|
|
#endif |
|
742 |
old = coop_global_curr; |
old = coop_global_curr; |
743 |
coop_global_curr = newthread; |
coop_global_curr = newthread; |
744 |
QT_BLOCK (coop_yieldhelp, old, (coop_q_t *) t->joining, newthread->sp); |
QT_BLOCK (coop_yieldhelp, old, (coop_q_t *) t->joining, newthread->sp); |
754 |
|
|
755 |
/* There may be no other runnable threads. Return if this is the |
/* There may be no other runnable threads. Return if this is the |
756 |
case. */ |
case. */ |
|
#if GUILE_ISELECT |
|
757 |
if (newthread == coop_global_curr) |
if (newthread == coop_global_curr) |
758 |
return; |
return; |
|
#else |
|
|
if (newthread == NULL) |
|
|
return; |
|
|
#endif |
|
759 |
|
|
760 |
old = coop_global_curr; |
old = coop_global_curr; |
761 |
|
|
784 |
return NULL; |
return NULL; |
785 |
} |
} |
786 |
|
|
|
#ifdef GUILE_ISELECT |
|
|
|
|
787 |
unsigned long |
unsigned long |
788 |
scm_thread_usleep (unsigned long usec) |
scm_thread_usleep (unsigned long usec) |
789 |
{ |
{ |
808 |
return slept > sec ? 0 : sec - slept; |
return slept > sec ? 0 : sec - slept; |
809 |
} |
} |
810 |
|
|
|
#else /* GUILE_ISELECT */ |
|
|
|
|
|
unsigned long |
|
|
scm_thread_sleep (unsigned long s) |
|
|
{ |
|
|
coop_t *newthread, *old; |
|
|
time_t now = time (NULL); |
|
|
coop_global_curr->wakeup_time = now + s; |
|
|
|
|
|
/* Put the current thread on the sleep queue */ |
|
|
coop_qput (&coop_global_sleepq, coop_global_curr); |
|
|
|
|
|
newthread = coop_next_runnable_thread(); |
|
|
|
|
|
/* If newthread is the same as the sleeping thread, do nothing */ |
|
|
if (newthread == coop_global_curr) |
|
|
return s; |
|
|
|
|
|
old = coop_global_curr; |
|
|
|
|
|
coop_global_curr = newthread; |
|
|
QT_BLOCK (coop_sleephelp, old, NULL, newthread->sp); |
|
|
|
|
|
return s; |
|
|
} |
|
|
|
|
|
unsigned long |
|
|
scm_thread_usleep (unsigned long usec) |
|
|
{ |
|
|
/* We're so cheap. */ |
|
|
scm_thread_sleep (usec / 1000000); |
|
|
return 0; /* Maybe we should calculate actual time slept, |
|
|
but this is faster... :) */ |
|
|
} |
|
|
|
|
|
#endif /* GUILE_ISELECT */ |
|
|
|
|
811 |
/* |
/* |
812 |
Local Variables: |
Local Variables: |
813 |
c-file-style: "gnu" |
c-file-style: "gnu" |