112027Sjungma@eit.uni-kl.de#include "copyright.h" 212027Sjungma@eit.uni-kl.de#include "qt.h" 312027Sjungma@eit.uni-kl.de#include "stp.h" 412027Sjungma@eit.uni-kl.de 512027Sjungma@eit.uni-kl.de#ifndef NULL 612027Sjungma@eit.uni-kl.de#define NULL 0 712027Sjungma@eit.uni-kl.de#endif 812027Sjungma@eit.uni-kl.de 912027Sjungma@eit.uni-kl.de#define STP_STKSIZE (0x1000) 1012027Sjungma@eit.uni-kl.de 1112027Sjungma@eit.uni-kl.de/* `alignment' must be a power of 2. */ 1212027Sjungma@eit.uni-kl.de#define STP_STKALIGN(sp, alignment) \ 1312027Sjungma@eit.uni-kl.de ((void *)((((qt_word_t)(sp)) + (alignment) - 1) & ~((alignment)-1))) 1412027Sjungma@eit.uni-kl.de 1512027Sjungma@eit.uni-kl.de 1612027Sjungma@eit.uni-kl.de/* The notion of a thread is merged with the notion of a queue. 1712027Sjungma@eit.uni-kl.de Thread stuff: thread status (sp) and stuff to use during 1812027Sjungma@eit.uni-kl.de (re)initialization. Queue stuff: next thread in the queue 1912027Sjungma@eit.uni-kl.de (next). */ 2012027Sjungma@eit.uni-kl.de 2112027Sjungma@eit.uni-kl.destruct stp_t { 2212027Sjungma@eit.uni-kl.de qt_t *sp; /* QuickThreads handle. */ 2312027Sjungma@eit.uni-kl.de void *sto; /* `malloc'-allocated stack. */ 2412027Sjungma@eit.uni-kl.de struct stp_t *next; /* Next thread in the queue. */ 2512027Sjungma@eit.uni-kl.de}; 2612027Sjungma@eit.uni-kl.de 2712027Sjungma@eit.uni-kl.de 2812027Sjungma@eit.uni-kl.de/* A queue is a circular list of threads. The queue head is a 2912027Sjungma@eit.uni-kl.de designated list element. If this is a uniprocessor-only 3012027Sjungma@eit.uni-kl.de implementation we can store the `main' thread in this, but in a 3112027Sjungma@eit.uni-kl.de multiprocessor there are several `heavy' threads but only one run 3212027Sjungma@eit.uni-kl.de queue. A fancier implementation might have private run queues, 3312027Sjungma@eit.uni-kl.de which would lead to a simpler (trivial) implementation */ 3412027Sjungma@eit.uni-kl.de 3512027Sjungma@eit.uni-kl.detypedef struct stp_q_t { 3612027Sjungma@eit.uni-kl.de stp_t t; 3712027Sjungma@eit.uni-kl.de stp_t *tail; 3812027Sjungma@eit.uni-kl.de} stp_q_t; 3912027Sjungma@eit.uni-kl.de 4012027Sjungma@eit.uni-kl.de 4112027Sjungma@eit.uni-kl.de/* Helper functions. */ 4212027Sjungma@eit.uni-kl.de 4312027Sjungma@eit.uni-kl.deextern void *malloc (unsigned size); 4412027Sjungma@eit.uni-kl.deextern void perror (char const *msg); 4512027Sjungma@eit.uni-kl.deextern void free (void *sto); 4612027Sjungma@eit.uni-kl.de 4712027Sjungma@eit.uni-kl.de void * 4812027Sjungma@eit.uni-kl.dexmalloc (unsigned size) 4912027Sjungma@eit.uni-kl.de{ 5012027Sjungma@eit.uni-kl.de void *sto; 5112027Sjungma@eit.uni-kl.de 5212027Sjungma@eit.uni-kl.de sto = malloc (size); 5312027Sjungma@eit.uni-kl.de if (!sto) { 5412027Sjungma@eit.uni-kl.de perror ("malloc"); 5512027Sjungma@eit.uni-kl.de exit (1); 5612027Sjungma@eit.uni-kl.de } 5712027Sjungma@eit.uni-kl.de return (sto); 5812027Sjungma@eit.uni-kl.de} 5912027Sjungma@eit.uni-kl.de 6012027Sjungma@eit.uni-kl.de/* Queue access functions. */ 6112027Sjungma@eit.uni-kl.de 6212027Sjungma@eit.uni-kl.de static void 6312027Sjungma@eit.uni-kl.destp_qinit (stp_q_t *q) 6412027Sjungma@eit.uni-kl.de{ 6512027Sjungma@eit.uni-kl.de q->t.next = q->tail = &q->t; 6612027Sjungma@eit.uni-kl.de} 6712027Sjungma@eit.uni-kl.de 6812027Sjungma@eit.uni-kl.de 6912027Sjungma@eit.uni-kl.de static stp_t * 7012027Sjungma@eit.uni-kl.destp_qget (stp_q_t *q) 7112027Sjungma@eit.uni-kl.de{ 7212027Sjungma@eit.uni-kl.de stp_t *t; 7312027Sjungma@eit.uni-kl.de 7412027Sjungma@eit.uni-kl.de t = q->t.next; 7512027Sjungma@eit.uni-kl.de q->t.next = t->next; 7612027Sjungma@eit.uni-kl.de if (t->next == &q->t) { 7712027Sjungma@eit.uni-kl.de if (t == &q->t) { /* If it was already empty .. */ 7812027Sjungma@eit.uni-kl.de return (NULL); /* .. say so. */ 7912027Sjungma@eit.uni-kl.de } 8012027Sjungma@eit.uni-kl.de q->tail = &q->t; /* Else now it is empty. */ 8112027Sjungma@eit.uni-kl.de } 8212027Sjungma@eit.uni-kl.de return (t); 8312027Sjungma@eit.uni-kl.de} 8412027Sjungma@eit.uni-kl.de 8512027Sjungma@eit.uni-kl.de 8612027Sjungma@eit.uni-kl.de static void 8712027Sjungma@eit.uni-kl.destp_qput (stp_q_t *q, stp_t *t) 8812027Sjungma@eit.uni-kl.de{ 8912027Sjungma@eit.uni-kl.de q->tail->next = t; 9012027Sjungma@eit.uni-kl.de t->next = &q->t; 9112027Sjungma@eit.uni-kl.de q->tail = t; 9212027Sjungma@eit.uni-kl.de} 9312027Sjungma@eit.uni-kl.de 9412027Sjungma@eit.uni-kl.de 9512027Sjungma@eit.uni-kl.de/* Thread routines. */ 9612027Sjungma@eit.uni-kl.de 9712027Sjungma@eit.uni-kl.destatic stp_q_t stp_global_runq; /* A queue of runable threads. */ 9812027Sjungma@eit.uni-kl.destatic stp_t stp_global_main; /* Thread for the process. */ 9912027Sjungma@eit.uni-kl.destatic stp_t *stp_global_curr; /* Currently-executing thread. */ 10012027Sjungma@eit.uni-kl.de 10112027Sjungma@eit.uni-kl.destatic void *stp_starthelp (qt_t *old, void *ignore0, void *ignore1); 10212027Sjungma@eit.uni-kl.destatic void stp_only (void *pu, void *pt, qt_userf_t *f); 10312027Sjungma@eit.uni-kl.destatic void *stp_aborthelp (qt_t *sp, void *old, void *null); 10412027Sjungma@eit.uni-kl.destatic void *stp_yieldhelp (qt_t *sp, void *old, void *blockq); 10512027Sjungma@eit.uni-kl.de 10612027Sjungma@eit.uni-kl.de 10712027Sjungma@eit.uni-kl.de void 10812027Sjungma@eit.uni-kl.destp_init() 10912027Sjungma@eit.uni-kl.de{ 11012027Sjungma@eit.uni-kl.de stp_qinit (&stp_global_runq); 11112027Sjungma@eit.uni-kl.de} 11212027Sjungma@eit.uni-kl.de 11312027Sjungma@eit.uni-kl.de 11412027Sjungma@eit.uni-kl.de void 11512027Sjungma@eit.uni-kl.destp_start() 11612027Sjungma@eit.uni-kl.de{ 11712027Sjungma@eit.uni-kl.de stp_t *next; 11812027Sjungma@eit.uni-kl.de 11912027Sjungma@eit.uni-kl.de while ((next = stp_qget (&stp_global_runq)) != NULL) { 12012027Sjungma@eit.uni-kl.de stp_global_curr = next; 12112027Sjungma@eit.uni-kl.de QT_BLOCK (stp_starthelp, 0, 0, next->sp); 12212027Sjungma@eit.uni-kl.de } 12312027Sjungma@eit.uni-kl.de} 12412027Sjungma@eit.uni-kl.de 12512027Sjungma@eit.uni-kl.de 12612027Sjungma@eit.uni-kl.de static void * 12712027Sjungma@eit.uni-kl.destp_starthelp (qt_t *old, void *ignore0, void *ignore1) 12812027Sjungma@eit.uni-kl.de{ 12912027Sjungma@eit.uni-kl.de stp_global_main.sp = old; 13012027Sjungma@eit.uni-kl.de stp_qput (&stp_global_runq, &stp_global_main); 13112027Sjungma@eit.uni-kl.de /* return (garbage); */ 13212027Sjungma@eit.uni-kl.de} 13312027Sjungma@eit.uni-kl.de 13412027Sjungma@eit.uni-kl.de 13512027Sjungma@eit.uni-kl.de void 13612027Sjungma@eit.uni-kl.destp_create (stp_userf_t *f, void *pu) 13712027Sjungma@eit.uni-kl.de{ 13812027Sjungma@eit.uni-kl.de stp_t *t; 13912027Sjungma@eit.uni-kl.de void *sto; 14012027Sjungma@eit.uni-kl.de 14112027Sjungma@eit.uni-kl.de t = xmalloc (sizeof(stp_t)); 14212027Sjungma@eit.uni-kl.de t->sto = xmalloc (STP_STKSIZE); 14312027Sjungma@eit.uni-kl.de sto = STP_STKALIGN (t->sto, QT_STKALIGN); 14412027Sjungma@eit.uni-kl.de t->sp = QT_SP (sto, STP_STKSIZE - QT_STKALIGN); 14512027Sjungma@eit.uni-kl.de t->sp = QT_ARGS (t->sp, pu, t, (qt_userf_t *)f, stp_only); 14612027Sjungma@eit.uni-kl.de stp_qput (&stp_global_runq, t); 14712027Sjungma@eit.uni-kl.de} 14812027Sjungma@eit.uni-kl.de 14912027Sjungma@eit.uni-kl.de 15012027Sjungma@eit.uni-kl.de static void 15112027Sjungma@eit.uni-kl.destp_only (void *pu, void *pt, qt_userf_t *f) 15212027Sjungma@eit.uni-kl.de{ 15312027Sjungma@eit.uni-kl.de stp_global_curr = (stp_t *)pt; 15412027Sjungma@eit.uni-kl.de (*(stp_userf_t *)f)(pu); 15512027Sjungma@eit.uni-kl.de stp_abort(); 15612027Sjungma@eit.uni-kl.de /* NOTREACHED */ 15712027Sjungma@eit.uni-kl.de} 15812027Sjungma@eit.uni-kl.de 15912027Sjungma@eit.uni-kl.de 16012027Sjungma@eit.uni-kl.de void 16112027Sjungma@eit.uni-kl.destp_abort (void) 16212027Sjungma@eit.uni-kl.de{ 16312027Sjungma@eit.uni-kl.de stp_t *old, *newthread; 16412027Sjungma@eit.uni-kl.de 16512027Sjungma@eit.uni-kl.de newthread = stp_qget (&stp_global_runq); 16612027Sjungma@eit.uni-kl.de old = stp_global_curr; 16712027Sjungma@eit.uni-kl.de stp_global_curr = newthread; 16812027Sjungma@eit.uni-kl.de QT_ABORT (stp_aborthelp, old, (void *)NULL, newthread->sp); 16912027Sjungma@eit.uni-kl.de} 17012027Sjungma@eit.uni-kl.de 17112027Sjungma@eit.uni-kl.de 17212027Sjungma@eit.uni-kl.de static void * 17312027Sjungma@eit.uni-kl.destp_aborthelp (qt_t *sp, void *old, void *null) 17412027Sjungma@eit.uni-kl.de{ 17512027Sjungma@eit.uni-kl.de free (((stp_t *)old)->sto); 17612027Sjungma@eit.uni-kl.de free (old); 17712027Sjungma@eit.uni-kl.de /* return (garbage); */ 17812027Sjungma@eit.uni-kl.de} 17912027Sjungma@eit.uni-kl.de 18012027Sjungma@eit.uni-kl.de 18112027Sjungma@eit.uni-kl.de void 18212027Sjungma@eit.uni-kl.destp_yield() 18312027Sjungma@eit.uni-kl.de{ 18412027Sjungma@eit.uni-kl.de stp_t *old, *newthread; 18512027Sjungma@eit.uni-kl.de 18612027Sjungma@eit.uni-kl.de newthread = stp_qget (&stp_global_runq); 18712027Sjungma@eit.uni-kl.de old = stp_global_curr; 18812027Sjungma@eit.uni-kl.de stp_global_curr = newthread; 18912027Sjungma@eit.uni-kl.de QT_BLOCK (stp_yieldhelp, old, &stp_global_runq, newthread->sp); 19012027Sjungma@eit.uni-kl.de} 19112027Sjungma@eit.uni-kl.de 19212027Sjungma@eit.uni-kl.de 19312027Sjungma@eit.uni-kl.de static void * 19412027Sjungma@eit.uni-kl.destp_yieldhelp (qt_t *sp, void *old, void *blockq) 19512027Sjungma@eit.uni-kl.de{ 19612027Sjungma@eit.uni-kl.de ((stp_t *)old)->sp = sp; 19712027Sjungma@eit.uni-kl.de stp_qput ((stp_q_t *)blockq, (stp_t *)old); 19812027Sjungma@eit.uni-kl.de /* return (garbage); */ 19912027Sjungma@eit.uni-kl.de} 200