Ruby: coroutine/ppc/Context.h Source File

Ruby 3.2.5p208 (2024-07-26 revision 31d0f1a2e7dbfb60731d1f05b868e1d578cda493)

Context.h
1#ifndef COROUTINE_PPC_CONTEXT_H
2#define COROUTINE_PPC_CONTEXT_H 1
3
4#pragma once
5
6#include <assert.h>
7#include <stddef.h>
8#include <stdint.h>
9#include <string.h>
10
11#define COROUTINE __attribute__((noreturn)) void
12#define COROUTINE_LIMITED_ADDRESS_SPACE
13
14enum {
15 COROUTINE_REGISTERS =
16 20 /* 19 general purpose registers (r13–r31) and 1 return address */
17 + 4 /* space for fiber_entry() to store the link register */
18};
19
20struct coroutine_context
21{
22 void **stack_pointer;
23 void *argument;
24};
25
26typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
27
28static inline void coroutine_initialize_main(struct coroutine_context * context) {
29 context->stack_pointer = NULL;
30}
31
32static inline void coroutine_initialize(
33 struct coroutine_context *context,
34 coroutine_start start,
35 void *stack,
36 size_t size
37) {
38 assert(start && stack && size >= 1024);
39
40 // Stack grows down. Force 16-byte alignment.
41 char * top = (char*)stack + size;
42 context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
43
44 context->stack_pointer -= COROUTINE_REGISTERS;
45 memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
46
47 /* Skip a global prologue that sets the TOC register */
48 context->stack_pointer[19] = ((char*)start) + 8;
49}
50
51struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
52
53static inline void coroutine_destroy(struct coroutine_context * context)
54{
55 context->stack_pointer = NULL;
56}
57
58#endif /* COROUTINE_PPC_CONTEXT_H */
assert.h
coroutine_context
Definition Context.h:36