]> git.donarmstrong.com Git - lilypond.git/blobdiff - guile18/qt/md/ksr1.h
Import guile-1.8 as multiple upstream tarball component
[lilypond.git] / guile18 / qt / md / ksr1.h
diff --git a/guile18/qt/md/ksr1.h b/guile18/qt/md/ksr1.h
new file mode 100644 (file)
index 0000000..83537a3
--- /dev/null
@@ -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 */