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