jcs
/subtext
/amendments
/626
uthread: Add hooks for checking uthread canaries on every function
jcs made amendment 626 8 months ago
--- uthread.c Fri Dec 12 16:41:21 2025
+++ uthread.c Mon Dec 15 21:41:20 2025
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#pragma options(!profile)
+
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -34,6 +36,8 @@ struct uthread *uthread_current = NULL;
unsigned long uthread_main_canary;
void uthread_begin(struct uthread *uthread);
+void _profile_(unsigned char *);
+static void * profile_exit(void);
/*
* | A5 world |
@@ -122,6 +126,7 @@ uthread_add(void *func, void *arg)
return NULL;
}
+#pragma nooptimize(uthread_begin)
void
uthread_begin(struct uthread *uthread)
{
@@ -147,6 +152,7 @@ uthread_begin(struct uthread *uthread)
longjmp(uthread_coord_env, UTHREAD_SETJMP_YIELDED);
}
+#pragma nooptimize(uthread_yield)
void
uthread_yield(void)
{
@@ -161,15 +167,6 @@ uthread_yield(void)
if (uthread_current == NULL)
panic("uthread_yield not from a thread!");
- if (_sp > uthread_current->stack_top ||
- _sp < uthread_current->stack_bottom)
- panic("thread %d stack pointer out of bounds [SP=0x%lx] "
- "[top=0x%lx] [bottom=0x%lx]", uthread_current->id, _sp,
- uthread_current->stack_top, uthread_current->stack_bottom);
-
- if (uthread_current->stack_top - _sp > ((UTHREAD_STACK_SIZE * 9) / 10))
- warn("thread %d stack usage >= 90%%", uthread_current->id);
-
if (uthread_current->state != UTHREAD_STATE_SLEEPING)
uthread_current->state = UTHREAD_STATE_YIELDING;
@@ -259,10 +256,61 @@ uthread_verify(void)
if (*(unsigned long *)uthreads[i].stack_canary != UTHREAD_CANARY)
warn("thread %d stack canary died", i);
- if (uthread_current && uthread_current == &uthreads[i]) {
- if (uthread_current->stack_top - _sp >
- ((UTHREAD_STACK_SIZE * 9) / 10))
- warn("thread %d stack usage >= 90%%", uthread_current->id);
- }
}
-}
\ No newline at end of file
+}
+
+static struct stack {
+ unsigned long ret[64];
+ unsigned depth;
+} uthread_stacks[NUM_UTHREADS + 1] = { 0 };
+
+void
+_profile_(unsigned char *fname)
+{
+ register struct stack *s;
+ register unsigned long *ret;
+
+ if (uthread_current)
+ s = &uthread_stacks[uthread_current->id];
+ else
+ s = &uthread_stacks[NUM_UTHREADS];
+
+ ret = &s->ret[s->depth++];
+
+ asm {
+ movea.l (a6),a0
+ move.l 4(a0),(ret)
+ lea @exit,a1
+ move.l a1,4(a0)
+ }
+
+ return;
+
+ /* the profiled function will return here */
+exit:
+ asm {
+ move.l d0,-(sp) ; preserve result
+ jsr profile_exit
+ movea.l d0,a0 ; real return address
+ move.l (sp)+,d0 ; restore result
+ jmp (a0) ; return
+ }
+}
+
+static void *
+profile_exit(void)
+{
+ register struct stack *s;
+ unsigned long *ret;
+
+ if (uthread_current)
+ s = &uthread_stacks[uthread_current->id];
+ else
+ s = &uthread_stacks[NUM_UTHREADS];
+
+ ret = &s->ret[--s->depth];
+
+ uthread_verify();
+
+ return (void *)*ret;
+}