Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

Context.h
Go to the documentation of this file.
1 /*
2 * This file is part of the "Coroutine" project and released under the MIT License.
3 *
4 * Created by Samuel Williams on 24/6/2019.
5 * Copyright, 2019, by Samuel Williams. All rights reserved.
6 */
7
8 #pragma once
9
10 #include <assert.h>
11 #include <stddef.h>
12 #include <ucontext.h>
13
14 #define COROUTINE __attribute__((noreturn)) void
15
16 #if INTPTR_MAX <= INT32_MAX
17 #define COROUTINE_LIMITED_ADDRESS_SPACE
18 #endif
19
20 struct coroutine_context
21 {
22 ucontext_t state;
23 struct coroutine_context * from;
24 };
25
26 typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
27
28 COROUTINE coroutine_trampoline(void * _start, void * _context);
29
30 static inline void coroutine_initialize_main(struct coroutine_context * context) {
31 context->from = NULL;
32 getcontext(&context->state);
33 }
34
35 static inline void coroutine_initialize(
36 struct coroutine_context *context,
37 coroutine_start start,
38 void *stack,
39 size_t size
40 ) {
41 assert(start && stack && size >= 1024);
42
43 coroutine_initialize_main(context);
44
45 context->state.uc_stack.ss_size = size;
46 // Despite what it's called, this is not actually a stack pointer. It points to the address of the stack allocation (the lowest address).
47 context->state.uc_stack.ss_sp = (char*)stack;
48 context->state.uc_stack.ss_flags = 0;
49 context->state.uc_link = NULL;
50
51 makecontext(&context->state, (void(*)(void))coroutine_trampoline, 2, (void*)start, (void*)context);
52 }
53
54 static inline struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target)
55 {
56 struct coroutine_context * previous = target->from;
57
58 target->from = current;
59 swapcontext(&current->state, &target->state);
60 target->from = previous;
61
62 return target;
63 }
64
65 static inline void coroutine_destroy(struct coroutine_context * context)
66 {
67 context->state.uc_stack.ss_sp = NULL;
68 context->state.uc_stack.ss_size = 0;
69 context->from = NULL;
70 }
COROUTINE
#define COROUTINE
Definition: Context.h:14
coroutine_context::stack
void * stack
Definition: Context.h:29
assert
#define assert(x)
Definition: dlmalloc.c:1176
ucontext_t
ucontext_t
Definition: rb_mjit_min_header-2.7.0.h:2335
coroutine_context::state
jmp_buf state
Definition: Context.h:35
assert.h
NULL
#define NULL
Definition: _sdbm.c:101
coroutine_start
COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self)
Definition: Context.h:22
coroutine_context::state
ucontext_t state
Definition: Context.h:22
coroutine_context::from
struct coroutine_context * from
Definition: Context.h:37
size
int size
Definition: encoding.c:58
coroutine_context
Definition: Context.h:17
coroutine_transfer
struct coroutine_context * coroutine_transfer(struct coroutine_context *current, struct coroutine_context *target)
Definition: Context.c:115
coroutine_trampoline
COROUTINE coroutine_trampoline(void *_start, void *_context)
Definition: Context.c:16