Zth (libzth)
sjlj.h
Go to the documentation of this file.
1 #ifndef ZTH_CONTEXT_SJLJ_H
2 #define ZTH_CONTEXT_SJLJ_H
3 /*
4  * Zth (libzth), a cooperative userspace multitasking library.
5  * Copyright (C) 2019-2022 Jochem Rutgers
6  *
7  * This Source Code Form is subject to the terms of the Mozilla Public
8  * License, v. 2.0. If a copy of the MPL was not distributed with this
9  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
10  */
11 
12 #ifndef ZTH_CONTEXT_CONTEXT_H
13 # error This file must be included by libzth/context/context.h.
14 #endif
15 
16 #ifdef __cplusplus
17 
18 # include <csetjmp>
19 # include <csignal>
20 
21 namespace zth {
22 
23 class Context : public impl::ContextArch<Context> {
25 public:
26  typedef ContextArch<Context> base;
27 
28  constexpr explicit Context(ContextAttr const& attr) noexcept
29  : base(attr)
30  , m_env()
31  {}
32 
33 private:
34 # ifdef ZTH_OS_BAREMETAL
35  // As bare metal does not have signals, sigsetjmp and siglongjmp is not necessary.
36  typedef jmp_buf jmp_buf_type;
37 # define zth_sjlj_setjmp(env) ::setjmp(env)
38 # define zth_sjlj_longjmp(env, val) ::longjmp(env, val)
39 # else
40  typedef sigjmp_buf jmp_buf_type;
41 # define zth_sjlj_setjmp(env) ::sigsetjmp(env, Config::ContextSignals)
42 # define zth_sjlj_longjmp(env, val) ::siglongjmp(env, val)
43 # endif
44 
45 public:
46  int create() noexcept
47  {
48  int res = base::create();
49  if(res)
50  return res;
51 
52  if(unlikely(!stack()))
53  // Stackless fiber only saves current context; nothing to do.
54  return 0;
55 
57  void** sp_ = sp(stackUsable());
58  set_sp(m_env, sp_);
59  set_pc(m_env, reinterpret_cast<void*>(&context_trampoline_from_jmp_buf));
60  stack_push(sp_, this);
61  return 0;
62  }
63 
64  void context_switch(Context& to) noexcept
65  {
67 
68  if(zth_sjlj_setjmp(m_env) == 0) {
69  context_prepare_jmp(to, to.m_env);
70  zth_sjlj_longjmp(to.m_env, 1);
71  }
72 
74  }
75 
76 private:
77  jmp_buf_type m_env;
78 };
79 
80 } // namespace zth
81 #endif // __cplusplus
82 #endif // ZTH_CONTEXT_SJLJ_H
int create() noexcept
Definition: sjlj.h:46
ContextArch< Context > base
Definition: sjlj.h:26
impl::ContextArch< Context > base
Definition: sigaltstack.h:63
void context_switch(Context &to) noexcept
Definition: sjlj.h:64
sigjmp_buf m_env
Definition: sigaltstack.h:302
constexpr Context(ContextAttr const &attr) noexcept
Definition: sigaltstack.h:65
static void * sp() noexcept
Definition: arch_arm.h:116
static void stack_push(void **&sp, void *p) noexcept
Push data into the stack.
void context_pop_regs() noexcept
Post-sjlj context restoring.
Definition: context.h:501
Stack const & stack() const noexcept
Return the stack address.
Definition: context.h:252
static void set_sp(jmp_buf &env, void **sp) noexcept
Set the stack pointer in a jmp_buf.
static void context_trampoline_from_jmp_buf()
Entry point to jump to from a (sig)jmp_buf.
void context_prepare_jmp(Impl &to, jmp_buf &env) noexcept
Pre-sjlj jump.
Definition: context.h:506
static void set_pc(jmp_buf &env, void *sp) noexcept
Set the program counter in a jmp_buf.
int create() noexcept
Create context.
Definition: context.h:162
ContextAttr & attr() noexcept
Return the context attributes, requested by the user.
Definition: context.h:146
Stack const & stackUsable() const noexcept
Return the start of the actual usable stack.
Definition: context.h:260
void context_push_regs() noexcept
Pre-sjlj context saving.
Definition: context.h:496
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
Definition: allocator.h:114
Definition: allocator.h:23
#define zth_sjlj_setjmp(env)
Definition: sjlj.h:41
#define zth_sjlj_longjmp(env, val)
Definition: sjlj.h:42
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.
Definition: util.h:56