summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig6
-rw-r--r--CMakeLists.txt3
-rw-r--r--GNUmakefile10
-rw-r--r--cmd/srv9p/CMakeLists.txt42
-rw-r--r--lib9p/CMakeLists.txt10
-rw-r--r--lib9p/idl/2003-9P2000.p9p.9p.wip48
-rwxr-xr-xlib9p/tests/runtest45
-rw-r--r--lib9p/tests/test_server/CMakeLists.txt42
-rw-r--r--lib9p/tests/test_server/config/config.h (renamed from cmd/srv9p/config/config.h)0
-rw-r--r--lib9p/tests/test_server/main.c (renamed from cmd/srv9p/main.c)8
-rw-r--r--lib9p/tests/test_server/static/Documentation/x (renamed from cmd/srv9p/static/Documentation/x)0
-rw-r--r--lib9p/tests/test_server/static/README.md (renamed from cmd/srv9p/static/README.md)0
-rw-r--r--libcr/coroutine.c23
-rw-r--r--libcr_ipc/include/libcr_ipc/rpc.h6
-rw-r--r--libhw/host_net.c4
15 files changed, 182 insertions, 65 deletions
diff --git a/.editorconfig b/.editorconfig
index b95a6ff..8fb3a6f 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,6 +1,6 @@
# .editorconfig - How files in sbc-harness should be formatted
#
-# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later
root = true
@@ -30,10 +30,10 @@ _mode = markdown
[*.9p{,.wip}]
_mode = 9p
-[{cmd/srv9p/static.h.gen,build-aux/embed-sources.h.gen}]
+[{lib9p/tests/test_server/static.h.gen,build-aux/embed-sources.h.gen}]
_mode = sh
-[{build-aux/linux-errno.txt.gen,libusb/include/libusb/tusb_helpers.h.gen}]
+[{build-aux/linux-errno.txt.gen,libusb/include/libusb/tusb_helpers.h.gen,lib9p/tests/runtest}]
_mode = bash
[{lib9p/idl.gen,lib9p/include/lib9p/linux-errno.h.gen,build-aux/stack.c.gen}]
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e4f4d91..0c2a9e5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
# CMakeLists.txt - Main per-platform build script for sbc-harness project
#
-# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later
cmake_minimum_required(VERSION 3.30)
@@ -138,4 +138,3 @@ add_subdirectory(lib9p)
add_subdirectory(lib9p_util)
add_subdirectory(cmd/sbc_harness)
-add_subdirectory(cmd/srv9p)
diff --git a/GNUmakefile b/GNUmakefile
index 86008a0..ab28ede 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -60,7 +60,7 @@ generate-clean:
# `build` and `check` ##########################################################
-platforms := $(shell sed -nE 's/if *\(PICO_PLATFORM STREQUAL "(.*)"\)/\1/p' cmd/*/CMakeLists.txt)
+platforms := rp2040 host # $(shell sed -nE 's/if *\(PICO_PLATFORM STREQUAL "(.*)"\)/\1/p' cmd/*/CMakeLists.txt)
build_types = Debug Release RelWithDebInfo MinSizeRel
build: $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/build))
@@ -74,12 +74,12 @@ $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/build)): build/%
.PHONY: $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/build))
check: build
- $(MAKE) -j1 -k $(foreach t,$(build-types),$(foreach p,$(platforms),build/$p-$t/check))
+ $(MAKE) -j1 -k $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check))
.PHONY: check
-$(foreach t,$(build-types),$(foreach p,$(platforms),build/$p-$t/check)): build/%/check: build/%/Makefile
+$(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check)): build/%/check: build/%/Makefile
CTEST_OUTPUT_ON_FAILURE=1 $(MAKE) -C $(<D) test
-.PHONY: $(foreach t,$(build-types),$(foreach p,$(platforms),build/$p-$t/check))
+.PHONY: $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check))
# `lint` and `format` ##########################################################
@@ -120,7 +120,7 @@ lint/unknown: lint/%:
@printf "%s: cannot lint unknown file type\n" $(sources_$*) >&2
lint/all: lint/%:
$(eval export sources_$*)
- @find $$(printf '%s\n' $${sources_$*} | grep -vE '^cmd/[^/]+/static/') \
+ @find $$(printf '%s\n' $${sources_$*} | grep -vE '^lib9p/tests/[^/]+/static/') \
-maxdepth 0 -type f | \
{ r=0; while read -r filename; do \
if ! grep -E -q 'Copyright \(C\) 202[4-9]((-|, )202[5-9])* Luke T. Shumaker' $$filename; then \
diff --git a/cmd/srv9p/CMakeLists.txt b/cmd/srv9p/CMakeLists.txt
deleted file mode 100644
index 0d8e320..0000000
--- a/cmd/srv9p/CMakeLists.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-# cmd/srv9p/CMakeLists.txt - Build script for srv9p test/dev executable
-#
-# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
-# SPDX-License-Identifier: AGPL-3.0-or-later
-
-if (PICO_PLATFORM STREQUAL "host")
-
-# Compile ######################################################################
-
-add_library(srv9p_objs OBJECT
- main.c
-)
-target_include_directories(srv9p_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config)
-target_include_directories(srv9p_objs PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
-target_link_libraries(srv9p_objs
- libcr
- libcr_ipc
- libmisc
- lib9p
- lib9p_util
-)
-
-# Analyze the stack ############################################################
-
-add_stack_analysis(srv9p_stack.c srv9p_objs)
-
-# Link #########################################################################
-
-add_executable(srv9p)
-target_sources(srv9p PRIVATE
- srv9p_stack.c
- "$<TARGET_OBJECTS:srv9p_objs>"
-)
-
-# Embed ########################################################################
-
-target_embed_sources(srv9p_objs srv9p static.h
- static/README.md
- static/Documentation/x
-)
-
-endif()
diff --git a/lib9p/CMakeLists.txt b/lib9p/CMakeLists.txt
index 488cff9..2f5fc70 100644
--- a/lib9p/CMakeLists.txt
+++ b/lib9p/CMakeLists.txt
@@ -1,6 +1,6 @@
# lib9p/CMakeLists.txt - TODO
#
-# Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later
add_library(lib9p INTERFACE)
@@ -15,3 +15,11 @@ target_link_libraries(lib9p INTERFACE
libmisc
libhw
)
+
+if (ENABLE_TESTS)
+ add_subdirectory(tests/test_server)
+ add_test(
+ NAME "lib9p/runtest"
+ COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/tests/runtest"
+ )
+endif()
diff --git a/lib9p/idl/2003-9P2000.p9p.9p.wip b/lib9p/idl/2003-9P2000.p9p.9p.wip
new file mode 100644
index 0000000..c42584f
--- /dev/null
+++ b/lib9p/idl/2003-9P2000.p9p.9p.wip
@@ -0,0 +1,48 @@
+# lib9p/idl/2003-9P2000.p9p.9p - Definitions of plan9port extension messages
+#
+# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+# Plan 9 from User Space (a.k.a. plan9port)'s lib9pclient:fsopenfd(3)
+# and 9pserve(4) proxy server (which takes the place of the Plan 9
+# kernel) add a special-purpose `openfd` command to 9P2000.
+#
+# https://9fans.github.io/plan9port/man/man9/openfd.htlm
+# https://github.com/9fans/plan9port/blob/master/man/man9/openfd.9p
+# https://github.com/9fans/plan9port/commit/32f69c36e0eec1227934bbd34854bfebd88686f2
+# https://github.com/9fans/plan9port/pull/692
+
+# BUG: There is no version-string for this extension; plan9port still
+# calls it vanilla "9P2000".
+
+from ./2002-9P2000.9p import *
+
+# On Plan 9 the usual 9P client is the kernel, not normal userspace
+# programs. The kernel multiplexes multiple userspace processes onto
+# a single 9P connection; the userspace programs make 9P calls by
+# making syscalls. plan9port emulates this by having mock syscalls
+# that make 9P client calls over an AF_UNIX socket to a local
+# `9pserve` daemon that does the multiplexing (you add an "fs" prefix;
+# e.g. you replace syscall:`open()` with lib9pclient:`fsopen()`).
+#
+# "Unfortunately", programs in plan9port must deal both with 9P files
+# and native "Unix" files; and need to turn an 9P FID into a native
+# file descriptor. To do this, the `9pserve` program and lib9pclient
+# add an extension call to 9P2000: Topenfd/Ropenfd/fsopenfd().
+#
+# An AF_UNIX socket has the ability to send a file descriptor over it
+# via an out-of-band "socket control message" ("CMSG" or "SCM").
+#
+# Topenfd asks 9pserve to create a socketpair() file descriptor that
+# 9pserve will pump to/from a FID, and then send that pipe file
+# descriptor over a control-message to the client program.
+#
+# When replying, the server sends not just an in-band Ropenfd message,
+# but also an out-of-band control-message with a socketpair() file
+# descriptor. A successful call results in the FID being clunked.
+msg Topenfd = "size[4,val=end-&size] typ[1,val=98] tag[tag] fid[fid] mode[o]"
+msg Ropenfd = "size[4,val=end-&size] typ[1,val=98] tag[tag] qid[qid] iounit[4] unixfd[4]"
+# BUG: The "unixfd" field nominally indicates the the file descriptor
+# of the pipe, but really 9pserve doesn't know which FD it will end up
+# on the client process, and lib9pclient ignores the value here and
+# overwrites it with the file descriptor indicated from the CMSG
diff --git a/lib9p/tests/runtest b/lib9p/tests/runtest
new file mode 100755
index 0000000..29d2089
--- /dev/null
+++ b/lib9p/tests/runtest
@@ -0,0 +1,45 @@
+#!/usr/bin/env bash
+# lib9p/tests/runtest - TODO
+#
+# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+set -euE -o pipefail
+set -x
+
+valgrind --error-exitcode=2 ./tests/test_server/test_server &
+server_pid=$!
+# shellcheck disable=SC2064
+trap "kill $server_pid || true; wait $server_pid || true" EXIT
+server_addr='localhost:9000'
+
+client=(9p -a "$server_addr")
+
+expect_lines() (
+ { set +x; } &>/dev/null
+ printf >&2 '+ diff -u expected.txt actual.txt\n'
+ diff -u <(printf '%s\n' "$@") <(printf '%s\n' "$out")
+)
+
+while [[ -d /proc/$server_pid && "$(readlink /proc/$server_pid/fd/4 2>/dev/null)" != socket:* ]]; do sleep 0.1; done
+
+out=$("${client[@]}" ls -l '')
+expect_lines \
+ 'd-r-xr-xr-x M 0 root root 0 Oct 7 15:51 Documentation' \
+ '--r--r--r-- M 0 root root 14 Oct 7 15:51 README.md'
+
+out=$("${client[@]}" ls -l 'Documentation/')
+expect_lines \
+ '--r--r--r-- M 0 root root 4 Oct 7 15:51 x'
+
+out=$("${client[@]}" read 'README.md')
+expect_lines \
+ 'Hello, world!'
+
+out=$("${client[@]}" read 'Documentation/x')
+expect_lines \
+ 'foo'
+
+out=$("${client[@]}" stat 'Documentation/x')
+expect_lines \
+ "'x' 'root' 'root' 'root' q (0000000000000009 1 ) m 0444 at 1728337905 mt 1728337904 l 4 t 0 d 0"
diff --git a/lib9p/tests/test_server/CMakeLists.txt b/lib9p/tests/test_server/CMakeLists.txt
new file mode 100644
index 0000000..a107b75
--- /dev/null
+++ b/lib9p/tests/test_server/CMakeLists.txt
@@ -0,0 +1,42 @@
+# lib9p/tests/test_server/CMakeLists.txt - Build script for test_server executable
+#
+# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+if (PICO_PLATFORM STREQUAL "host")
+
+# Compile ######################################################################
+
+add_library(test_server_objs OBJECT
+ main.c
+)
+target_include_directories(test_server_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config)
+target_include_directories(test_server_objs PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
+target_link_libraries(test_server_objs
+ libcr
+ libcr_ipc
+ libmisc
+ lib9p
+ lib9p_util
+)
+
+# Analyze the stack ############################################################
+
+add_stack_analysis(test_server_stack.c test_server_objs)
+
+# Link #########################################################################
+
+add_executable(test_server)
+target_sources(test_server PRIVATE
+ test_server_stack.c
+ "$<TARGET_OBJECTS:test_server_objs>"
+)
+
+# Embed ########################################################################
+
+target_embed_sources(test_server_objs test_server static.h
+ static/README.md
+ static/Documentation/x
+)
+
+endif()
diff --git a/cmd/srv9p/config/config.h b/lib9p/tests/test_server/config/config.h
index 4f8384e..4f8384e 100644
--- a/cmd/srv9p/config/config.h
+++ b/lib9p/tests/test_server/config/config.h
diff --git a/cmd/srv9p/main.c b/lib9p/tests/test_server/main.c
index b5cb122..a6e4eeb 100644
--- a/cmd/srv9p/main.c
+++ b/lib9p/tests/test_server/main.c
@@ -1,6 +1,6 @@
-/* srv9p/main.c - Main entry point for test 9P server
+/* lib9p/tests/test_server/main.c - Main entry point for test 9P server
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -107,17 +107,17 @@ struct lib9p_srv srv = {
static COROUTINE init_cr(void *) {
cr_begin();
+ sleep_for_ms(1);
+
for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++) {
char name[] = {'r', 'e', 'a', 'd', '-', hexdig[i], '\0'};
if (!coroutine_add(name, read_cr, &srv))
error(1, 0, "coroutine_add(read_cr, &srv)");
- sleep_for_s(1);
}
for (int i = 0; i < 2*CONFIG_SRV9P_NUM_CONNS; i++) {
char name[] = {'w', 'r', 'i', 't', 'e', '-', hexdig[i], '\0'};
if (!coroutine_add(name, lib9p_srv_write_cr, &srv))
error(1, 0, "coroutine_add(lib9p_srv_write_cr, &srv)");
- sleep_for_s(1);
}
cr_exit();
diff --git a/cmd/srv9p/static/Documentation/x b/lib9p/tests/test_server/static/Documentation/x
index 257cc56..257cc56 100644
--- a/cmd/srv9p/static/Documentation/x
+++ b/lib9p/tests/test_server/static/Documentation/x
diff --git a/cmd/srv9p/static/README.md b/lib9p/tests/test_server/static/README.md
index af5626b..af5626b 100644
--- a/cmd/srv9p/static/README.md
+++ b/lib9p/tests/test_server/static/README.md
diff --git a/libcr/coroutine.c b/libcr/coroutine.c
index 129f4da..73460b7 100644
--- a/libcr/coroutine.c
+++ b/libcr/coroutine.c
@@ -1,6 +1,6 @@
/* libcr/coroutine.c - Simple embeddable coroutine implementation
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -158,9 +158,19 @@ static_assert(CONFIG_COROUTINE_NUM > 1);
#define _CR_SIG_GDB SIGWINCH
#endif
+#if CONFIG_COROUTINE_VALGRIND
+ /* Hack around a bug in Valgrind where it runs the
+ * sigsuspend(tmp_sigmask)-triggered handler function with the
+ * original mask, not the `tmp_mask`. */
+ static bool _cr_plat_in_sigsuspend = false;
+#endif
+
bool cr_plat_is_in_intrhandler(void) {
+#if CONFIG_COROUTINE_VALGRIND
+ if (_cr_plat_in_sigsuspend)
+ return true;
+#endif
sigset_t cur_mask;
- sigfillset(&cur_mask);
sigprocmask(0, NULL, &cur_mask);
if (sigismember(&cur_mask, _CR_SIG_SENTINEL))
/* Interrupts are disabled, so we cannot be in
@@ -184,10 +194,13 @@ static_assert(CONFIG_COROUTINE_NUM > 1);
assert(!_cr_plat_are_interrupts_enabled());
sigset_t set;
sigemptyset(&set);
+#if CONFIG_COROUTINE_VALGRIND
+ _cr_plat_in_sigsuspend = true;
+#endif
sigsuspend(&set);
-
- sigfillset(&set);
- sigprocmask(SIG_SETMASK, &set, NULL);
+#if CONFIG_COROUTINE_VALGRIND
+ _cr_plat_in_sigsuspend = false;
+#endif
}
bool _cr_plat_save_and_disable_interrupts(void) {
assert(!cr_plat_is_in_intrhandler());
diff --git a/libcr_ipc/include/libcr_ipc/rpc.h b/libcr_ipc/include/libcr_ipc/rpc.h
index 0d6d25e..80eee74 100644
--- a/libcr_ipc/include/libcr_ipc/rpc.h
+++ b/libcr_ipc/include/libcr_ipc/rpc.h
@@ -1,6 +1,6 @@
/* libcr_ipc/rpc.h - Simple request/response system for libcr
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -120,8 +120,10 @@
.cid = cr_getcid(), \
}; \
_cr_ipc_sll_push_to_rear(&ch->waiting_reqs, &self); \
- if (ch->waiting_resps.front) \
+ if (ch->waiting_resps.front) { \
cr_unpause(_cr_ipc_sll_node_cast(struct _##NAME##_waiting_resp, ch->waiting_resps.front)->cid); \
+ _cr_ipc_sll_pop_from_front(&ch->waiting_resps); \
+ } \
cr_pause_and_yield(); \
return resp; \
} \
diff --git a/libhw/host_net.c b/libhw/host_net.c
index 917e764..d5a5ad5 100644
--- a/libhw/host_net.c
+++ b/libhw/host_net.c
@@ -1,6 +1,6 @@
/* libhw/host_net.c - <libhw/generic/net.h> implementation for hosted glibc
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -66,9 +66,11 @@ static void hostnet_init(void) {
static inline bool RUN_PTHREAD(void *(*fn)(void *), void *args) {
pthread_t thread;
+ bool saved = cr_save_and_disable_interrupts();
if (pthread_create(&thread, NULL, fn, args))
return true;
cr_pause_and_yield();
+ cr_restore_interrupts(saved);
if (pthread_join(thread, NULL))
return true;
return false;