Ruby 4.1.0dev (2026-09-22 revision 1f717ae3d6ca76015582dc610e892be1aacb905b)
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 + 18 /* non-volatile FP registers f14-f31 */
17 + 24 /* non-volatile vector registers v20-v31, 16 bytes each */
18 + 4 /* space for fiber_entry() to store the link register */
19};
20
22{
23 void **stack_pointer;
24 void *argument;
25};
26
27typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
28
29static inline void coroutine_initialize_main(struct coroutine_context * context) {
30 context->stack_pointer = NULL;
31}
32
33static inline void coroutine_initialize(
34 struct coroutine_context *context,
35 coroutine_start start,
36 void *stack,
37 size_t size
38) {
39 assert(start && stack && size >= 1024);
40
41 // Stack grows down. Force 16-byte alignment.
42 char * top = (char*)stack + size;
43 context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
44
45 context->stack_pointer -= COROUTINE_REGISTERS;
46 memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
47
48 /* Skip a global prologue that sets the TOC register */
49 context->stack_pointer[18] = ((char*)start) + 8;
50}
51
52struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
53
54static inline void coroutine_destroy(struct coroutine_context * context)
55{
56 context->stack_pointer = NULL;
57}
58
59#endif /* COROUTINE_PPC64LE_CONTEXT_H */