Ruby 3.5.0dev (2025-01-10 revision 5fab31b15e32622c4b71d1d347a41937e9f9c212)
Context.h
1#ifndef COROUTINE_PPC64LE_CONTEXT_H
2#define COROUTINE_PPC64LE_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
13enum {
14 COROUTINE_REGISTERS =
15 20 /* 18 general purpose registers (r14-r31), 1 special register (cr) and 1 return address */
16 + 4 /* space for fiber_entry() to store the link register */
17};
18
20{
21 void **stack_pointer;
22 void *argument;
23};
24
25typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
26
27static inline void coroutine_initialize_main(struct coroutine_context * context) {
28 context->stack_pointer = NULL;
29}
30
31static inline void coroutine_initialize(
32 struct coroutine_context *context,
33 coroutine_start start,
34 void *stack,
35 size_t size
36) {
37 assert(start && stack && size >= 1024);
38
39 // Stack grows down. Force 16-byte alignment.
40 char * top = (char*)stack + size;
41 context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
42
43 context->stack_pointer -= COROUTINE_REGISTERS;
44 memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
45
46 /* Skip a global prologue that sets the TOC register */
47 context->stack_pointer[18] = ((char*)start) + 8;
48}
49
50struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
51
52static inline void coroutine_destroy(struct coroutine_context * context)
53{
54 context->stack_pointer = NULL;
55}
56
57#endif /* COROUTINE_PPC64LE_CONTEXT_H */