Loading...
Searching...
No Matches
ucontext.h
1/*
2 * Copyright (C) 2013 - 2016 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
3 * Copyright (C) 2025 carl-tud
4 *
5 * This file is subject to the terms and conditions of the GNU Lesser
6 * General Public License v2.1. See the file LICENSE in the top level
7 * directory for more details.
8 */
9
10#pragma once
11
12#if USE_LIBUCONTEXT
13# include <libucontext/libucontext.h>
14#else
15# include <ucontext.h>
16#endif /* USE_LIBUCONTEXT */
17
18#include <stdint.h>
19#include <stdbool.h>
20
21#ifdef __cplusplus
22extern "C" {
23#endif
24
29
30/* MARK: - Context accessors */
35
41static inline uintptr_t _context_get_fptr(ucontext_t *context) {
42# if defined(__FreeBSD__) /* FreeBSD */
43 return (uintptr_t)((struct sigcontext *)context)->sc_eip;
44# elif defined(__linux__) /* Linux */
45# if defined(__arm__)
46 return (uintptr_t)((ucontext_t *)context)->uc_mcontext.arm_pc;
47# elif defined(__x86_64__)
48 return (uintptr_t)((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP];
49# elif defined(__i386__)
50 return (uintptr_t)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP];
51# else
52# error "Unsupported Linux architecture"
53# endif
54# else
55# error "Operating system unsupported"
56# endif
57}
58
64static inline void _context_set_fptr(ucontext_t *context, uintptr_t func) {
65# if defined(__FreeBSD__) /* FreeBSD */
66 ((struct sigcontext *)context)->sc_eip = (unsigned int)func;
67# elif defined(__linux__) /* Linux */
68# if defined(__arm__)
69 ((ucontext_t *)context)->uc_mcontext.arm_lr = func;
70 ((ucontext_t *)context)->uc_mcontext.arm_pc = func;
71# elif defined(__x86_64__)
72 ((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP] = (greg_t)func;
73# elif defined(__i386__)
74 ((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP] = func;
75# else
76# error "Unsupported Linux architecture"
77# endif
78# else
79# error "Operating system unsupported"
80# endif
81}
82
83
84/* MARK: - 64-bit support for makecontext */
89#if defined(__LP64__) || defined(DOXYGEN)
97extern void _start_task_func64(void);
98#endif
99
109static inline void makecontext64(ucontext_t *context, void (*func)(void), void* arg) {
110# if defined(__LP64__)
111 /* makecontext accepts int arguments. In RIOT, we use void* for the optional argument.
112 * To not truncate the argument pointer, we pass it in a register to _start_task_func64. */
113 makecontext(context, (void (*)(void))_start_task_func64, 0);
114
115# if defined(__x86_64__)
116# if defined(__linux__)
117 context->uc_mcontext.gregs[REG_R14] = (greg_t)func;
118 context->uc_mcontext.gregs[REG_R15] = (greg_t)arg;
119# endif
120# endif
121
122# else
123 /* On 32-bit platforms, the width of an int is enough to fit a pointer. */
124 makecontext(context, (void (*)(void))func, 1, arg);
125# endif
126}
127
128
130
131#ifdef __cplusplus
132}
133#endif
void _start_task_func64(void)
Invokes thread task function.
static void _context_set_fptr(ucontext_t *context, uintptr_t func)
Retrieves function pointer generated during calls to makecontext/setcontext/swapcontext
Definition ucontext.h:64
static uintptr_t _context_get_fptr(ucontext_t *context)
Retrieves function pointer generated during calls to makecontext/setcontext/swapcontext
Definition ucontext.h:41
static void makecontext64(ucontext_t *context, void(*func)(void), void *arg)
Like makecontext, allows 64-bit wide function argument on 64-bit platforms.
Definition ucontext.h:109