Skip to content

Commit 751f4b0

Browse files
committed
Avoid stack overflow by yielding to trampoline
1 parent c9e6579 commit 751f4b0

File tree

2 files changed

+10
-7
lines changed

2 files changed

+10
-7
lines changed

libraries/common/io/signal.effekt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ namespace signal {
1414
"""
1515
}
1616

17-
extern global def unsafeSend[T](signal: Signal[T], value: T): Unit =
17+
extern async def unsafeSend[T](signal: Signal[T], value: T): Unit =
1818
llvm """
19-
call void @c_signal_send(%Pos ${signal}, %Pos ${value})
20-
ret %Pos zeroinitializer
19+
call void @c_signal_send(%Pos ${signal}, %Pos ${value}, %Stack %stack)
20+
ret void
2121
"""
2222

2323
extern async def unsafeWait[T](signal: Signal[T]): T =

libraries/llvm/io.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,15 @@ struct Pos c_signal_make() {
338338
return (struct Pos) { .tag = 0, .obj = signal, };
339339
}
340340

341-
void c_signal_send(struct Pos signal, struct Pos value) {
341+
void c_signal_send(struct Pos signal, struct Pos value, Stack stack) {
342342
Signal* f = (Signal*)signal.obj;
343343
switch (f->state) {
344344
case BEFORE: {
345345
f->state = SENDING;
346346
f->payload.value = value;
347347
erasePositive(signal);
348+
// TODO avoid stack overflow without yielding
349+
c_yield(stack);
348350
break;
349351
}
350352
case SENDING: {
@@ -354,11 +356,12 @@ void c_signal_send(struct Pos signal, struct Pos value) {
354356
break;
355357
}
356358
case WAITING: {
357-
Stack stack = f->payload.stack;
359+
Stack other = f->payload.stack;
358360
f->state = AFTER;
359361
erasePositive(signal);
360-
// TODO this overflows the C stack
361-
resume_Pos(stack, value);
362+
// TODO avoid stack overflow without yielding
363+
c_yield(stack);
364+
resume_Pos(other, value);
362365
break;
363366
}
364367
case AFTER: {

0 commit comments

Comments
 (0)