123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- /*
- * 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.
- */
- #include <stdarg.h>
- #include "qt.h"
- /* Varargs is harder on the m88k. Parameters are saved on the stack as
- something like (stack grows down to low memory; low at bottom of
- picture):
- | :
- | arg8 <-- va_list.__va_stk
- +---
- | :
- +---
- | arg7
- | :
- | iarg0 <-- va_list.__va_reg
- +---
- | :
- | va_list { __va_arg, __va_stk, __va_reg }
- | :
- +---
- Here, `va_list.__va_arg' is the number of word-size arguments
- that have already been skipped. Doubles must be double-arligned.
- What this means for us is that the user's routine needs to be
- called with an arg list where some of the words in the `__va_stk'
- part of the parameter list have to be promoted to registers.
- BUG: doubleword register arguments must be double-aligned. If
- something is passed as an even # arg and used as an odd # arg or
- vice-versa, the code in the called routine (in the new thread) that
- decides how to adjust the index will get it wrong, because it will
- be expect it to be, say, doubleword aligned and it will really be
- singleword aligned.
- I'm not sure you can solve this without knowing the types of all
- the arguments. All in all, we never promised varargs would work
- reliably. */
- #define QT_VADJ(sp) (((char *)sp) - QT_VSTKBASE)
- /* Always allocate at least enough space for 8 args; waste some space
- at the base of the stack to ensure the startup routine doesn't read
- off the end of the stack. */
- #define QT_VARGS_MD0(sp, vabytes) \
- ((qt_t *)(((char *)(sp)) - 8*4 - QT_STKROUNDUP(vabytes)))
- extern void qt_vstart(void);
- #define QT_VARGS_MD1(sp) (QT_SPUT (sp, QT_1, qt_vstart))
- struct qt_t *
- qt_vargs (struct qt_t *qsp, int nbytes, void *vargs,
- void *pt, qt_function_t *startup,
- qt_function_t *vuserf, qt_function_t *cleanup)
- {
- va_list ap;
- int i;
- int n; /* Number of words into original arg list. */
- qt_word_t *sp;
- int *reg; /* Where to read passed-in-reg args. */
- int *stk; /* Where to read passed-on-stk args. */
- ap = *(va_list *)vargs;
- qsp = QT_VARGS_MD0 (qsp, nbytes);
- sp = (qt_word_t *)qsp;
- reg = (ap.__va_arg < 8)
- ? &ap.__va_reg[ap.__va_arg]
- : 0;
- stk = &ap.__va_stk[8];
- n = ap.__va_arg;
- for (i=0; i<nbytes/sizeof(qt_word_t) && n<8; ++i,++n) {
- sp[i] = *reg++;
- }
- for (; i<nbytes/sizeof(qt_word_t); ++i) {
- sp[i] = *stk++;
- }
- #ifdef QT_NDEF
- for (i=0; i<nbytes/sizeof(qt_word_t); ++i) {
- sp[i] = (n < 8)
- ? *reg++
- : *stk++;
- ++n;
- }
- #endif
- QT_VARGS_MD1 (QT_VADJ(sp));
- QT_SPUT (QT_VADJ(sp), QT_VARGT_INDEX, pt);
- QT_SPUT (QT_VADJ(sp), QT_VSTARTUP_INDEX, startup);
- QT_SPUT (QT_VADJ(sp), QT_VUSERF_INDEX, vuserf);
- QT_SPUT (QT_VADJ(sp), QT_VCLEANUP_INDEX, cleanup);
- return ((qt_t *)QT_VADJ(sp));
- }
|