9 #define STP_STKSIZE (0x1000)
11 /* `alignment' must be a power of 2. */
12 #define STP_STKALIGN(sp, alignment) \
13 ((void *)((((qt_word_t)(sp)) + (alignment) - 1) & ~((alignment)-1)))
16 /* The notion of a thread is merged with the notion of a queue.
17 Thread stuff: thread status (sp) and stuff to use during
18 (re)initialization. Queue stuff: next thread in the queue
22 qt_t
*sp
; /* QuickThreads handle. */
23 void *sto
; /* `malloc'-allocated stack. */
24 struct stp_t
*next
; /* Next thread in the queue. */
28 /* A queue is a circular list of threads. The queue head is a
29 designated list element. If this is a uniprocessor-only
30 implementation we can store the `main' thread in this, but in a
31 multiprocessor there are several `heavy' threads but only one run
32 queue. A fancier implementation might have private run queues,
33 which would lead to a simpler (trivial) implementation */
35 typedef struct stp_q_t
{
41 \f/* Helper functions. */
43 extern void *malloc (unsigned size
);
44 extern void perror (char const *msg
);
45 extern void free (void *sto
);
48 xmalloc (unsigned size
)
60 \f/* Queue access functions. */
63 stp_qinit (stp_q_t
*q
)
65 q
->t
.next
= q
->tail
= &q
->t
;
76 if (t
->next
== &q
->t
) {
77 if (t
== &q
->t
) { /* If it was already empty .. */
78 return (NULL
); /* .. say so. */
80 q
->tail
= &q
->t
; /* Else now it is empty. */
87 stp_qput (stp_q_t
*q
, stp_t
*t
)
95 \f/* Thread routines. */
97 static stp_q_t stp_global_runq
; /* A queue of runable threads. */
98 static stp_t stp_global_main
; /* Thread for the process. */
99 static stp_t
*stp_global_curr
; /* Currently-executing thread. */
101 static void *stp_starthelp (qt_t
*old
, void *ignore0
, void *ignore1
);
102 static void stp_only (void *pu
, void *pt
, qt_userf_t
*f
);
103 static void *stp_aborthelp (qt_t
*sp
, void *old
, void *null
);
104 static void *stp_yieldhelp (qt_t
*sp
, void *old
, void *blockq
);
110 stp_qinit (&stp_global_runq
);
119 while ((next
= stp_qget (&stp_global_runq
)) != NULL
) {
120 stp_global_curr
= next
;
121 QT_BLOCK (stp_starthelp
, 0, 0, next
->sp
);
127 stp_starthelp (qt_t
*old
, void *ignore0
, void *ignore1
)
129 stp_global_main
.sp
= old
;
130 stp_qput (&stp_global_runq
, &stp_global_main
);
131 /* return (garbage); */
136 stp_create (stp_userf_t
*f
, void *pu
)
141 t
= xmalloc (sizeof(stp_t
));
142 t
->sto
= xmalloc (STP_STKSIZE
);
143 sto
= STP_STKALIGN (t
->sto
, QT_STKALIGN
);
144 t
->sp
= QT_SP (sto
, STP_STKSIZE
- QT_STKALIGN
);
145 t
->sp
= QT_ARGS (t
->sp
, pu
, t
, (qt_userf_t
*)f
, stp_only
);
146 stp_qput (&stp_global_runq
, t
);
151 stp_only (void *pu
, void *pt
, qt_userf_t
*f
)
153 stp_global_curr
= (stp_t
*)pt
;
154 (*(stp_userf_t
*)f
)(pu
);
163 stp_t
*old
, *newthread
;
165 newthread
= stp_qget (&stp_global_runq
);
166 old
= stp_global_curr
;
167 stp_global_curr
= newthread
;
168 QT_ABORT (stp_aborthelp
, old
, (void *)NULL
, newthread
->sp
);
173 stp_aborthelp (qt_t
*sp
, void *old
, void *null
)
175 free (((stp_t
*)old
)->sto
);
177 /* return (garbage); */
184 stp_t
*old
, *newthread
;
186 newthread
= stp_qget (&stp_global_runq
);
187 old
= stp_global_curr
;
188 stp_global_curr
= newthread
;
189 QT_BLOCK (stp_yieldhelp
, old
, &stp_global_runq
, newthread
->sp
);
194 stp_yieldhelp (qt_t
*sp
, void *old
, void *blockq
)
196 ((stp_t
*)old
)->sp
= sp
;
197 stp_qput ((stp_q_t
*)blockq
, (stp_t
*)old
);
198 /* return (garbage); */