Long jump API
The long jump API allows to perform nonlocal gotos, that is jump from one function to another typically further down in the stack, while properly restoring the stack’s state (unwinding). The two functions needed to do this are setjmp() and longjmp().
In addition to these two standard POSIX.1-2001/C89 functions, a third one is present in U-Boot: initjmp(). It is an extension which allows to implement user-mode threads.
-
type jmp_buf
information needed to restore a calling environment
Parameters
jmp_buf env
jump buffer used to store register values
Description
Registers, the stack pointer, and the return address are saved in the jump bufffer. The function returns zero afterwards. When longjmp() is executed the function returns a second time with a non-zero value.
Return
0 after setting up jump buffer, non-zero after longjmp()
Parameters
jmp_buf env
jump buffer
int val
value to be returned by setjmp(), 0 is replaced by 1
Description
Jump back to the address and the register state saved by setjmp().
-
int initjmp(jmp_buf env, void __noreturn (*func)(void), void *stack_base, size_t stack_sz)
prepare for a long jump to a given function with a given stack
Parameters
jmp_buf env
jump buffer
void __noreturn (*func)(void)
function to be called on longjmp(), MUST NOT RETURN
void *stack_base
the stack to be used by func (lower address)
size_t stack_sz
the stack size in bytes
Description
This function sets up a jump buffer for later use with longjmp(). It allows to branch to a specific function with a specific stack. Please note that func MUST NOT return. It shall typically restore the main stack and resume execution by doing a long jump to a jump buffer initialized by setjmp() before the long jump. initjmp() allows to implement multithreading.
Example
Here is an example showing how to use the a long jump functions and initjmp() in particular:
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright 2025 Linaro Limited
4 *
5 * Unit test for initjmp()
6 */
7
8#include <compiler.h>
9#include <setjmp.h>
10#include <stdbool.h>
11#include <test/lib.h>
12#include <test/ut.h>
13#include <vsprintf.h>
14
15static bool ep_entered;
16static jmp_buf return_buf;
17
18static void __noreturn entrypoint(void)
19{
20 ep_entered = true;
21
22 /* Jump back to the main routine */
23 longjmp(return_buf, 1);
24
25 /* Not reached */
26 panic("longjmp failed\n");
27}
28
29static int lib_initjmp(struct unit_test_state *uts)
30{
31 int ret;
32 void *stack;
33 jmp_buf buf;
34 /* Arbitrary but smaller values (< page size?) fail on SANDBOX */
35 size_t stack_sz = 8192;
36
37 (void)entrypoint;
38
39 ep_entered = false;
40
41 stack = malloc(stack_sz);
42 ut_assertnonnull(stack);
43
44 /*
45 * Prepare return_buf so that entrypoint may jump back just after the
46 * if()
47 */
48 if (!setjmp(return_buf)) {
49 /* return_buf initialized, entrypoint not yet called */
50
51 /*
52 * Prepare another jump buffer to jump into entrypoint with the
53 * given stack
54 */
55 ret = initjmp(buf, entrypoint, stack, stack_sz);
56 ut_assertok(ret);
57
58 /* Jump into entrypoint */
59 longjmp(buf, 1);
60 /*
61 * Not reached since entrypoint is expected to branch after
62 * the if()
63 */
64 ut_assert(false);
65 }
66
67 ut_assert(ep_entered);
68
69 free(stack);
70
71 return 0;
72}
73LIB_TEST(lib_initjmp, 0);