From ad5098bb07a6000d9a6f0890509d97211e374c69 Mon Sep 17 00:00:00 2001 From: Janis Hutz Date: Fri, 16 Jan 2026 08:19:39 +0100 Subject: [PATCH] [SPCA] Finish unorthodox control flow --- .../01_asm/08_unorthodox-controlflow.c | 22 ++++++++++ .../code-examples/01_asm/09_setjmp-longjmp.s | 27 ++++++++++++ .../spca/code-examples/01_asm/10_coroutine.c | 40 ++++++++++++++++++ .../spca/code-examples/01_asm/10_coroutine.h | 13 ++++++ semester3/spca/parts/00_asm/05_stack.tex | 1 - .../00_asm/06_unorthodox-control-flow.tex | 19 +++++++++ semester3/spca/parts/00_asm/07_coroutines.tex | 12 ++++++ semester3/spca/spca-summary.pdf | Bin 616390 -> 624990 bytes semester3/spca/spca-summary.tex | 2 + 9 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 semester3/spca/code-examples/01_asm/08_unorthodox-controlflow.c create mode 100644 semester3/spca/code-examples/01_asm/09_setjmp-longjmp.s create mode 100644 semester3/spca/code-examples/01_asm/10_coroutine.c create mode 100644 semester3/spca/code-examples/01_asm/10_coroutine.h create mode 100644 semester3/spca/parts/00_asm/07_coroutines.tex diff --git a/semester3/spca/code-examples/01_asm/08_unorthodox-controlflow.c b/semester3/spca/code-examples/01_asm/08_unorthodox-controlflow.c new file mode 100644 index 0000000..7ec2b6e --- /dev/null +++ b/semester3/spca/code-examples/01_asm/08_unorthodox-controlflow.c @@ -0,0 +1,22 @@ +#include +#include + +static jmp_buf buf; + +void second( void ) { + printf( "second\n" ); + longjmp( buf, 1 ); +} + +void first( void ) { + second(); + printf( "first\n" ); // Never executed +} + +int main() { + if ( !setjmp( buf ) ) // returns 0 initially + first(); + else + printf( "main\n" ); // 1 is returned when longjmp is executed + return 0; +} diff --git a/semester3/spca/code-examples/01_asm/09_setjmp-longjmp.s b/semester3/spca/code-examples/01_asm/09_setjmp-longjmp.s new file mode 100644 index 0000000..ea3650a --- /dev/null +++ b/semester3/spca/code-examples/01_asm/09_setjmp-longjmp.s @@ -0,0 +1,27 @@ +# Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license +setjmp: + mov %rbx, (%rdi) + mov %rbp, 8(%rdi) + mov %r12, 16(%rdi) + mov %r13, 24(%rdi) + mov %r14, 32(%rdi) + mov %r15, 40(%rdi) + lea 8(%rsp), %rdx + mov %rdx, 48(%rdi) + mov (%rsp), %rdx + mov %rdx, 56(%rdi) + xor %eax, %eax + ret + +longjmp: + xor %eax, %eax + cmp $1, %esi # CF = val ? 0 : 1 + adc %esi, %eax # eax = val + !val + mov (%rdi), %rbx # rdi is the jmp_buf, restore regs from it + mov 8(%rdi), %rbp + mov 16(%rdi), %r12 + mov 24(%rdi), %r13 + mov 32(%rdi), %r14 + mov 40(%rdi), %r15 + mov 48(%rdi), %rsp + jmp *56(%rdi) # goto saved address without altering rsp diff --git a/semester3/spca/code-examples/01_asm/10_coroutine.c b/semester3/spca/code-examples/01_asm/10_coroutine.c new file mode 100644 index 0000000..5c7e383 --- /dev/null +++ b/semester3/spca/code-examples/01_asm/10_coroutine.c @@ -0,0 +1,40 @@ +#include "10_coroutine.h" +#include +#include +#include +#define CORO_STACK_SIZE 128 +static struct coroutine *cur_co; +static struct coroutine *main_co; + +void co_init() { + main_co = (struct coroutine *) calloc( 1, sizeof( struct coroutine ) ); + cur_co = main_co; + co_switchto( main_co ); +} + +void *co_switchto( struct coroutine *next, void *arg ) { + if ( setjmp( cur_co->env ) == 0 ) { + cur_co = next; + cur_co->arg = arg; + longjmp( cur_co->env, 1 ); + } + return cur_co->arg; +} + +static void start_cl( void ) { + ( cur_co->start )( cur_co->arg ); + co_switchto( main_co ); + + printf( "Error: returned from coroutine start closure.\n" ); + exit( -1 ); +} + +struct coroutine *co_new( co_start_fn *start, void *ctxt ) { + struct coroutine *co = (struct coroutine *) calloc( 1, sizeof( struct coroutine ) ); + co->stack = calloc( 1, CORO_STACK_SIZE + 16 ); + co->start = start; + co->arg = ctxt; + setjmp( co->env ); + co->env[ 0 ].__jmpbuf[ 6 ] = ( (uint64_t) ( co->stack ) + CORO_STACK_SIZE ); // Machine specific + co->env[ 0 ].__jmpbuf[ 7 ] = ( (uint64_t) ( start_cl ) ); // Machine specific +} diff --git a/semester3/spca/code-examples/01_asm/10_coroutine.h b/semester3/spca/code-examples/01_asm/10_coroutine.h new file mode 100644 index 0000000..c71a6f5 --- /dev/null +++ b/semester3/spca/code-examples/01_asm/10_coroutine.h @@ -0,0 +1,13 @@ +#include +typedef void( co_start_fn )( void * ); + +struct coroutine { + void *stack; // The call stack + jmp_buf env; // The saved context + co_start_fn *start; // Function to call + void *arg; // Argument to the function +}; +struct coroutine *co_new( co_start_fn *start, void *ctxt ); +void co_free( struct coroutine *self ); +void *co_switchto( struct coroutine *next ); +void co_init( void ); diff --git a/semester3/spca/parts/00_asm/05_stack.tex b/semester3/spca/parts/00_asm/05_stack.tex index cf50ef1..521f870 100644 --- a/semester3/spca/parts/00_asm/05_stack.tex +++ b/semester3/spca/parts/00_asm/05_stack.tex @@ -75,4 +75,3 @@ A more complex example, passing addresses as arguments: \\ This function swaps 2 array elements (using a \texttt{swap} function) and adds the first value to an accumulator. \inputcodewithfilename{gas}{code-examples/01_asm/}{07_swap_and_sum.s} - diff --git a/semester3/spca/parts/00_asm/06_unorthodox-control-flow.tex b/semester3/spca/parts/00_asm/06_unorthodox-control-flow.tex index e69de29..047a97a 100644 --- a/semester3/spca/parts/00_asm/06_unorthodox-control-flow.tex +++ b/semester3/spca/parts/00_asm/06_unorthodox-control-flow.tex @@ -0,0 +1,19 @@ +\newpage +\subsection{Unorthodox Control Flow} +In \lC, the \texttt{setjmp.h} header file can be included, which gives us access to \texttt{setjmp} and \texttt{longjmp}. + +To use them, we first need to declare a \texttt{jmp\_buf} somewhere, usually as a static variable. + +The \texttt{setjmp( jmp\_buf env } function stores the current stack / environment in the \texttt{jmp\_buf} and returns 0. + +The \texttt{longjmp( jmp\_buf env, int val )} function causes a second return, which returns \texttt{val}, +to the \texttt{setjmp} invocation and jumps back to that place. + +\inputcodewithfilename{c}{code-examples/01_asm/}{08_unorthodox-controlflow.c} + +What the above code outputs is: \texttt{second} followed by \texttt{main}. + +\newpage +They are implemented in Assembly as follows. Nothing really surprising for the implementation there. +The assembly code is from the Musl \lC\ library +\inputcodewithfilename{gas}{code-examples/01_asm/}{09_setjmp-longjmp.s} diff --git a/semester3/spca/parts/00_asm/07_coroutines.tex b/semester3/spca/parts/00_asm/07_coroutines.tex new file mode 100644 index 0000000..d736990 --- /dev/null +++ b/semester3/spca/parts/00_asm/07_coroutines.tex @@ -0,0 +1,12 @@ +\newpage +\subsection{Coroutines} +Coroutines are functions that call each other when they are done or they need new data to work on. +An example is a decompresser that calls a parser when it has finished compressing parts of the file and that parser then again calls the decompresser when it has finished parsing. + +We can implement that either by rewriting the functions into a single function, which often is a bit clumsy. +A way around this is to use \bi{Continuations}, where the first function saves its state and the context is switched to the other function. +That function can then load its state and continue where it left off, runs until it finishes its task, then saves its state and the context switches back to the original function. +\inputcodewithfilename{c}{code-examples/01_asm/}{10_coroutine.h} +\inputcodewithfilename{c}{code-examples/01_asm/}{10_coroutine.c} + +As you can see, the \texttt{setjmp.h} functions are the foundation of all concurrent programming. diff --git a/semester3/spca/spca-summary.pdf b/semester3/spca/spca-summary.pdf index d9148f723ed06d79350fbb22cb7ac12a34b659b3..e333478d1600bed822509f4197959b5ad0e33a88 100644 GIT binary patch delta 144516 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