Loading...
Searching...
No Matches
ucontext.h
1/*
2 * SPDX-FileCopyrightText: 2013-2016 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
3 * SPDX-FileCopyrightText: 2025 carl-tud
4 * SPDX-License-Identifier: LGPL-2.1-only
5 */
6
7#pragma once
8
9#if USE_LIBUCONTEXT
10# include <libucontext/libucontext.h>
11#else
12# include <ucontext.h>
13#endif /* USE_LIBUCONTEXT */
14
15#include <stdint.h>
16#include <stdbool.h>
17
18#ifdef __cplusplus
19extern "C" {
20#endif
21
26
27/* MARK: - Context accessors */
32
38static inline uintptr_t _context_get_fptr(ucontext_t *context) {
39# if defined(__FreeBSD__) /* FreeBSD */
40 return (uintptr_t)((struct sigcontext *)context)->sc_eip;
41# elif defined(__linux__) /* Linux */
42# if defined(__arm__)
43 return (uintptr_t)((ucontext_t *)context)->uc_mcontext.arm_pc;
44# elif defined(__x86_64__)
45 return (uintptr_t)((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP];
46# elif defined(__i386__)
47 return (uintptr_t)((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP];
48# else
49# error "Unsupported Linux architecture"
50# endif
51# else
52# error "Operating system unsupported"
53# endif
54}
55
61static inline void _context_set_fptr(ucontext_t *context, uintptr_t func) {
62# if defined(__FreeBSD__) /* FreeBSD */
63 ((struct sigcontext *)context)->sc_eip = (unsigned int)func;
64# elif defined(__linux__) /* Linux */
65# if defined(__arm__)
66 ((ucontext_t *)context)->uc_mcontext.arm_lr = func;
67 ((ucontext_t *)context)->uc_mcontext.arm_pc = func;
68# elif defined(__x86_64__)
69 ((ucontext_t *)context)->uc_mcontext.gregs[REG_RIP] = (greg_t)func;
70# elif defined(__i386__)
71 ((ucontext_t *)context)->uc_mcontext.gregs[REG_EIP] = func;
72# else
73# error "Unsupported Linux architecture"
74# endif
75# else
76# error "Operating system unsupported"
77# endif
78}
79
80
81/* MARK: - 64-bit support for makecontext */
86#if defined(__LP64__) || defined(DOXYGEN)
94extern void _start_task_func64(void);
95#endif
96
106static inline void makecontext64(ucontext_t *context, void (*func)(void), void* arg) {
107# if defined(__LP64__)
108 /* makecontext accepts int arguments. In RIOT, we use void* for the optional argument.
109 * To not truncate the argument pointer, we pass it in a register to _start_task_func64. */
110 makecontext(context, (void (*)(void))_start_task_func64, 0);
111
112# if defined(__x86_64__)
113# if defined(__linux__)
114 context->uc_mcontext.gregs[REG_R14] = (greg_t)func;
115 context->uc_mcontext.gregs[REG_R15] = (greg_t)arg;
116# endif
117# endif
118
119# else
120 /* On 32-bit platforms, the width of an int is enough to fit a pointer. */
121 makecontext(context, (void (*)(void))func, 1, arg);
122# endif
123}
124
125
127
128#ifdef __cplusplus
129}
130#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:61
static uintptr_t _context_get_fptr(ucontext_t *context)
Retrieves function pointer generated during calls to makecontext/setcontext/swapcontext
Definition ucontext.h:38
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:106