1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/x86/include/ucontext.h
2014-11-24 19:10:15 +01:00

175 lines
5.2 KiB
C

/*
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Coroutine helper functions. The base of the multi-threading system.
*
* @ingroup x86-multithreading
* @{
* @file
* @author René Kijewski <rene.kijewski@fu-berlin.de>
*/
#ifndef CPU__X86__UCONTEXT__HPP__
#define CPU__X86__UCONTEXT__HPP__
#include <stdlib.h>
#include <unistd.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Common stacksize for a signal handler.
*
* Do not use this variable.
* The standard wants us to define this variable, but you are better off the the RIOT specific macros.
*/
#define SIGSTKSZ (2048)
/**
* @brief General purpose registers of an x86 CPU.
*
* Used by ucontext_t.
* Application developers should not use this type directly.
*/
struct x86_pushad {
unsigned long ax, cx, dx, bx; /* field in ucontext_t: 3*4 -> 6*4 */
unsigned long sp, bp, si, di; /* field in ucontext_t: 7*4 -> 10*4 */
} __attribute__((packed));
/**
* @brief Opaque memory needed to store the x87 FPU state.
*
* Used by x86_threading.c.
* Application developers should not use this type directly.
* There is only enough room for the basic x87 state, not the multimedia extensions.
*/
struct x86_fxsave {
char opaque[512];
} __attribute__((packed, aligned(0x10)));
/**
* @brief Machine specific part of the corouting state.
*
* Used by ucontext_t.
* Application developers should not use this type directly.
*/
typedef struct mcontext {
unsigned long flags; /* field in ucontext_t: 2*4 */
struct x86_pushad registers; /* field in ucontext_t: 3*4 -> 10*4 */
void *ip; /* field in ucontext_t: 11*4 */
} __attribute__((packed)) mcontext_t;
/**
* @brief Stack assigned to a coroutine.
*
* Used by ucontext_t.
* Application developers need to set this values to make coroutines working.
*/
typedef struct stack {
void *ss_sp; /* field in ucontext_t: 0*4 */
//int ss_flags;
size_t ss_size; /* field in ucontext_t: 1*4 */
} __attribute__((packed)) stack_t;
/**
* @brief Extra data to perform an `iret`.
*
* Used by x86_interrupts.c to continue a thread
* if sched_context_switch_request was set set by an ISR.
* Application developers should not use this type directly.
*/
struct x86_interrupted_interrupt {
unsigned long ip;
unsigned long flags;
} __attribute__((packed));
/**
* @brief Datatype to enable coroutines in userspace.
*
* This datatype stores the machine state of a suspended coroutine.
*/
typedef struct ucontext {
stack_t uc_stack; /* field in ucontext_t: 0*4 - 1*4 */
mcontext_t uc_context; /* field in ucontext_t: 2*4 -> 11*4 */
struct ucontext *uc_link; /* field in ucontext_t: 12*4 */
//sigset_t uc_sigmask;
struct x86_interrupted_interrupt __intr;
struct x86_fxsave __fxsave;
} __attribute__((packed)) ucontext_t;
/**
* @brief Store current coroutine state.
*
* With setcontext() you can jump to this point of execution again.
* Take care about your stack, though.
* After your thread of execution left the function calling getcontext() there be dragons.
*
* The FPU registers are not stored!
*/
int getcontext(ucontext_t *ucp);
/**
* @brief Restore a coroutine state.
*
* The state must be set up by calling getcontext() or makecontext() previously.
* The FPU registers won't be restored.
*/
int setcontext(const ucontext_t *ucp) __attribute__((noreturn));
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
typedef void (*makecontext_fun_t)();
#pragma GCC diagnostic pop
/**
* @brief Create a coroutine / trampoline.
* @param[in] func Function to call.
* @param[in] argc Number of arguments for func. Must not exceed 5.
*
* The function arguments shall be passed after argc.
* The arguments have to be type punnable as an int,
* this includes integral types up to 4 bytes,
* but excludes int64_t, float and so on.
*
* Different from what the POSIX standard states,
* you do not have to getcontext() on ucp before calling makecontext().
* This function creates a whole new coroutine state / trampoline.
*/
void makecontext(ucontext_t *ucp, makecontext_fun_t func, int argc, ...);
/**
* @brief Swap coroutine.
* @param[out] oucp Memory to preserve current coroutine state in.
* @param[in] ucp Coroutine to execute next.
*
* This function is an atomic variant of getcontext() and setcontext().
* Same restrictions apply.
*/
int swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
#ifdef __cplusplus
}
#endif
#endif
/** @} */