Initial revision
[cacao.git] / threads / notyet.c
1 /* ------------------------ thread.c -------------------------- */
2
3 /*
4  * Put a thread to sleep.
5  */
6 void
7 sleepThread(int64 time)
8 {
9     thread** tidp;
10
11     /* Sleep for no time */
12     if (time == 0) {
13         return;
14     }
15     
16     intsDisable();
17
18     /* Get absolute time */
19     currentThread->PrivateInfo->time = time + currentTime();
20
21     /* Find place in alarm list */
22     for (tidp = &alarmList; (*tidp) != 0; tidp = &(*tidp)->next) {
23         if ((*tidp)->PrivateInfo->time > currentThread->PrivateInfo->time) {
24             break;
25         }
26     }
27
28     /* If I'm head of alarm list, restart alarm */
29     if (tidp == &alarmList) {
30         MALARM(time);
31     }
32     
33     /* Suspend thread on it */
34     suspendOnQThread(currentThread, tidp);
35     
36     intsRestore();
37 }
38
39 /*
40  * Handle alarm.
41  * This routine uses a different meaning of "blockInts". Formerly, it was just
42  * "don't reschedule if you don't have to". Now it is "don't do ANY
43  * rescheduling actions due to an expired timer". An alternative would be to
44  * block SIGALARM during critical sections (by means of sigprocmask). But
45  * this would be required quite often (for every outmost intsDisable(),
46  * intsRestore()) and therefore would be much more expensive than just
47  * setting an int flag which - sometimes - might cause an additional
48  * setitimer call.
49  */
50 static
51 void
52 alarmException(int sig)
53 {
54     thread* tid;
55     int64 time;
56
57     /* Re-enable signal - necessary for SysV */
58     signal(sig, (SIG_T)alarmException);
59
60     /*
61      * If ints are blocked, this might indicate an inconsistent state of
62      * one of the thread queues (either alarmList or threadQhead/tail).
63      * We better don't touch one of them in this case and come back later.
64      */
65     if (blockInts > 0) {
66         MALARM(50);
67         return;
68     }
69
70     intsDisable();
71
72     /* Wake all the threads which need waking */
73     time = currentTime();
74     while (alarmList != 0 && alarmList->PrivateInfo->time <= time) {
75         tid = alarmList;
76         alarmList = alarmList->next;
77         iresumeThread(tid);
78     }
79
80     /* Restart alarm */
81     if (alarmList != 0) {
82         MALARM(alarmList->PrivateInfo->time - time);
83     }
84
85     /*
86      * The next bit is rather tricky.  If we don't reschedule then things
87      * are fine, we exit this handler and everything continues correctly.
88      * On the otherhand, if we do reschedule, we will schedule the new
89      * thread with alarms blocked which is wrong.  However, we cannot
90      * unblock them here incase we have just set an alarm which goes
91      * off before the reschedule takes place (and we enter this routine
92      * recusively which isn't good).  So, we set a flag indicating alarms
93      * are blocked, and allow the rescheduler to unblock the alarm signal
94      * after the context switch has been made.  At this point it's safe.
95      */
96     alarmBlocked = true;
97     intsRestore();
98     alarmBlocked = false;
99 }
100
101 /*
102  * How many stack frames have I invoked?
103  */
104 long
105 framesThread(thread* tid)
106 {
107     long count;
108     THREADFRAMES(tid, count);
109     return (count);
110 }