📄 stp.c
字号:
#include "copyright.h"#include "qt.h"#include "stp.h"#ifndef NULL#define NULL 0#endif#define STP_STKSIZE (0x1000)/* `alignment' must be a power of 2. */#define STP_STKALIGN(sp, alignment) \ ((void *)((((qt_word_t)(sp)) + (alignment) - 1) & ~((alignment)-1)))/* The notion of a thread is merged with the notion of a queue. Thread stuff: thread status (sp) and stuff to use during (re)initialization. Queue stuff: next thread in the queue (next). */struct stp_t { qt_t *sp; /* QuickThreads handle. */ void *sto; /* `malloc'-allocated stack. */ struct stp_t *next; /* Next thread in the queue. */};/* A queue is a circular list of threads. The queue head is a designated list element. If this is a uniprocessor-only implementation we can store the `main' thread in this, but in a multiprocessor there are several `heavy' threads but only one run queue. A fancier implementation might have private run queues, which would lead to a simpler (trivial) implementation */typedef struct stp_q_t { stp_t t; stp_t *tail;} stp_q_t;/* Helper functions. */extern void *malloc (unsigned size);extern void perror (char const *msg);extern void free (void *sto); void *xmalloc (unsigned size){ void *sto; sto = malloc (size); if (!sto) { perror ("malloc"); exit (1); } return (sto);}/* Queue access functions. */ static voidstp_qinit (stp_q_t *q){ q->t.next = q->tail = &q->t;} static stp_t *stp_qget (stp_q_t *q){ stp_t *t; t = q->t.next; q->t.next = t->next; if (t->next == &q->t) { if (t == &q->t) { /* If it was already empty .. */ return (NULL); /* .. say so. */ } q->tail = &q->t; /* Else now it is empty. */ } return (t);} static voidstp_qput (stp_q_t *q, stp_t *t){ q->tail->next = t; t->next = &q->t; q->tail = t;}/* Thread routines. */static stp_q_t stp_global_runq; /* A queue of runable threads. */static stp_t stp_global_main; /* Thread for the process. */static stp_t *stp_global_curr; /* Currently-executing thread. */static void *stp_starthelp (qt_t *old, void *ignore0, void *ignore1);static void stp_only (void *pu, void *pt, qt_userf_t *f);static void *stp_aborthelp (qt_t *sp, void *old, void *null);static void *stp_yieldhelp (qt_t *sp, void *old, void *blockq); voidstp_init(){ stp_qinit (&stp_global_runq);} voidstp_start(){ stp_t *next; while ((next = stp_qget (&stp_global_runq)) != NULL) { stp_global_curr = next; QT_BLOCK (stp_starthelp, 0, 0, next->sp); }} static void *stp_starthelp (qt_t *old, void *ignore0, void *ignore1){ stp_global_main.sp = old; stp_qput (&stp_global_runq, &stp_global_main); /* return (garbage); */} voidstp_create (stp_userf_t *f, void *pu){ stp_t *t; void *sto; t = xmalloc (sizeof(stp_t)); t->sto = xmalloc (STP_STKSIZE); sto = STP_STKALIGN (t->sto, QT_STKALIGN); t->sp = QT_SP (sto, STP_STKSIZE - QT_STKALIGN); t->sp = QT_ARGS (t->sp, pu, t, (qt_userf_t *)f, stp_only); stp_qput (&stp_global_runq, t);} static voidstp_only (void *pu, void *pt, qt_userf_t *f){ stp_global_curr = (stp_t *)pt; (*(stp_userf_t *)f)(pu); stp_abort(); /* NOTREACHED */} voidstp_abort (void){ stp_t *old, *newthread; newthread = stp_qget (&stp_global_runq); old = stp_global_curr; stp_global_curr = newthread; QT_ABORT (stp_aborthelp, old, (void *)NULL, newthread->sp);} static void *stp_aborthelp (qt_t *sp, void *old, void *null){ free (((stp_t *)old)->sto); free (old); /* return (garbage); */} voidstp_yield(){ stp_t *old, *newthread; newthread = stp_qget (&stp_global_runq); old = stp_global_curr; stp_global_curr = newthread; QT_BLOCK (stp_yieldhelp, old, &stp_global_runq, newthread->sp);} static void *stp_yieldhelp (qt_t *sp, void *old, void *blockq){ ((stp_t *)old)->sp = sp; stp_qput ((stp_q_t *)blockq, (stp_t *)old); /* return (garbage); */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -