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_KSR1_H 1512027Sjungma@eit.uni-kl.de#define QUICKTHREADS_KSR1_H 1612027Sjungma@eit.uni-kl.de 1712027Sjungma@eit.uni-kl.de/* 1812027Sjungma@eit.uni-kl.de Stack layout: 1912027Sjungma@eit.uni-kl.de 2012027Sjungma@eit.uni-kl.de Registers are saved in strictly low to high order, FPU regs first 2112027Sjungma@eit.uni-kl.de (only if qt_block is called), CEU regs second, IPU regs next, with no 2212027Sjungma@eit.uni-kl.de padding between the groups. 2312027Sjungma@eit.uni-kl.de 2412027Sjungma@eit.uni-kl.de Callee-save: f16..f63; c15..c30; i12..i30. 2512027Sjungma@eit.uni-kl.de Args passed in i2..i5. 2612027Sjungma@eit.uni-kl.de 2712027Sjungma@eit.uni-kl.de Note: c31 is a private data pointer. It is not changed on thread 2812027Sjungma@eit.uni-kl.de swaps with the assumption that it represents per-processor rather 2912027Sjungma@eit.uni-kl.de than per-thread state. 3012027Sjungma@eit.uni-kl.de 3112027Sjungma@eit.uni-kl.de Note: i31 is an instruction count register that is updated by the 3212027Sjungma@eit.uni-kl.de context switch routines. Like c31, it is not changed on context 3312027Sjungma@eit.uni-kl.de switches. 3412027Sjungma@eit.uni-kl.de 3512027Sjungma@eit.uni-kl.de This is what we want on startup: 3612027Sjungma@eit.uni-kl.de 3712027Sjungma@eit.uni-kl.de 3812027Sjungma@eit.uni-kl.de +------ <-- BOS: Bottom of stack (grows down) 3912027Sjungma@eit.uni-kl.de | 80 (128 - 48) bytes of padding to a 128-byte boundary 4012027Sjungma@eit.uni-kl.de +--- 4112027Sjungma@eit.uni-kl.de | only 4212027Sjungma@eit.uni-kl.de | userf 4312027Sjungma@eit.uni-kl.de | t 4412027Sjungma@eit.uni-kl.de | u 4512027Sjungma@eit.uni-kl.de | qt_start$TXT 4612027Sjungma@eit.uni-kl.de | (empty) <-- qt.sp 4712027Sjungma@eit.uni-kl.de +------ <-- (BOS - 128) 4812027Sjungma@eit.uni-kl.de 4912027Sjungma@eit.uni-kl.de This is why we want this on startup: 5012027Sjungma@eit.uni-kl.de 5112027Sjungma@eit.uni-kl.de A thread begins running when the restore procedure switches thread stacks 5212027Sjungma@eit.uni-kl.de and pops a return address off of the top of the new stack (see below 5312027Sjungma@eit.uni-kl.de for the reason why we explicitly store qt_start$TXT). The 5412027Sjungma@eit.uni-kl.de block procedure pushes two jump addresses on a thread's stack before 5512027Sjungma@eit.uni-kl.de it switches stacks. The first is the return address for the block 5612027Sjungma@eit.uni-kl.de procedure, and the second is a restore address. The return address 5712027Sjungma@eit.uni-kl.de is used to jump back to the thread that has been switched to; the 5812027Sjungma@eit.uni-kl.de restore address is a jump within the block code to restore the registers. 5912027Sjungma@eit.uni-kl.de Normally, this is just a jump to the next address. However, on thread 6012027Sjungma@eit.uni-kl.de startup, this is a jump to qt_start$TXT. (The block procedure stores 6112027Sjungma@eit.uni-kl.de the restore address at an offset of 8 bytes from the top of the stack, 6212027Sjungma@eit.uni-kl.de which is also the offset at which qt_start$TXT is stored on the stacks 6312027Sjungma@eit.uni-kl.de of new threads. Hence, when the block procedure switches to a new 6412027Sjungma@eit.uni-kl.de thread stack, it will initially jump to qt_start$TXT; thereafter, 6512027Sjungma@eit.uni-kl.de it jumps to the restore code.) 6612027Sjungma@eit.uni-kl.de 6712027Sjungma@eit.uni-kl.de qt_start$TXT, after it has read the initial data on the new thread's 6812027Sjungma@eit.uni-kl.de stack and placed it in registers, pops the initial stack frame 6912027Sjungma@eit.uni-kl.de and gives the thread the entire stack to use for execution. 7012027Sjungma@eit.uni-kl.de 7112027Sjungma@eit.uni-kl.de The KSR runtime system has an unusual treatment of pointers to 7212027Sjungma@eit.uni-kl.de functions. From C, taking the `name' of a function yields a 7312027Sjungma@eit.uni-kl.de pointer to a _constant block_ and *not* the address of the 7412027Sjungma@eit.uni-kl.de function. The zero'th entry in the constant block is a pointer to 7512027Sjungma@eit.uni-kl.de the function. 7612027Sjungma@eit.uni-kl.de 7712027Sjungma@eit.uni-kl.de We have to be careful: the restore procedure expects a return 7812027Sjungma@eit.uni-kl.de address on the top of the stack (pointed to by qt.sp). This is not 7912027Sjungma@eit.uni-kl.de a problem when restoring a thread that has run before, since the 8012027Sjungma@eit.uni-kl.de block routine would have stored the return address on top of the 8112027Sjungma@eit.uni-kl.de stack. However, when ``faking up'' a thread start (bootstrapping a 8212027Sjungma@eit.uni-kl.de thread stack frame), the top of the stack needs to contain a 8312027Sjungma@eit.uni-kl.de pointer to the code that will start the thread running. 8412027Sjungma@eit.uni-kl.de 8512027Sjungma@eit.uni-kl.de The pointer to the startup code is *not* `qt_start'. It is the 8612027Sjungma@eit.uni-kl.de word *pointed to* by `qt_start'. Thus, we dereference `qt_start', 8712027Sjungma@eit.uni-kl.de see QUICKTHREADS_ARGS_MD below. 8812027Sjungma@eit.uni-kl.de 8912027Sjungma@eit.uni-kl.de On varargs startup (still unimplemented): 9012027Sjungma@eit.uni-kl.de 9112027Sjungma@eit.uni-kl.de | padding to 128 byte boundary 9212027Sjungma@eit.uni-kl.de | varargs <-- padded to a 128-byte-boundary 9312027Sjungma@eit.uni-kl.de +--- 9412027Sjungma@eit.uni-kl.de | caller's frame, 16 bytes 9512027Sjungma@eit.uni-kl.de | 80 bytes of padding (frame padded to a 128-byte boundary) 9612027Sjungma@eit.uni-kl.de +--- 9712027Sjungma@eit.uni-kl.de | cleanup 9812027Sjungma@eit.uni-kl.de | vuserf 9912027Sjungma@eit.uni-kl.de | startup 10012027Sjungma@eit.uni-kl.de | t 10112027Sjungma@eit.uni-kl.de +--- 10212027Sjungma@eit.uni-kl.de | qt_start <-- qt.sp 10312027Sjungma@eit.uni-kl.de +--- 10412027Sjungma@eit.uni-kl.de 10512027Sjungma@eit.uni-kl.de Of a suspended thread: 10612027Sjungma@eit.uni-kl.de 10712027Sjungma@eit.uni-kl.de +--- 10812027Sjungma@eit.uni-kl.de | caller's frame, 16 bytes 10912027Sjungma@eit.uni-kl.de | fpu registers 47 regs * 8 bytes/reg 376 bytes 11012027Sjungma@eit.uni-kl.de | ceu registers 16 regs * 8 bytes/reg 128 bytes 11112027Sjungma@eit.uni-kl.de | ipu registers 19 regs * 8 bytes/reg 152 bytes 11212027Sjungma@eit.uni-kl.de | : 11312027Sjungma@eit.uni-kl.de | 80 bytes of padding 11412027Sjungma@eit.uni-kl.de | : 11512027Sjungma@eit.uni-kl.de | qt_restore <-- qt.sp 11612027Sjungma@eit.uni-kl.de +--- 11712027Sjungma@eit.uni-kl.de 11812027Sjungma@eit.uni-kl.de */ 11912027Sjungma@eit.uni-kl.de 12012027Sjungma@eit.uni-kl.de 12112027Sjungma@eit.uni-kl.de#define QUICKTHREADS_STKALIGN 128 12212027Sjungma@eit.uni-kl.de#define QUICKTHREADS_GROW_DOWN 12312027Sjungma@eit.uni-kl.detypedef unsigned long qt_word_t; 12412027Sjungma@eit.uni-kl.de 12512027Sjungma@eit.uni-kl.de#define QUICKTHREADS_STKBASE QUICKTHREADS_STKALIGN 12612027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE 12712027Sjungma@eit.uni-kl.de 12812027Sjungma@eit.uni-kl.deextern void qt_start(void); 12912027Sjungma@eit.uni-kl.de/* 13012027Sjungma@eit.uni-kl.de * See the discussion above for what indexing into a procedure ptr 13112027Sjungma@eit.uni-kl.de * does for us (it's lovely, though, isn't it?). 13212027Sjungma@eit.uni-kl.de * 13312027Sjungma@eit.uni-kl.de * This assumes that the address of a procedure's code is the 13412027Sjungma@eit.uni-kl.de * first word in a procedure's constant block. That's how the manual 13512027Sjungma@eit.uni-kl.de * says it will be arranged. 13612027Sjungma@eit.uni-kl.de */ 13712027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, 1, ((qt_word_t *)qt_start)[0])) 13812027Sjungma@eit.uni-kl.de 13912027Sjungma@eit.uni-kl.de/* 14012027Sjungma@eit.uni-kl.de * The *index* (positive offset) of where to put each value. 14112027Sjungma@eit.uni-kl.de * See the picture of the stack above that explains the offsets. 14212027Sjungma@eit.uni-kl.de */ 14312027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ONLY_INDEX (5) 14412027Sjungma@eit.uni-kl.de#define QUICKTHREADS_USER_INDEX (4) 14512027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ARGT_INDEX (3) 14612027Sjungma@eit.uni-kl.de#define QUICKTHREADS_ARGU_INDEX (2) 14712027Sjungma@eit.uni-kl.de 14812027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS_DEFAULT 14912027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS(sp, nb, vargs, pt, startup, vuserf, cleanup) \ 15012027Sjungma@eit.uni-kl.de (qt_vargs (sp, nbytes, &vargs, pt, startup, vuserf, cleanup)) 15112027Sjungma@eit.uni-kl.de 15212027Sjungma@eit.uni-kl.de 15312027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ 15412027Sjungma@eit.uni-kl.de ((qt_t *)(((char *)(sp)) - 4*8 - QUICKTHREADS_STKROUNDUP(vabytes))) 15512027Sjungma@eit.uni-kl.de 15612027Sjungma@eit.uni-kl.deextern void qt_vstart(void); 15712027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, 0, ((qt_word_t *)qt_vstart)[0])) 15812027Sjungma@eit.uni-kl.de 15912027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VCLEANUP_INDEX (4) 16012027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VUSERF_INDEX (3) 16112027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VSTARTUP_INDEX (2) 16212027Sjungma@eit.uni-kl.de#define QUICKTHREADS_VARGT_INDEX (1) 16312027Sjungma@eit.uni-kl.de 16412027Sjungma@eit.uni-kl.de#endif /* def QUICKTHREADS_KSR1_H */ 165