X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=guile18%2Fqt%2Fmd%2Fksr1.h;fp=guile18%2Fqt%2Fmd%2Fksr1.h;h=83537a3c20fccdeb9ebdde1100bb8961096ade0a;hb=139c38d9204dd07f6b235f83bae644faedbc63fd;hp=0000000000000000000000000000000000000000;hpb=652ed35a2013489d0a14fede6307cd2595abb2c4;p=lilypond.git diff --git a/guile18/qt/md/ksr1.h b/guile18/qt/md/ksr1.h new file mode 100644 index 0000000000..83537a3c20 --- /dev/null +++ b/guile18/qt/md/ksr1.h @@ -0,0 +1,164 @@ +/* + * QuickThreads -- Threads-building toolkit. + * Copyright (c) 1993 by David Keppel + * + * Permission to use, copy, modify and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice and this notice + * appear in all copies. This software is provided as a + * proof-of-concept and for demonstration purposes; there is no + * representation about the suitability of this software for any + * purpose. + */ + +#ifndef QT_KSR1_H +#define QT_KSR1_H + +/* + Stack layout: + + Registers are saved in strictly low to high order, FPU regs first + (only if qt_block is called), CEU regs second, IPU regs next, with no + padding between the groups. + + Callee-save: f16..f63; c15..c30; i12..i30. + Args passed in i2..i5. + + Note: c31 is a private data pointer. It is not changed on thread + swaps with the assumption that it represents per-processor rather + than per-thread state. + + Note: i31 is an instruction count register that is updated by the + context switch routines. Like c31, it is not changed on context + switches. + + This is what we want on startup: + + + +------ <-- BOS: Bottom of stack (grows down) + | 80 (128 - 48) bytes of padding to a 128-byte boundary + +--- + | only + | userf + | t + | u + | qt_start$TXT + | (empty) <-- qt.sp + +------ <-- (BOS - 128) + + This is why we want this on startup: + + A thread begins running when the restore procedure switches thread stacks + and pops a return address off of the top of the new stack (see below + for the reason why we explicitly store qt_start$TXT). The + block procedure pushes two jump addresses on a thread's stack before + it switches stacks. The first is the return address for the block + procedure, and the second is a restore address. The return address + is used to jump back to the thread that has been switched to; the + restore address is a jump within the block code to restore the registers. + Normally, this is just a jump to the next address. However, on thread + startup, this is a jump to qt_start$TXT. (The block procedure stores + the restore address at an offset of 8 bytes from the top of the stack, + which is also the offset at which qt_start$TXT is stored on the stacks + of new threads. Hence, when the block procedure switches to a new + thread stack, it will initially jump to qt_start$TXT; thereafter, + it jumps to the restore code.) + + qt_start$TXT, after it has read the initial data on the new thread's + stack and placed it in registers, pops the initial stack frame + and gives the thread the entire stack to use for execution. + + The KSR runtime system has an unusual treatment of pointers to + functions. From C, taking the `name' of a function yields a + pointer to a _constant block_ and *not* the address of the + function. The zero'th entry in the constant block is a pointer to + the function. + + We have to be careful: the restore procedure expects a return + address on the top of the stack (pointed to by qt.sp). This is not + a problem when restoring a thread that has run before, since the + block routine would have stored the return address on top of the + stack. However, when ``faking up'' a thread start (bootstrapping a + thread stack frame), the top of the stack needs to contain a + pointer to the code that will start the thread running. + + The pointer to the startup code is *not* `qt_start'. It is the + word *pointed to* by `qt_start'. Thus, we dereference `qt_start', + see QT_ARGS_MD below. + + On varargs startup (still unimplemented): + + | padding to 128 byte boundary + | varargs <-- padded to a 128-byte-boundary + +--- + | caller's frame, 16 bytes + | 80 bytes of padding (frame padded to a 128-byte boundary) + +--- + | cleanup + | vuserf + | startup + | t + +--- + | qt_start <-- qt.sp + +--- + + Of a suspended thread: + + +--- + | caller's frame, 16 bytes + | fpu registers 47 regs * 8 bytes/reg 376 bytes + | ceu registers 16 regs * 8 bytes/reg 128 bytes + | ipu registers 19 regs * 8 bytes/reg 152 bytes + | : + | 80 bytes of padding + | : + | qt_restore <-- qt.sp + +--- + + */ + + +#define QT_STKALIGN 128 +#define QT_GROW_DOWN +typedef unsigned long qt_word_t; + +#define QT_STKBASE QT_STKALIGN +#define QT_VSTKBASE QT_STKBASE + +extern void qt_start(void); +/* + * See the discussion above for what indexing into a procedure ptr + * does for us (it's lovely, though, isn't it?). + * + * This assumes that the address of a procedure's code is the + * first word in a procedure's constant block. That's how the manual + * says it will be arranged. + */ +#define QT_ARGS_MD(sp) (QT_SPUT (sp, 1, ((qt_word_t *)qt_start)[0])) + +/* + * The *index* (positive offset) of where to put each value. + * See the picture of the stack above that explains the offsets. + */ +#define QT_ONLY_INDEX (5) +#define QT_USER_INDEX (4) +#define QT_ARGT_INDEX (3) +#define QT_ARGU_INDEX (2) + +#define QT_VARGS_DEFAULT +#define QT_VARGS(sp, nb, vargs, pt, startup, vuserf, cleanup) \ + (qt_vargs (sp, nbytes, &vargs, pt, startup, vuserf, cleanup)) + + +#define QT_VARGS_MD0(sp, vabytes) \ + ((qt_t *)(((char *)(sp)) - 4*8 - QT_STKROUNDUP(vabytes))) + +extern void qt_vstart(void); +#define QT_VARGS_MD1(sp) (QT_SPUT (sp, 0, ((qt_word_t *)qt_vstart)[0])) + +#define QT_VCLEANUP_INDEX (4) +#define QT_VUSERF_INDEX (3) +#define QT_VSTARTUP_INDEX (2) +#define QT_VARGT_INDEX (1) + +#endif /* def QT_KSR1_H */