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