112027Sjungma@eit.uni-kl.de/*
212027Sjungma@eit.uni-kl.de * QuickThreads -- Threads-building toolkit.
312027Sjungma@eit.uni-kl.de * Copyright (c) 1993 by David Keppel
412027Sjungma@eit.uni-kl.de *
512027Sjungma@eit.uni-kl.de * Permission to use, copy, modify and distribute this software and
612027Sjungma@eit.uni-kl.de * its documentation for any purpose and without fee is hereby
712027Sjungma@eit.uni-kl.de * granted, provided that the above copyright notice and this notice
812027Sjungma@eit.uni-kl.de * appear in all copies.  This software is provided as a
912027Sjungma@eit.uni-kl.de * proof-of-concept and for demonstration purposes; there is no
1012027Sjungma@eit.uni-kl.de * representation about the suitability of this software for any
1112027Sjungma@eit.uni-kl.de * purpose.
1212027Sjungma@eit.uni-kl.de */
1312027Sjungma@eit.uni-kl.de
1412027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_QT_H
1512027Sjungma@eit.uni-kl.de#define QUICKTHREADS_QT_H
1612027Sjungma@eit.uni-kl.de
1712027Sjungma@eit.uni-kl.de#if !defined(SC_USE_PTHREADS)
1812027Sjungma@eit.uni-kl.de
1912027Sjungma@eit.uni-kl.de#ifdef __cplusplus
2012027Sjungma@eit.uni-kl.deextern "C" {
2112027Sjungma@eit.uni-kl.de#endif
2212027Sjungma@eit.uni-kl.de
2312027Sjungma@eit.uni-kl.de#include <sysc/qt/qtmd.h>
2412027Sjungma@eit.uni-kl.de
2512027Sjungma@eit.uni-kl.de
2612027Sjungma@eit.uni-kl.de/* A QuickThreads thread is represented by it's current stack pointer.
2712027Sjungma@eit.uni-kl.de   To restart a thread, you merely need pass the current sp (qt_t*) to
2812027Sjungma@eit.uni-kl.de   a QuickThreads primitive.  `qt_t*' is a location on the stack.  To
2912027Sjungma@eit.uni-kl.de   improve type checking, represent it by a particular struct. */
3012027Sjungma@eit.uni-kl.de
3112027Sjungma@eit.uni-kl.detypedef struct qt_t {
3212027Sjungma@eit.uni-kl.de  char dummy;
3312027Sjungma@eit.uni-kl.de} qt_t;
3412027Sjungma@eit.uni-kl.de
3512027Sjungma@eit.uni-kl.de
3612027Sjungma@eit.uni-kl.de/* Alignment is guaranteed to be a power of two. */
3712027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_STKALIGN
3812027Sjungma@eit.uni-kl.de  #error "Need to know the machine-dependent stack alignment."
3912027Sjungma@eit.uni-kl.de#endif
4012027Sjungma@eit.uni-kl.de
4112027Sjungma@eit.uni-kl.de#define QUICKTHREADS_STKROUNDUP(bytes) \
4212027Sjungma@eit.uni-kl.de  (((bytes)+QUICKTHREADS_STKALIGN) & ~(QUICKTHREADS_STKALIGN-1))
4312027Sjungma@eit.uni-kl.de
4412027Sjungma@eit.uni-kl.de
4512027Sjungma@eit.uni-kl.de/* Find ``top'' of the stack, space on the stack. */
4612027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_SP
4712027Sjungma@eit.uni-kl.de#ifdef QUICKTHREADS_GROW_DOWN
4812027Sjungma@eit.uni-kl.de#define QUICKTHREADS_SP(sto, size)	((qt_t *)(&((char *)(sto))[(size)]))
4912027Sjungma@eit.uni-kl.de#endif
5012027Sjungma@eit.uni-kl.de#ifdef QUICKTHREADS_GROW_UP
5112027Sjungma@eit.uni-kl.de#define QUICKTHREADS_SP(sto, size)	((qt_t *)(sto))
5212027Sjungma@eit.uni-kl.de#endif
5312027Sjungma@eit.uni-kl.de#if !defined(QUICKTHREADS_SP)
5412027Sjungma@eit.uni-kl.de  #error "QUICKTHREADS_QT_H: Stack must grow up or down!"
5512027Sjungma@eit.uni-kl.de#endif
5612027Sjungma@eit.uni-kl.de#endif
5712027Sjungma@eit.uni-kl.de
5812027Sjungma@eit.uni-kl.de
5912027Sjungma@eit.uni-kl.de/* The type of the user function:
6012027Sjungma@eit.uni-kl.de   For non-varargs, takes one void* function.
6112027Sjungma@eit.uni-kl.de   For varargs, takes some number of arguments. */
6212027Sjungma@eit.uni-kl.detypedef void *(qt_userf_t)(void *pu);
6312027Sjungma@eit.uni-kl.detypedef void *(qt_vuserf_t)(int arg0, ...);
6412027Sjungma@eit.uni-kl.de
6512027Sjungma@eit.uni-kl.de/* For non-varargs, just call a client-supplied function,
6612027Sjungma@eit.uni-kl.de   it does all startup and cleanup, and also calls the user's
6712027Sjungma@eit.uni-kl.de   function. */
6812027Sjungma@eit.uni-kl.detypedef void (qt_only_t)(void *pu, void *pt, qt_userf_t *userf);
6912027Sjungma@eit.uni-kl.de
7012027Sjungma@eit.uni-kl.de/* For varargs, call `startup', then call the user's function,
7112027Sjungma@eit.uni-kl.de   then call `cleanup'. */
7212027Sjungma@eit.uni-kl.detypedef void (qt_startup_t)(void *pt);
7312027Sjungma@eit.uni-kl.detypedef void (qt_cleanup_t)(void *pt, void *vuserf_return);
7412027Sjungma@eit.uni-kl.de
7512027Sjungma@eit.uni-kl.de
7612027Sjungma@eit.uni-kl.de/* Internal helper for putting stuff on stack. */
7712027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_SPUT
7812027Sjungma@eit.uni-kl.de#define QUICKTHREADS_SPUT(top, at, val)	\
7912027Sjungma@eit.uni-kl.de    (((qt_word_t *)(top))[(at)] = (qt_word_t)(val))
8012027Sjungma@eit.uni-kl.de#endif
8112027Sjungma@eit.uni-kl.de
8212027Sjungma@eit.uni-kl.de
8312027Sjungma@eit.uni-kl.de/* Push arguments for the non-varargs case. */
8412027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_ARGS
8512027Sjungma@eit.uni-kl.de
8612027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_ARGS_MD
8712027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ARGS_MD (0)
8812027Sjungma@eit.uni-kl.de#endif
8912027Sjungma@eit.uni-kl.de
9012027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_STKBASE
9112027Sjungma@eit.uni-kl.de  #error "Need to know the machine-dependent stack allocation."
9212027Sjungma@eit.uni-kl.de#endif
9312027Sjungma@eit.uni-kl.de
9412027Sjungma@eit.uni-kl.de/* All things are put on the stack relative to the final value of
9512027Sjungma@eit.uni-kl.de   the stack pointer. */
9612027Sjungma@eit.uni-kl.de#ifdef QUICKTHREADS_GROW_DOWN
9712027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ADJ(sp)	(((char *)sp) - QUICKTHREADS_STKBASE)
9812027Sjungma@eit.uni-kl.de#else
9912027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ADJ(sp)	(((char *)sp) + QUICKTHREADS_STKBASE)
10012027Sjungma@eit.uni-kl.de#endif
10112027Sjungma@eit.uni-kl.de
10212027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ARGS(sp, pu, pt, userf, only) \
10312027Sjungma@eit.uni-kl.de    (QUICKTHREADS_ARGS_MD (QUICKTHREADS_ADJ(sp)), \
10412027Sjungma@eit.uni-kl.de     QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ONLY_INDEX, only), \
10512027Sjungma@eit.uni-kl.de     QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_USER_INDEX, userf), \
10612027Sjungma@eit.uni-kl.de     QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGT_INDEX, pt), \
10712027Sjungma@eit.uni-kl.de     QUICKTHREADS_SPUT (QUICKTHREADS_ADJ(sp), QUICKTHREADS_ARGU_INDEX, pu), \
10812027Sjungma@eit.uni-kl.de     ((qt_t *)QUICKTHREADS_ADJ(sp)))
10912027Sjungma@eit.uni-kl.de
11012027Sjungma@eit.uni-kl.de#endif
11112027Sjungma@eit.uni-kl.de
11212027Sjungma@eit.uni-kl.de
11312027Sjungma@eit.uni-kl.de/* Push arguments for the varargs case.
11412027Sjungma@eit.uni-kl.de   Has to be a function call because initialization is an expression
11512027Sjungma@eit.uni-kl.de   and we need to loop to copy nbytes of stuff on to the stack.
11612027Sjungma@eit.uni-kl.de   But that's probably OK, it's not terribly cheap, anyway. */
11712027Sjungma@eit.uni-kl.de
11812027Sjungma@eit.uni-kl.de#ifdef QUICKTHREADS_VARGS_DEFAULT
11912027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_VARGS_MD0
12012027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS_MD0(sp, vasize)	(sp)
12112027Sjungma@eit.uni-kl.de#endif
12212027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_VARGS_MD1
12312027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS_MD1(sp)	do { ; } while (0)
12412027Sjungma@eit.uni-kl.de#endif
12512027Sjungma@eit.uni-kl.de
12612027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_VSTKBASE
12712027Sjungma@eit.uni-kl.de  #error "Need base stack size for varargs functions."
12812027Sjungma@eit.uni-kl.de#endif
12912027Sjungma@eit.uni-kl.de
13012027Sjungma@eit.uni-kl.de/* Sometimes the stack pointer needs to munged a bit when storing
13112027Sjungma@eit.uni-kl.de   the list of arguments. */
13212027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_VARGS_ADJUST
13312027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS_ADJUST(sp)	(sp)
13412027Sjungma@eit.uni-kl.de#endif
13512027Sjungma@eit.uni-kl.de
13612027Sjungma@eit.uni-kl.de/* All things are put on the stack relative to the final value of
13712027Sjungma@eit.uni-kl.de   the stack pointer. */
13812027Sjungma@eit.uni-kl.de#ifdef QUICKTHREADS_GROW_DOWN
13912027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VADJ(sp)	(((char *)sp) - QUICKTHREADS_VSTKBASE)
14012027Sjungma@eit.uni-kl.de#else
14112027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VADJ(sp)	(((char *)sp) + QUICKTHREADS_VSTKBASE)
14212027Sjungma@eit.uni-kl.de#endif
14312027Sjungma@eit.uni-kl.de
14412027Sjungma@eit.uni-kl.deextern qt_t *qt_vargs (qt_t *sp, int nbytes, void *vargs,
14512027Sjungma@eit.uni-kl.de		       void *pt, qt_startup_t *startup,
14612027Sjungma@eit.uni-kl.de		       qt_vuserf_t *vuserf, qt_cleanup_t *cleanup);
14712027Sjungma@eit.uni-kl.de
14812027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_VARGS
14912027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
15012027Sjungma@eit.uni-kl.de      (qt_vargs (sp, nbytes, vargs, pt, startup, vuserf, cleanup))
15112027Sjungma@eit.uni-kl.de#endif
15212027Sjungma@eit.uni-kl.de
15312027Sjungma@eit.uni-kl.de#endif
15412027Sjungma@eit.uni-kl.de
15512027Sjungma@eit.uni-kl.de
15612027Sjungma@eit.uni-kl.de/* Save the state of the thread and call the helper function
15712027Sjungma@eit.uni-kl.de   using the stack of the new thread. */
15812027Sjungma@eit.uni-kl.detypedef void *(qt_helper_t)(qt_t *old, void *a0, void *a1);
15912027Sjungma@eit.uni-kl.detypedef void *(qt_block_t)(qt_helper_t *helper, void *a0, void *a1,
16012027Sjungma@eit.uni-kl.de			  qt_t *newthread);
16112027Sjungma@eit.uni-kl.de
16212027Sjungma@eit.uni-kl.de/* Rearrange the parameters so that things passed to the helper
16312027Sjungma@eit.uni-kl.de   function are already in the right argument registers. */
16412027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_ABORT
16512027Sjungma@eit.uni-kl.deextern void *qt_abort (qt_helper_t *h, void *a0, void *a1, qt_t *newthread);
16612027Sjungma@eit.uni-kl.de/* The following does, technically, `return' a value, but the
16712027Sjungma@eit.uni-kl.de   user had better not rely on it, since the function never
16812027Sjungma@eit.uni-kl.de   returns. */
16912027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ABORT(h, a0, a1, newthread) \
17012027Sjungma@eit.uni-kl.de    do { qt_abort (h, a0, a1, newthread); } while (0)
17112027Sjungma@eit.uni-kl.de#endif
17212027Sjungma@eit.uni-kl.de
17312027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_BLOCK
17412027Sjungma@eit.uni-kl.deextern void *qt_block (qt_helper_t *h, void *a0, void *a1,
17512027Sjungma@eit.uni-kl.de		       qt_t *newthread);
17612027Sjungma@eit.uni-kl.de#define QUICKTHREADS_BLOCK(h, a0, a1, newthread) \
17712027Sjungma@eit.uni-kl.de    (qt_block (h, a0, a1, newthread))
17812027Sjungma@eit.uni-kl.de#endif
17912027Sjungma@eit.uni-kl.de
18012027Sjungma@eit.uni-kl.de#ifndef QUICKTHREADS_BLOCKI
18112027Sjungma@eit.uni-kl.deextern void *qt_blocki (qt_helper_t *h, void *a0, void *a1,
18212027Sjungma@eit.uni-kl.de			qt_t *newthread);
18312027Sjungma@eit.uni-kl.de#define QUICKTHREADS_BLOCKI(h, a0, a1, newthread) \
18412027Sjungma@eit.uni-kl.de    (qt_blocki (h, a0, a1, newthread))
18512027Sjungma@eit.uni-kl.de#endif
18612027Sjungma@eit.uni-kl.de
18712027Sjungma@eit.uni-kl.de#ifdef __cplusplus
18812027Sjungma@eit.uni-kl.de}		/* Match `extern "C" {' at top. */
18912027Sjungma@eit.uni-kl.de#endif
19012027Sjungma@eit.uni-kl.de
19112027Sjungma@eit.uni-kl.de#endif // !defined(SC_USE_PTHREADS)
19212027Sjungma@eit.uni-kl.de#endif /* ndef QUICKTHREADS_H */
193