v / vlib / goroutines / context_nix.c.v
47 lines · 41 sloc · 1.76 KB · 0480d0b9a920efc39d5ca3c43509a6cf6ebca274
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4//
5// Platform-specific context switching using ucontext (Linux, macOS, BSDs).
6// This provides the low-level mechanism for goroutine context switches,
7// analogous to Go's gogo/gosave assembly routines.
8module goroutines
9
10#flag -D_XOPEN_SOURCE=700
11#flag darwin -D_DARWIN_C_SOURCE
12#include "@VMODROOT/vlib/goroutines/context_nix.h"
13
14fn C.goroutines_context_alloc() voidptr
15fn C.goroutines_context_init(ctx voidptr, stack voidptr, stack_size int, entry_fn voidptr, arg voidptr)
16fn C.goroutines_context_switch(from voidptr, to voidptr)
17fn C.goroutines_context_set(to voidptr)
18
19// Context wraps ucontext_t for goroutine context switching.
20// The actual ucontext_t is heap-allocated in C to avoid issues with
21// ucontext_t being a typedef rather than a struct tag.
22pub struct Context {
23pub mut:
24 uctx voidptr // heap-allocated ucontext_t
25}
26
27// context_init initializes a context for a new goroutine.
28// Sets up the context to run `entry_fn` with `arg` on the given stack.
29pub fn context_init(mut ctx Context, stack voidptr, stack_size int, entry_fn fn (voidptr), arg voidptr) {
30 if ctx.uctx == unsafe { nil } {
31 ctx.uctx = C.goroutines_context_alloc()
32 }
33 C.goroutines_context_init(ctx.uctx, stack, stack_size, voidptr(entry_fn), arg)
34}
35
36// context_switch saves the current context into `from` and switches to `to`.
37pub fn context_switch(mut from Context, to &Context) {
38 if from.uctx == unsafe { nil } {
39 from.uctx = C.goroutines_context_alloc()
40 }
41 C.goroutines_context_switch(from.uctx, to.uctx)
42}
43
44// context_set switches to the given context without saving.
45pub fn context_set(to &Context) {
46 C.goroutines_context_set(to.uctx)
47}
48