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

int setjmp(jmp_buf env)

prepare for a long jump

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()

void longjmp(jmp_buf env, int val)

long jump

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);