00001 #include "copyright.h"
00002 #include "qt.h"
00003 #include "stp.h"
00004
00005 #ifndef NULL
00006 #define NULL 0
00007 #endif
00008
00009 #define STP_STKSIZE (0x1000)
00010
00011
00012 #define STP_STKALIGN(sp, alignment) \
00013 ((void *)((((qt_word_t)(sp)) + (alignment) - 1) & ~((alignment)-1)))
00014
00015
00016
00017
00018
00019
00020
00021 struct stp_t {
00022 qt_t *sp;
00023 void *sto;
00024 struct stp_t *next;
00025 };
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 typedef struct stp_q_t {
00036 stp_t t;
00037 stp_t *tail;
00038 } stp_q_t;
00039
00040
00041
00042
00043 extern void *malloc (unsigned size);
00044 extern void perror (char const *msg);
00045 extern void free (void *sto);
00046
00047 void *
00048 xmalloc (unsigned size)
00049 {
00050 void *sto;
00051
00052 sto = malloc (size);
00053 if (!sto) {
00054 perror ("malloc");
00055 exit (1);
00056 }
00057 return (sto);
00058 }
00059
00060
00061
00062 static void
00063 stp_qinit (stp_q_t *q)
00064 {
00065 q->t.next = q->tail = &q->t;
00066 }
00067
00068
00069 static stp_t *
00070 stp_qget (stp_q_t *q)
00071 {
00072 stp_t *t;
00073
00074 t = q->t.next;
00075 q->t.next = t->next;
00076 if (t->next == &q->t) {
00077 if (t == &q->t) {
00078 return (NULL);
00079 }
00080 q->tail = &q->t;
00081 }
00082 return (t);
00083 }
00084
00085
00086 static void
00087 stp_qput (stp_q_t *q, stp_t *t)
00088 {
00089 q->tail->next = t;
00090 t->next = &q->t;
00091 q->tail = t;
00092 }
00093
00094
00095
00096
00097 static stp_q_t stp_global_runq;
00098 static stp_t stp_global_main;
00099 static stp_t *stp_global_curr;
00100
00101 static void *stp_starthelp (qt_t *old, void *ignore0, void *ignore1);
00102 static void stp_only (void *pu, void *pt, qt_userf_t *f);
00103 static void *stp_aborthelp (qt_t *sp, void *old, void *null);
00104 static void *stp_yieldhelp (qt_t *sp, void *old, void *blockq);
00105
00106
00107 void
00108 stp_init()
00109 {
00110 stp_qinit (&stp_global_runq);
00111 }
00112
00113
00114 void
00115 stp_start()
00116 {
00117 stp_t *next;
00118
00119 while ((next = stp_qget (&stp_global_runq)) != NULL) {
00120 stp_global_curr = next;
00121 QT_BLOCK (stp_starthelp, 0, 0, next->sp);
00122 }
00123 }
00124
00125
00126 static void *
00127 stp_starthelp (qt_t *old, void *ignore0, void *ignore1)
00128 {
00129 stp_global_main.sp = old;
00130 stp_qput (&stp_global_runq, &stp_global_main);
00131
00132 }
00133
00134
00135 void
00136 stp_create (stp_userf_t *f, void *pu)
00137 {
00138 stp_t *t;
00139 void *sto;
00140
00141 t = xmalloc (sizeof(stp_t));
00142 t->sto = xmalloc (STP_STKSIZE);
00143 sto = STP_STKALIGN (t->sto, QT_STKALIGN);
00144 t->sp = QT_SP (sto, STP_STKSIZE - QT_STKALIGN);
00145 t->sp = QT_ARGS (t->sp, pu, t, (qt_userf_t *)f, stp_only);
00146 stp_qput (&stp_global_runq, t);
00147 }
00148
00149
00150 static void
00151 stp_only (void *pu, void *pt, qt_userf_t *f)
00152 {
00153 stp_global_curr = (stp_t *)pt;
00154 (*(stp_userf_t *)f)(pu);
00155 stp_abort();
00156
00157 }
00158
00159
00160 void
00161 stp_abort (void)
00162 {
00163 stp_t *old, *newthread;
00164
00165 newthread = stp_qget (&stp_global_runq);
00166 old = stp_global_curr;
00167 stp_global_curr = newthread;
00168 QT_ABORT (stp_aborthelp, old, (void *)NULL, newthread->sp);
00169 }
00170
00171
00172 static void *
00173 stp_aborthelp (qt_t *sp, void *old, void *null)
00174 {
00175 free (((stp_t *)old)->sto);
00176 free (old);
00177
00178 }
00179
00180
00181 void
00182 stp_yield()
00183 {
00184 stp_t *old, *newthread;
00185
00186 newthread = stp_qget (&stp_global_runq);
00187 old = stp_global_curr;
00188 stp_global_curr = newthread;
00189 QT_BLOCK (stp_yieldhelp, old, &stp_global_runq, newthread->sp);
00190 }
00191
00192
00193 static void *
00194 stp_yieldhelp (qt_t *sp, void *old, void *blockq)
00195 {
00196 ((stp_t *)old)->sp = sp;
00197 stp_qput ((stp_q_t *)blockq, (stp_t *)old);
00198
00199 }