Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions lib/libc/powerpc64/gen/_ctx_start.S
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,27 @@
ld %r2,8(%r14)
ld %r14,0(%r14)
#else
/*
* The stack frame was already set up in makecontext(),
* so we can safely use the guaranteed fields here.
*
* Note we do step on the allocated stack frame's TOC,
* but since we never return from this function (i.e.
* never restore the stack frame) this should be safe.
*/
std %r2,24(%r1) /* save TOC */

/* Load global entry point */
mr %r12,%r14
#endif
mtlr %r14
blrl /* branch to start function */
mr %r3,%r15 /* pass pointer to ucontext as argument */
nop
#if defined(_CALL_ELF) && _CALL_ELF != 1
/* Restore TOC */
ld %r2,24(%r1)
#endif
bl CNAME(_ctx_done) /* branch to ctxt completion func */
/*
* we should never return from the
Expand Down
3 changes: 2 additions & 1 deletion lib/libc/powerpc64/gen/makecontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
*/
stackargs = (argc > 8) ? argc - 8 : 0;
sp = (char *) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size
- sizeof(uintptr_t)*(stackargs + 2);
- sizeof(uintptr_t)*(stackargs + 6);

Check failure on line 81 in lib/libc/powerpc64/gen/makecontext.c

View workflow job for this annotation

GitHub Actions / Style Checker

spaces required around that '*' (ctx:VxV)
sp = (char *)((uintptr_t)sp & ~0x1f);

mc = &ucp->uc_mcontext;
Expand Down Expand Up @@ -119,6 +119,7 @@
mc->mc_srr0 = *(uintptr_t *)_ctx_start;
#else
mc->mc_srr0 = (uintptr_t) _ctx_start;
mc->mc_gpr[12] = (uintptr_t) _ctx_start;/* required for prologue */
#endif
mc->mc_gpr[1] = (uintptr_t) sp; /* new stack pointer */
mc->mc_gpr[14] = (uintptr_t) start; /* r14 <- start */
Expand Down
4 changes: 2 additions & 2 deletions lib/libc/tests/sys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ ATF_TESTS_C+= brk_test
.endif
ATF_TESTS_C+= cpuset_test
ATF_TESTS_C+= errno_test
ATF_TESTS_C+= swapcontext_test
ATF_TESTS_C+= queue_test
ATF_TESTS_C+= sendfile_test

# TODO: clone, lwp_create, lwp_ctl, posix_fadvise, recvmmsg,
# swapcontext
# TODO: clone, lwp_create, lwp_ctl, posix_fadvise, recvmmsg
NETBSD_ATF_TESTS_C+= access_test
NETBSD_ATF_TESTS_C+= bind_test
NETBSD_ATF_TESTS_C+= chroot_test
Expand Down
63 changes: 63 additions & 0 deletions lib/libc/tests/sys/swapcontext_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*-
* Copyright (c) 2025 Raptor Computing Systems, LLC
*
* SPDX-License-Identifier: BSD-2-Clause
*/

#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <errno.h>

#include <atf-c.h>

#define STACK_SIZE (64ull << 10)

static volatile int callback_reached = 0;

static ucontext_t uctx_save, uctx_switch;

static void swapcontext_callback()
{
// Increment callback reached variable
// If this is called multiple times, we will fail the test
// If this is not called at all, we will fail the test
callback_reached++;
}

ATF_TC(swapcontext_basic);
ATF_TC_HEAD(swapcontext_basic, tc)
{
atf_tc_set_md_var(tc, "descr",
"Verify basic functionality of swapcontext");
}

ATF_TC_BODY(swapcontext_basic, tc)
{
char *stack;
int res;

stack = malloc(STACK_SIZE);
ATF_REQUIRE_MSG(stack != NULL, "malloc failed: %s", strerror(errno));
res = getcontext(&uctx_switch);
ATF_REQUIRE_MSG(res == 0, "getcontext failed: %s", strerror(errno));

uctx_switch.uc_stack.ss_sp = stack;
uctx_switch.uc_stack.ss_size = STACK_SIZE;
uctx_switch.uc_link = &uctx_save;
makecontext(&uctx_switch, swapcontext_callback, 0);

res = swapcontext(&uctx_save, &uctx_switch);

ATF_REQUIRE_MSG(res == 0, "swapcontext failed: %s", strerror(errno));
ATF_REQUIRE_MSG(callback_reached == 1,
"callback failed, reached %d times", callback_reached);
}

ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, swapcontext_basic);

return (atf_no_error());
}

Loading