Ruby 3.5.0dev (2025-01-10 revision 5fab31b15e32622c4b71d1d347a41937e9f9c212)
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
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 */