summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig51
-rw-r--r--3rd-party/linux-errno.txt2
-rw-r--r--CMakeLists.txt2
-rw-r--r--GNUmakefile58
-rw-r--r--PLAN.md14
-rwxr-xr-xbuild-aux/embed-sources.h.gen4
-rwxr-xr-xbuild-aux/lint-bin15
-rwxr-xr-xbuild-aux/lint-generic2
-rwxr-xr-xbuild-aux/lint-h6
-rwxr-xr-xbuild-aux/valgrind15
-rw-r--r--cmd/sbc_harness/main.c1
-rw-r--r--lib9p/include/lib9p/9p.generated.h2
-rw-r--r--lib9p/include/lib9p/9p.h2
-rw-r--r--lib9p/include/lib9p/linux-errno.h2
-rw-r--r--lib9p/include/lib9p/srv.h2
-rwxr-xr-xlib9p/linux-errno.txt.gen (renamed from build-aux/linux-errno.txt.gen)4
-rw-r--r--lib9p/protogen/h.py2
-rw-r--r--lib9p/srv.c3
-rw-r--r--lib9p/tables.c8
-rwxr-xr-xlib9p/tests/runtest6
-rw-r--r--lib9p/tests/test_server/CMakeLists.txt1
-rw-r--r--lib9p/tests/test_server/fs_shutdown.c93
-rw-r--r--lib9p/tests/test_server/fs_shutdown.h23
-rw-r--r--lib9p/tests/test_server/main.c102
-rw-r--r--libcr/CMakeLists.txt2
-rw-r--r--libcr_ipc/CMakeLists.txt1
-rw-r--r--libcr_ipc/_linkedlist.h51
-rw-r--r--libcr_ipc/chan.c16
-rw-r--r--libcr_ipc/include/libcr_ipc/_linkedlist_pub.h26
-rw-r--r--libcr_ipc/include/libcr_ipc/chan.h7
-rw-r--r--libcr_ipc/include/libcr_ipc/mutex.h5
-rw-r--r--libcr_ipc/include/libcr_ipc/rpc.h5
-rw-r--r--libcr_ipc/include/libcr_ipc/rwmutex.h5
-rw-r--r--libcr_ipc/include/libcr_ipc/sema.h5
-rw-r--r--libcr_ipc/mutex.c10
-rw-r--r--libcr_ipc/rpc.c18
-rw-r--r--libcr_ipc/rwmutex.c29
-rw-r--r--libcr_ipc/sema.c18
-rw-r--r--libmisc/CMakeLists.txt1
-rw-r--r--libmisc/include/libmisc/linkedlist.h46
-rw-r--r--libmisc/include/libmisc/macro.h13
-rw-r--r--libmisc/linkedlist.c (renamed from libcr_ipc/_linkedlist.c)16
-rw-r--r--libusb/include/libusb/tusb_helpers.h2
-rwxr-xr-xlibusb/include/libusb/tusb_helpers.h.gen21
-rw-r--r--notes.md4
45 files changed, 389 insertions, 332 deletions
diff --git a/.editorconfig b/.editorconfig
index f907b33..23d17cc 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -15,6 +15,8 @@ indent_style = tab
insert_final_newline = true
trim_trailing_whitespace = true
+# By well-known name ###########################################################
+
[*.{c,h}]
_mode = c
@@ -27,20 +29,6 @@ _mode = cmake
[*.md]
_mode = markdown
-[*.9p{,.wip}]
-_mode = 9p
-
-[{lib9p/tests/test_server/static.h.gen,build-aux/embed-sources.h.gen,build-aux/lint-{generic,unknown},lib9p/tests/test_compile.c.gen}]
-_mode = sh
-
-[{build-aux/lint-h,build-aux/lint-bin,build-aux/get-dscname,build-aux/linux-errno.txt.gen,libusb/include/libusb/tusb_helpers.h.gen,lib9p/tests/runtest}]
-_mode = bash
-
-[{lib9p/proto.gen,lib9p/include/lib9p/linux-errno.h.gen,build-aux/stack.c.gen}]
-_mode = python3
-indent_style = space
-indent_size = 4
-
[*.py]
_mode = python3
indent_style = space
@@ -49,11 +37,40 @@ indent_size = 4
[requirements.txt]
_mode = pip
-[**/Documentation/**.txt]
-_mode = man-cat
-
[{.editorconfig,.gitmodules,.pylintrc}]
_mode = ini
[.gitignore]
_mode = gitignore
+
+# By specific filename (non-lib9p) #############################################
+
+[{build-aux/lint-{generic,unknown},build-aux/embed-sources.h.gen}]
+_mode = sh
+
+[{build-aux/lint-{bin,h},build-aux/get-dscname,build-aux/valgrind,libusb/include/libusb/tusb_helpers.h.gen}]
+_mode = bash
+
+[build-aux/stack.c.gen]
+_mode = python3
+indent_style = space
+indent_size = 4
+
+[**/Documentation/**.txt]
+_mode = man-cat
+
+# By specific filename (lib9p) #################################################
+
+[lib9p/idl/*.9p{,.wip}]
+_mode = 9p-idl
+
+[{lib9p/tests/test_server/static.h.gen,lib9p/tests/test_compile.c.gen}]
+_mode = sh
+
+[{lib9p/linux-errno.txt.gen,lib9p/tests/runtest}]
+_mode = bash
+
+[{lib9p/proto.gen,lib9p/include/lib9p/linux-errno.h.gen}]
+_mode = python3
+indent_style = space
+indent_size = 4
diff --git a/3rd-party/linux-errno.txt b/3rd-party/linux-errno.txt
index 839efc2..5b450f0 100644
--- a/3rd-party/linux-errno.txt
+++ b/3rd-party/linux-errno.txt
@@ -1,4 +1,4 @@
-# 3rd-party/linux-errno.txt - Generated from build-aux/linux-errno.txt.gen and linux.git v6.7. DO NOT EDIT!
+# 3rd-party/linux-errno.txt - Generated from lib9p/linux-errno.txt.gen and linux.git v6.14. DO NOT EDIT!
1 EPERM Operation not permitted
2 ENOENT No such file or directory
3 ESRCH No such process
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 22756c1..9fa048f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -112,7 +112,7 @@ function(add_lib_test arg_libname arg_testname)
target_include_directories("${arg_testname}" PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/tests)
add_test(
NAME "${arg_libname}/${arg_testname}"
- COMMAND valgrind --error-exitcode=2 "./${arg_testname}"
+ COMMAND "${CMAKE_SOURCE_DIR}/build-aux/valgrind" "./${arg_testname}"
)
endif()
endfunction()
diff --git a/GNUmakefile b/GNUmakefile
index f6ff6c3..4183e37 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -34,7 +34,7 @@ generate/files += 3rd-party/COPYING.newlib.txt
cp $< $@
generate/files += 3rd-party/linux-errno.txt
-3rd-party/linux-errno.txt: build-aux/linux-errno.txt.gen
+3rd-party/linux-errno.txt: lib9p/linux-errno.txt.gen
$< $(linux.git) $@
generate/files += lib9p/include/lib9p/linux-errno.h
@@ -78,9 +78,6 @@ generate-clean:
platforms := rp2040 host # $(shell sed -nE 's/if *\(PICO_PLATFORM STREQUAL "(.*)"\)/\1/p' cmd/*/CMakeLists.txt)
build_types = Debug Release RelWithDebInfo MinSizeRel
-export CTEST_PARALLEL_LEVEL = 0
-export CTEST_OUTPUT_ON_FAILURE = 1
-
build: $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/build))
.PHONY: build
@@ -91,12 +88,12 @@ $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/build)): build/%
$(MAKE) -C $(<D)
.PHONY: $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/build))
-check: build
- $(MAKE) -j1 -k INNER=t $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check))
+check:
+ $(MAKE) -k INNER=t $(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
- $(MAKE) -C $(<D) test
+$(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check)): build/%/check: build/%/build
+ +cd $(@D) && ctest --output-on-failure $(if $(filter --jobserver-auth=%,$(MAKEFLAGS)),--parallel)
.PHONY: $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/check))
# `lint` and `format` ##########################################################
@@ -109,15 +106,25 @@ build-aux/venv: build-aux/requirements.txt
$@/bin/pip install -r $<
touch --no-create $@
-# `lint` ###########
+# `lint` ###############################
+# generic ##########
lint:
$(MAKE) -k INNER=t $(patsubst sources_%,lint/%,$(filter sources_%,$(.VARIABLES)))
# Only lint binaries if the build scripts pass lint.
$(MAKE) INNER=t lint/bin
lint/bin: build build-aux/lint-bin
./build-aux/lint-bin $(foreach t,$(build_types),build/rp2040-$t/cmd/sbc_harness/sbc_harness.elf)
+lint/all: lint/%: build-aux/lint-generic build-aux/get-dscname
+ ./build-aux/lint-generic '%s\n' $(sources_$*)
+lint/unknown: lint/%: build-aux/lint-unknown
+ ./build-aux/lint-unknown $(sources_$*)
+.PHONY: lint lint/%
+# specific #########
+lint/c: lint/%: build-aux/lint-h build-aux/get-dscname
+ ./build-aux/lint-h $(filter %.h,$(sources_$*))
lint/sh lint/bash: lint/%:
shellcheck $(sources_$*)
+ shfmt --diff --case-indent --simplify $(sources_$*)
lint/python3: lint/%: build-aux/venv
./build-aux/venv/bin/mypy --strict --scripts-are-modules $(sources_$*)
./build-aux/venv/bin/black --check $(sources_$*)
@@ -125,28 +132,21 @@ lint/python3: lint/%: build-aux/venv
./build-aux/venv/bin/pylint $(sources_$*)
! grep -nh 'SPECIAL$$' -- lib9p/proto.gen lib9p/protogen/*.py
./build-aux/venv/bin/pytest $(foreach f,$(sources_python3),$(if $(filter test_%.py,$(notdir $f)),$f))
-lint/c: lint/%: build-aux/lint-h build-aux/get-dscname
- ./build-aux/lint-h $(filter %.h,$(sources_$*))
-lint/make lint/cmake lint/gitignore lint/ini lint/9p lint/markdown lint/pip lint/man-cat: lint/%:
- @:
-lint/unknown: lint/%: build-aux/lint-unknown
- ./build-aux/lint-unknown $(sources_$*)
-lint/all: lint/%: build-aux/lint-generic build-aux/get-dscname
- ./build-aux/lint-generic '%s\n' $(sources_$*)
-.PHONY: lint lint/%
+lint/make lint/cmake lint/gitignore lint/ini lint/9p-idl lint/markdown lint/pip lint/man-cat: lint/%:
+ @: TODO: Write/adopt linters for these file types
-# `format` #########
+# `format` #############################
+# generic ##########
format:
- $(MAKE) -k INNER=t $(patsubst sources_%,format/%,$(filter-out sources_all,$(filter sources_%,$(.VARIABLES))))
+ $(MAKE) -k INNER=t $(patsubst sources_%,format/%,$(filter-out sources_all sources_unknown,$(filter sources_%,$(.VARIABLES))))
+.PHONY: format format/%
+# specific #########
+format/c: format/%:
+ @: TODO: Adopt a C code-formatter
+format/sh format/bash: format/%:
+ shfmt --write --case-indent --simplify $(sources_$*)
format/python3: format/%: ./build-aux/venv
./build-aux/venv/bin/black $(sources_$*)
./build-aux/venv/bin/isort $(sources_$*)
-format/sh format/bash: format/%
- @:
-format/c: format/%:
- @: TODO: Adopt a C code-formatter
-format/make format/cmake format/gitignore format/ini format/9p format/markdown format/pip format/man-cat: format/%:
- @:
-format/unknown: format/%:
- @:
-.PHONY: format format/%
+format/make format/cmake format/gitignore format/ini format/9p-idl format/markdown format/pip format/man-cat: format/%:
+ @: TODO: Write/adopt formatters for these file types
diff --git a/PLAN.md b/PLAN.md
index 2bae3fd..3201122 100644
--- a/PLAN.md
+++ b/PLAN.md
@@ -1,10 +1,20 @@
<!--
PLAN.md - Misc planning notes
- 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
-->
+- [ ] syslog on 9p
+- [ ] better 9p-shutdown
+- [ ] PIO-based USB
+- [ ] wire the USB keyboard to 9P
+- [ ] wire uart to 9p
+
+- SDcard to 9p
+- PicoDVI
+- solder up the bus switch
+
- with hardware I have:
1. [X] type "hello world" as a USB keyboard
2. [ ] get networking up (ping)
@@ -19,5 +29,3 @@
1. [ ] PicoDVI hello-world
2. [ ] "PiciDVI" to network
3. [ ] reverse the flow of PicoDVI
-
-https://hackaday.com/2022/08/26/bit-banged-ethernet-on-the-raspberry-pi-pico/
diff --git a/build-aux/embed-sources.h.gen b/build-aux/embed-sources.h.gen
index 0329496..ee9eb42 100755
--- a/build-aux/embed-sources.h.gen
+++ b/build-aux/embed-sources.h.gen
@@ -6,5 +6,5 @@
nm --format=posix "$@" |
sed -n -E \
- -e 's/(.*_(end|start)) [DR] .*/extern char \1[];/p' \
- -e 's/(.*_size) A .*/extern size_t \1;/p'
+ -e 's/(.*_(end|start)) [DR] .*/extern char \1[];/p' \
+ -e 's/(.*_size) A .*/extern size_t \1;/p'
diff --git a/build-aux/lint-bin b/build-aux/lint-bin
index 78ed19f..91f1612 100755
--- a/build-aux/lint-bin
+++ b/build-aux/lint-bin
@@ -62,7 +62,7 @@ lint_globals() {
cd "$rel_base"
total=0
while read -r symbol addr size source; do
- if (( addr == 0 )); then
+ if ((addr == 0)); then
continue
fi
case "$source" in
@@ -103,8 +103,9 @@ lint_stack() {
fi
done < <(
comm -3 \
- <(sed -En 's/^included: (.*:)?//p' "${in_elffile%.elf}_stack.c" | sort -u) \
- <(readelf_funcs "$in_elffile" | sed -E -e 's/\.part\.[0-9]*$//' -e 's/^__(.*)_veneer$/\1/' | sort -u))
+ <(sed -En 's/^included: (.*:)?//p' "${in_elffile%.elf}_stack.c" | sort -u) \
+ <(readelf_funcs "$in_elffile" | sed -E -e 's/\.part\.[0-9]*$//' -e 's/^__(.*)_veneer$/\1/' | sort -u)
+ )
}
lint_func_blocklist() {
@@ -118,8 +119,8 @@ lint_func_blocklist() {
while read -r func; do
err "$in_elffile" "Contains blocklisted function: ${func}"
done < <(readelf --syms --wide -- "$in_elffile" |
- awk '$4 == "FUNC" { print $8 }' |
- grep -Fx "${blocklist[@]/#/-e}")
+ awk '$4 == "FUNC" { print $8 }' |
+ grep -Fx "${blocklist[@]/#/-e}")
}
main() {
@@ -130,8 +131,8 @@ main() {
{
echo 'Global variables:'
lint_globals "${elf}.map" | sed 's/^/ /'
- } > "${elf%.elf}.lint.globals"
- (lint_stack "$elf") &> "${elf%.elf}.lint.stack"
+ } >"${elf%.elf}.lint.globals"
+ (lint_stack "$elf") &>"${elf%.elf}.lint.stack"
lint_func_blocklist "$elf"
done
diff --git a/build-aux/lint-generic b/build-aux/lint-generic
index 290988c..70e814a 100755
--- a/build-aux/lint-generic
+++ b/build-aux/lint-generic
@@ -25,7 +25,7 @@ for filename in "$@"; do
if [ -x "$filename" ] && [ -z "$shebang" ]; then
err "$filename" 'is executable but does not have a shebang'
elif [ -n "$shebang" ] && ! [ -x "$filename" ]; then
- err "$filename" 'has a shebang but is executable'
+ err "$filename" 'has a shebang but is not executable'
fi
if ! grep -E -q 'Copyright \(C\) 202[4-9]((-|, )202[5-9])* Luke T. Shumaker' "$filename"; then
diff --git a/build-aux/lint-h b/build-aux/lint-h
index 26ac13d..7459032 100755
--- a/build-aux/lint-h
+++ b/build-aux/lint-h
@@ -18,9 +18,9 @@ for filename in "$@"; do
guard=${dscname//'/'/'_'}
guard=${guard//'.'/'_'}
guard="_${guard^^}_"
- if ! { grep -Fxq "#ifndef ${guard}" "$filename" &&
- grep -Fxq "#define ${guard}" "$filename" &&
- grep -Fxq "#endif /* ${guard} */" "$filename"; }; then
+ if ! { grep -Fxq "#ifndef ${guard}" "$filename" &&
+ grep -Fxq "#define ${guard}" "$filename" &&
+ grep -Fxq "#endif /* ${guard} */" "$filename"; }; then
err "$filename" "does not have ${guard} guard"
fi
done
diff --git a/build-aux/valgrind b/build-aux/valgrind
new file mode 100755
index 0000000..728faca
--- /dev/null
+++ b/build-aux/valgrind
@@ -0,0 +1,15 @@
+#!/bin/env bash
+# build-aux/valgrind - Wrapper around valgrind to keep flags consistent
+#
+# Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+# SPDX-License-Identifier: AGPL-3.0-or-later
+
+exec \
+ valgrind \
+ --error-exitcode=2 \
+ --leak-check=full \
+ --show-leak-kinds=all \
+ --errors-for-leak-kinds=all \
+ --show-error-list=all \
+ -- \
+ "$@"
diff --git a/cmd/sbc_harness/main.c b/cmd/sbc_harness/main.c
index 25b122c..7765ca8 100644
--- a/cmd/sbc_harness/main.c
+++ b/cmd/sbc_harness/main.c
@@ -234,4 +234,5 @@ int main() {
infof("===================================================================");
coroutine_add("init", init_cr, NULL);
coroutine_main();
+ assert_notreached("all coroutines exited");
}
diff --git a/lib9p/include/lib9p/9p.generated.h b/lib9p/include/lib9p/9p.generated.h
index 7e901a3..afd89ed 100644
--- a/lib9p/include/lib9p/9p.generated.h
+++ b/lib9p/include/lib9p/9p.generated.h
@@ -7,7 +7,7 @@
#include <stdint.h> /* for uint{n}_t types */
#include <libfmt/fmt.h> /* for fmt_formatter */
-#include <libhw/generic/net.h> /* for struct iovec */
+#include <libhw/generic/io.h> /* for struct iovec */
/* config *********************************************************************/
diff --git a/lib9p/include/lib9p/9p.h b/lib9p/include/lib9p/9p.h
index 5919260..42381cf 100644
--- a/lib9p/include/lib9p/9p.h
+++ b/lib9p/include/lib9p/9p.h
@@ -166,7 +166,7 @@ static inline void lib9p_stat_assert(struct lib9p_stat stat) {
* @return whether there was an error
*/
bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes,
- uint32_t *ret_net_size, ssize_t *ret_host_size);
+ uint32_t *ret_net_size, size_t *ret_host_size);
/**
* Unmarshal the 9P `net_bytes` into the C struct `ret_obj`.
diff --git a/lib9p/include/lib9p/linux-errno.h b/lib9p/include/lib9p/linux-errno.h
index e7c74f5..e864fb6 100644
--- a/lib9p/include/lib9p/linux-errno.h
+++ b/lib9p/include/lib9p/linux-errno.h
@@ -1,5 +1,5 @@
/* lib9p/linux-errno.h - Generated by `lib9p/include/lib9p/linux-errno.h.gen 3rd-party/linux-errno.txt`. DO NOT EDIT! */
-/* 3rd-party/linux-errno.txt - Generated from build-aux/linux-errno.txt.gen and linux.git v6.7. DO NOT EDIT! */
+/* 3rd-party/linux-errno.txt - Generated from lib9p/linux-errno.txt.gen and linux.git v6.14. DO NOT EDIT! */
#ifndef _LIB9P_LINUX_ERRNO_H_
#define _LIB9P_LINUX_ERRNO_H_
diff --git a/lib9p/include/lib9p/srv.h b/lib9p/include/lib9p/srv.h
index ec47142..7ad1b19 100644
--- a/lib9p/include/lib9p/srv.h
+++ b/lib9p/include/lib9p/srv.h
@@ -33,7 +33,7 @@ struct lib9p_srv_ctx {
bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx);
-int lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx);
+void lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx);
/* interface definitions ******************************************************/
diff --git a/build-aux/linux-errno.txt.gen b/lib9p/linux-errno.txt.gen
index f94178f..687e58b 100755
--- a/build-aux/linux-errno.txt.gen
+++ b/lib9p/linux-errno.txt.gen
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
-# build-aux/linux-errno.txt.gen - Generate a listing of Linux kernel errnos
+# lib9p/linux-errno.txt.gen - Generate a listing of Linux kernel errnos
#
-# 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
set -e
diff --git a/lib9p/protogen/h.py b/lib9p/protogen/h.py
index 3b33419..8f7fba2 100644
--- a/lib9p/protogen/h.py
+++ b/lib9p/protogen/h.py
@@ -166,7 +166,7 @@ def gen_h(versions: set[str], typs: list[idl.UserType]) -> str:
#include <stdint.h> /* for uint{{n}}_t types */
#include <libfmt/fmt.h> /* for fmt_formatter */
-#include <libhw/generic/net.h> /* for struct iovec */
+#include <libhw/generic/io.h> /* for struct iovec */
"""
id2typ: dict[int, idl.Message] = {}
diff --git a/lib9p/srv.c b/lib9p/srv.c
index 60a1bb0..b3b9c4c 100644
--- a/lib9p/srv.c
+++ b/lib9p/srv.c
@@ -57,12 +57,11 @@ bool lib9p_srv_flush_requested(struct lib9p_srv_ctx *ctx) {
return _lib9p_srv_flushch_can_send(&ctx->_flushch);
}
-int lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) {
+void lib9p_srv_acknowledge_flush(struct lib9p_srv_ctx *ctx) {
assert(ctx);
assert(_lib9p_srv_flushch_can_send(&ctx->_flushch));
lib9p_error(&ctx->basectx, LINUX_ECANCELED, "request canceled by flush");
_lib9p_srv_flushch_send(&ctx->_flushch, true);
- return -1;
}
/* structs ********************************************************************/
diff --git a/lib9p/tables.c b/lib9p/tables.c
index 271b17b..86e3298 100644
--- a/lib9p/tables.c
+++ b/lib9p/tables.c
@@ -96,6 +96,7 @@ void _lib9p_unmarshal(const struct _lib9p_recv_tentry xxx_table[LIB9P_VER_NUM][0
enum lib9p_msg_type typ = net_bytes[4];
*ret_typ = typ;
struct _lib9p_recv_tentry tentry = xxx_table[ctx->version][typ/2];
+ assert(tentry.unmarshal);
tentry.unmarshal(ctx, net_bytes, ret_body);
}
@@ -124,8 +125,9 @@ bool _lib9p_marshal(const struct _lib9p_send_tentry xxx_table[LIB9P_VER_NUM][0x8
.net_copied_size = 0,
.net_copied = ret_copied,
};
-
struct _lib9p_send_tentry tentry = xxx_table[ctx->version][typ/2];
+ assert(tentry.marshal);
+
bool ret_erred = tentry.marshal(ctx, body, &ret);
if (ret_iov[ret.net_iov_cnt-1].iov_len == 0)
ret.net_iov_cnt--;
@@ -154,12 +156,12 @@ bool lib9p_Rmsg_marshal(struct lib9p_ctx *ctx, enum lib9p_msg_type typ, void *bo
/* `struct lib9p_stat` helpers ************************************************/
bool lib9p_stat_validate(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes,
- uint32_t *ret_net_size, ssize_t *ret_host_size) {
+ uint32_t *ret_net_size, size_t *ret_host_size) {
ssize_t host_size = _lib9p_stat_validate(ctx, net_size, net_bytes, ret_net_size);
if (host_size < 0)
return true;
if (ret_host_size)
- *ret_host_size = host_size;
+ *ret_host_size = (size_t)host_size;
return false;
}
diff --git a/lib9p/tests/runtest b/lib9p/tests/runtest
index 379ea6d..fb66a43 100755
--- a/lib9p/tests/runtest
+++ b/lib9p/tests/runtest
@@ -7,8 +7,10 @@
set -euE -o pipefail
set -x
+build_aux=$(realpath --canonicalize-missing -- "${BASH_SOURCE[0]}/../../../build-aux")
+
port=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()')
-valgrind --error-exitcode=2 ./tests/test_server/test_server "$port" &
+"${build_aux}/valgrind" ./tests/test_server/test_server "$port" &
server_pid=$!
# shellcheck disable=SC2064
trap "kill $server_pid || true; wait $server_pid || true" EXIT
@@ -22,7 +24,7 @@ expect_lines() (
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
+while [[ -d /proc/$server_pid ]] && ! (readlink /proc/$server_pid/fd/* 2>/dev/null | grep -q ^socket:); do sleep 0.1; done
out=$("${client[@]}" ls -l '')
expect_lines \
diff --git a/lib9p/tests/test_server/CMakeLists.txt b/lib9p/tests/test_server/CMakeLists.txt
index 5313917..19c8edb 100644
--- a/lib9p/tests/test_server/CMakeLists.txt
+++ b/lib9p/tests/test_server/CMakeLists.txt
@@ -9,6 +9,7 @@ if (PICO_PLATFORM STREQUAL "host")
add_library(test_server_objs OBJECT
main.c
+ fs_shutdown.c
)
target_include_directories(test_server_objs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/config)
target_include_directories(test_server_objs PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/lib9p/tests/test_server/fs_shutdown.c b/lib9p/tests/test_server/fs_shutdown.c
new file mode 100644
index 0000000..3f88985
--- /dev/null
+++ b/lib9p/tests/test_server/fs_shutdown.c
@@ -0,0 +1,93 @@
+/* lib9p/tests/test_server/fs_shutdown.c - /shutdown API endpoint
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include "fs_shutdown.h"
+
+LO_IMPLEMENTATION_C(lib9p_srv_file, struct shutdown_file, shutdown_file, static);
+
+LO_IMPLEMENTATION_H(lib9p_srv_fio, struct shutdown_file, shutdown_file);
+LO_IMPLEMENTATION_C(lib9p_srv_fio, struct shutdown_file, shutdown_file, static);
+
+/* srv_file *******************************************************************/
+
+static void shutdown_file_free(struct shutdown_file *self) {
+ assert(self);
+}
+static struct lib9p_qid shutdown_file_qid(struct shutdown_file *self) {
+ assert(self);
+ return (struct lib9p_qid){
+ .type = LIB9P_QT_FILE,
+ .vers = 1,
+ .path = self->pathnum,
+ };
+}
+
+static struct lib9p_stat shutdown_file_stat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) {
+ assert(self);
+ assert(ctx);
+ return (struct lib9p_stat){
+ .kern_type = 0,
+ .kern_dev = 0,
+ .file_qid = shutdown_file_qid(self),
+ .file_mode = 0222,
+ .file_atime = UTIL9P_ATIME,
+ .file_mtime = UTIL9P_MTIME,
+ .file_size = 0,
+ .file_name = lib9p_str(self->name),
+ .file_owner_uid = lib9p_str("root"),
+ .file_owner_gid = lib9p_str("root"),
+ .file_last_modified_uid = lib9p_str("root"),
+ .file_extension = lib9p_str(NULL),
+ .file_owner_n_uid = 0,
+ .file_owner_n_gid = 0,
+ .file_last_modified_n_uid = 0,
+ };
+}
+static void shutdown_file_wstat(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_stat) {
+ assert(self);
+ assert(ctx);
+ lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file");
+}
+static void shutdown_file_remove(struct shutdown_file *self, struct lib9p_srv_ctx *ctx) {
+ assert(self);
+ assert(ctx);
+ lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file");
+}
+
+LIB9P_SRV_NOTDIR(struct shutdown_file, shutdown_file)
+
+static lo_interface lib9p_srv_fio shutdown_file_fopen(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) {
+ assert(self);
+ assert(ctx);
+ return lo_box_shutdown_file_as_lib9p_srv_fio(self);
+}
+
+/* srv_fio ********************************************************************/
+
+static void shutdown_file_iofree(struct shutdown_file *self) {
+ assert(self);
+}
+
+static uint32_t shutdown_file_iounit(struct shutdown_file *self) {
+ assert(self);
+ return 0;
+}
+
+static uint32_t shutdown_file_pwrite(struct shutdown_file *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t LM_UNUSED(offset)) {
+ assert(self);
+ assert(ctx);
+ assert(buf);
+ if (byte_count == 0)
+ return 0;
+ for (size_t i = 0; i < self->nlisteners; i++)
+ LO_CALL(lo_box_hostnet_tcplist_as_net_stream_listener(&self->listeners[i]), close);
+ return byte_count;
+}
+static void shutdown_file_pread(struct shutdown_file *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx),
+ uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset),
+ struct iovec *LM_UNUSED(ret)) {
+ assert_notreached("not readable");
+}
diff --git a/lib9p/tests/test_server/fs_shutdown.h b/lib9p/tests/test_server/fs_shutdown.h
new file mode 100644
index 0000000..65956db
--- /dev/null
+++ b/lib9p/tests/test_server/fs_shutdown.h
@@ -0,0 +1,23 @@
+/* lib9p/tests/test_server/fs_shutdown.h - /shutdown API endpoint
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _LIB9P_TESTS_TEST_SERVER_FS_SHUTDOWN_H_
+#define _LIB9P_TESTS_TEST_SERVER_FS_SHUTDOWN_H_
+
+#include <util9p/static.h>
+#include <libhw/host_net.h>
+
+struct shutdown_file {
+ char *name;
+ uint64_t pathnum;
+
+ struct hostnet_tcp_listener *listeners;
+ size_t nlisteners;
+};
+LO_IMPLEMENTATION_H(lib9p_srv_file, struct shutdown_file, shutdown_file);
+#define lo_box_shutdown_file_as_lib9p_srv_file(obj) util9p_box(shutdown_file, obj)
+
+#endif /* _LIB9P_TESTS_TEST_SERVER_FS_SHUTDOWN_H_ */
diff --git a/lib9p/tests/test_server/main.c b/lib9p/tests/test_server/main.c
index a31c083..8d22a04 100644
--- a/lib9p/tests/test_server/main.c
+++ b/lib9p/tests/test_server/main.c
@@ -17,6 +17,7 @@
#include <util9p/static.h>
#include "static.h"
+#include "fs_shutdown.h"
/* configuration **************************************************************/
@@ -42,96 +43,6 @@ struct {
},
};
-/* api ************************************************************************/
-
-struct api_file {
- uint64_t pathnum;
-};
-LO_IMPLEMENTATION_H(lib9p_srv_file, struct api_file, api);
-LO_IMPLEMENTATION_H(lib9p_srv_fio, struct api_file, api);
-
-LO_IMPLEMENTATION_C(lib9p_srv_file, struct api_file, api, static);
-LO_IMPLEMENTATION_C(lib9p_srv_fio, struct api_file, api, static);
-
-static void api_free(struct api_file *self) {
- assert(self);
-}
-static struct lib9p_qid api_qid(struct api_file *self) {
- assert(self);
- return (struct lib9p_qid){
- .type = LIB9P_QT_FILE,
- .vers = 1,
- .path = self->pathnum,
- };
-}
-
-static struct lib9p_stat api_stat(struct api_file *self, struct lib9p_srv_ctx *ctx) {
- assert(self);
- assert(ctx);
- return (struct lib9p_stat){
- .kern_type = 0,
- .kern_dev = 0,
- .file_qid = api_qid(self),
- .file_mode = 0222,
- .file_atime = UTIL9P_ATIME,
- .file_mtime = UTIL9P_MTIME,
- .file_size = 0,
- .file_name = lib9p_str("shutdown"),
- .file_owner_uid = lib9p_str("root"),
- .file_owner_gid = lib9p_str("root"),
- .file_last_modified_uid = lib9p_str("root"),
- .file_extension = lib9p_str(NULL),
- .file_owner_n_uid = 0,
- .file_owner_n_gid = 0,
- .file_last_modified_n_uid = 0,
- };
-}
-static void api_wstat(struct api_file *self, struct lib9p_srv_ctx *ctx, struct lib9p_stat) {
- assert(self);
- assert(ctx);
- lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot wstat API file");
-}
-static void api_remove(struct api_file *self, struct lib9p_srv_ctx *ctx) {
- assert(self);
- assert(ctx);
- lib9p_error(&ctx->basectx, LINUX_EROFS, "cannot remove API file");
-}
-
-LIB9P_SRV_NOTDIR(struct api_file, api)
-
-static lo_interface lib9p_srv_fio api_fopen(struct api_file *self, struct lib9p_srv_ctx *ctx, bool, bool, bool) {
- assert(self);
- assert(ctx);
- return lo_box_api_as_lib9p_srv_fio(self);
-}
-
-static void api_iofree(struct api_file *self) {
- assert(self);
-}
-
-static uint32_t api_iounit(struct api_file *self) {
- assert(self);
- return 0;
-}
-
-static uint32_t api_pwrite(struct api_file *self, struct lib9p_srv_ctx *ctx, void *buf, uint32_t byte_count, uint64_t LM_UNUSED(offset)) {
- assert(self);
- assert(ctx);
- assert(buf);
- if (byte_count == 0)
- return 0;
- for (int i = 0; i < CONFIG_SRV9P_NUM_CONNS; i++)
- LO_CALL(lo_box_hostnet_tcplist_as_net_stream_listener(&globals.listeners[i]), close);
- return byte_count;
-}
-static void api_pread(struct api_file *LM_UNUSED(self), struct lib9p_srv_ctx *LM_UNUSED(ctx),
- uint32_t LM_UNUSED(byte_count), uint64_t LM_UNUSED(byte_offset),
- struct iovec *LM_UNUSED(ret)) {
- assert_notreached("not readable");
-}
-
-#define lo_box_api_as_lib9p_srv_file(obj) util9p_box(api, obj)
-
/* file tree ******************************************************************/
enum { PATH_BASE = __COUNTER__ };
@@ -144,13 +55,22 @@ enum { PATH_BASE = __COUNTER__ };
#define STATIC_DIR(STRNAME, ...) \
UTIL9P_STATIC_DIR(PATH_COUNTER, STRNAME, __VA_ARGS__)
+#define API_FILE(STRNAME, SYMNAME, ...) \
+ lo_box_##SYMNAME##_file_as_lib9p_srv_file(&((struct SYMNAME##_file){ \
+ .name = STRNAME, \
+ .pathnum = PATH_COUNTER \
+ __VA_OPT__(,) __VA_ARGS__ \
+ }))
+
struct lib9p_srv_file root =
STATIC_DIR("",
STATIC_DIR("Documentation",
STATIC_FILE("x", Documentation_x_txt),
),
STATIC_FILE("README.md", README_md),
- lo_box_api_as_lib9p_srv_file(&(struct api_file){.pathnum = PATH_COUNTER}),
+ API_FILE("shutdown", shutdown,
+ .listeners = globals.listeners,
+ .nlisteners = LM_ARRAY_LEN(globals.listeners)),
);
static lo_interface lib9p_srv_file get_root(struct lib9p_srv_ctx *LM_UNUSED(ctx), struct lib9p_s LM_UNUSED(treename)) {
diff --git a/libcr/CMakeLists.txt b/libcr/CMakeLists.txt
index 80a4ece..2e66020 100644
--- a/libcr/CMakeLists.txt
+++ b/libcr/CMakeLists.txt
@@ -30,7 +30,7 @@ function(add_libcr_matrix_test n defs)
if ("CONFIG_COROUTINE_VALGRIND=1" IN_LIST defs)
add_test(
NAME "libcr/test_matrix${n}"
- COMMAND valgrind --error-exitcode=2 "./test_matrix${n}"
+ COMMAND "${CMAKE_SOURCE_DIR}/build-aux/valgrind" "./test_matrix${n}"
)
else()
add_test(
diff --git a/libcr_ipc/CMakeLists.txt b/libcr_ipc/CMakeLists.txt
index bd72f54..60d3f2d 100644
--- a/libcr_ipc/CMakeLists.txt
+++ b/libcr_ipc/CMakeLists.txt
@@ -6,7 +6,6 @@
add_library(libcr_ipc INTERFACE)
target_include_directories(libcr_ipc PUBLIC INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_sources(libcr_ipc INTERFACE
- _linkedlist.c
chan.c
mutex.c
rpc.c
diff --git a/libcr_ipc/_linkedlist.h b/libcr_ipc/_linkedlist.h
deleted file mode 100644
index ab6d89e..0000000
--- a/libcr_ipc/_linkedlist.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* libcr_ipc/_linkedlist.h - Common low-level linked lists for use in libcr_ipc
- *
- * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#ifndef _LIBCR_IPC__LINKEDLIST_H_
-#define _LIBCR_IPC__LINKEDLIST_H_
-
-#include <libmisc/assert.h>
-
-#include <libcr_ipc/_linkedlist_pub.h>
-
-/* singly linked list *********************************************************/
-
-typedef struct _cr_ipc_sll_node {
- struct _cr_ipc_sll_node *rear;
-} cr_ipc_sll_node;
-
-#define cr_ipc_sll_node_cast(node_typ, node_ptr) \
- ({ \
- static_assert(_Generic(node_ptr, cr_ipc_sll_node *: 1, default: 0), \
- "typeof("#node_ptr") != cr_ipc_sll_node *"); \
- assert(node_ptr); \
- static_assert(offsetof(node_typ, cr_ipc_sll_node) == 0); \
- ((node_typ*)(node_ptr)); \
- })
-
-void cr_ipc_sll_push_to_rear(_cr_ipc_sll_root *root, cr_ipc_sll_node *node);
-void cr_ipc_sll_pop_from_front(_cr_ipc_sll_root *root);
-
-/* doubly linked list *********************************************************/
-
-typedef struct _cr_ipc_dll_node {
- struct _cr_ipc_dll_node *front, *rear;
-} cr_ipc_dll_node;
-
-#define cr_ipc_dll_node_cast(node_typ, node_ptr) \
- ({ \
- static_assert(_Generic(node_ptr, cr_ipc_dll_node *: 1, default: 0), \
- "typeof("#node_ptr") != cr_ipc_dll_node *"); \
- assert(node_ptr); \
- static_assert(offsetof(node_typ, cr_ipc_dll_node) == 0); \
- ((node_typ*)(node_ptr)); \
- })
-
-void cr_ipc_dll_push_to_rear(_cr_ipc_dll_root *root, cr_ipc_dll_node *node);
-void cr_ipc_dll_remove(_cr_ipc_dll_root *root, cr_ipc_dll_node *node);
-void cr_ipc_dll_pop_from_front(_cr_ipc_dll_root *root);
-
-#endif /* _LIBCR_IPC__LINKEDLIST_H_ */
diff --git a/libcr_ipc/chan.c b/libcr_ipc/chan.c
index 12d2ec2..6ccfa44 100644
--- a/libcr_ipc/chan.c
+++ b/libcr_ipc/chan.c
@@ -13,12 +13,10 @@
#include <libcr_ipc/chan.h>
-#include "_linkedlist.h"
-
/* base channels **************************************************************/
struct cr_chan_waiter {
- cr_ipc_dll_node;
+ lm_dll_node;
cid_t cid;
void *val_ptr;
void (*dequeue)(void *, size_t);
@@ -28,7 +26,7 @@ struct cr_chan_waiter {
void cr_chan_dequeue(void *_ch, size_t) {
struct _cr_chan *ch = _ch;
- cr_ipc_dll_pop_from_front(&ch->waiters);
+ lm_dll_pop_from_front(&ch->waiters);
}
void _cr_chan_xfer(enum _cr_chan_waiter_typ self_typ, struct _cr_chan *ch, void *val_ptr, size_t val_size) {
@@ -37,7 +35,7 @@ void _cr_chan_xfer(enum _cr_chan_waiter_typ self_typ, struct _cr_chan *ch, void
if (ch->waiters.front && ch->waiter_typ != self_typ) { /* non-blocking fast-path */
/* Copy. */
- struct cr_chan_waiter *front = cr_ipc_dll_node_cast(struct cr_chan_waiter, ch->waiters.front);
+ struct cr_chan_waiter *front = lm_dll_node_cast(struct cr_chan_waiter, ch->waiters.front);
if (self_typ == _CR_CHAN_SENDER)
memcpy(front->val_ptr, val_ptr, val_size);
else
@@ -53,7 +51,7 @@ void _cr_chan_xfer(enum _cr_chan_waiter_typ self_typ, struct _cr_chan *ch, void
.dequeue = cr_chan_dequeue,
.dequeue_arg1 = ch,
};
- cr_ipc_dll_push_to_rear(&ch->waiters, &self);
+ lm_dll_push_to_rear(&ch->waiters, &self);
ch->waiter_typ = self_typ;
cr_pause_and_yield();
}
@@ -95,8 +93,8 @@ static inline enum cr_select_class cr_select_getclass(struct cr_select_arg arg)
void cr_select_dequeue(void *_waiters, size_t idx) {
struct cr_select_waiters *waiters = _waiters;
for (size_t i = 0; i < waiters->cnt; i++)
- cr_ipc_dll_remove(&(waiters->args[i].ch->waiters),
- &(waiters->nodes[i]));
+ lm_dll_remove(&(waiters->args[i].ch->waiters),
+ &(waiters->nodes[i]));
waiters->cnt = idx;
}
@@ -162,7 +160,7 @@ size_t cr_select_v(size_t arg_cnt, struct cr_select_arg arg_vec[]) {
.dequeue_arg1 = &waiters,
.dequeue_arg2 = i,
};
- cr_ipc_dll_push_to_rear(&arg_vec[i].ch->waiters, &waiters.nodes[i]);
+ lm_dll_push_to_rear(&arg_vec[i].ch->waiters, &waiters.nodes[i]);
}
cr_pause_and_yield();
return waiters.cnt;
diff --git a/libcr_ipc/include/libcr_ipc/_linkedlist_pub.h b/libcr_ipc/include/libcr_ipc/_linkedlist_pub.h
deleted file mode 100644
index 6719ba4..0000000
--- a/libcr_ipc/include/libcr_ipc/_linkedlist_pub.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* libcr_ipc/_linkedlist_pub.h - Common low-level linked lists for use in libcr_ipc
- *
- * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
- * SPDX-License-Identifier: AGPL-3.0-or-later
- */
-
-#ifndef _LIBCR_IPC__LINKEDLIST_PUB_H_
-#define _LIBCR_IPC__LINKEDLIST_PUB_H_
-
-/* singly linked list *********************************************************/
-
-struct _cr_ipc_sll_node;
-
-typedef struct {
- struct _cr_ipc_sll_node *front, *rear;
-} _cr_ipc_sll_root;
-
-/* doubly linked list *********************************************************/
-
-struct _cr_ipc_dll_node;
-
-typedef struct {
- struct _cr_ipc_dll_node *front, *rear;
-} _cr_ipc_dll_root;
-
-#endif /* _LIBCR_IPC__LINKEDLIST_PUB_H_ */
diff --git a/libcr_ipc/include/libcr_ipc/chan.h b/libcr_ipc/include/libcr_ipc/chan.h
index ad311a0..80acdb8 100644
--- a/libcr_ipc/include/libcr_ipc/chan.h
+++ b/libcr_ipc/include/libcr_ipc/chan.h
@@ -10,9 +10,8 @@
#include <stdbool.h> /* for bool */
#include <stddef.h> /* for size_t */
-#include <libmisc/macro.h> /* LM_CAT2_() */
-
-#include <libcr_ipc/_linkedlist_pub.h>
+#include <libmisc/linkedlist.h> /* for lm_dll_root */
+#include <libmisc/macro.h> /* for LM_CAT2_() */
/* base channels **************************************************************/
@@ -113,7 +112,7 @@ enum _cr_chan_waiter_typ {
struct _cr_chan {
enum _cr_chan_waiter_typ waiter_typ;
- _cr_ipc_dll_root waiters;
+ lm_dll_root waiters;
};
void _cr_chan_xfer(enum _cr_chan_waiter_typ self_typ, struct _cr_chan *ch, void *val_ptr, size_t val_size);
diff --git a/libcr_ipc/include/libcr_ipc/mutex.h b/libcr_ipc/include/libcr_ipc/mutex.h
index ec40f5c..0f3c9c2 100644
--- a/libcr_ipc/include/libcr_ipc/mutex.h
+++ b/libcr_ipc/include/libcr_ipc/mutex.h
@@ -9,10 +9,9 @@
#include <stdbool.h> /* for bool */
+#include <libmisc/linkedlist.h>
#include <libmisc/private.h>
-#include <libcr_ipc/_linkedlist_pub.h>
-
/**
* A cr_mutex_t is a fair mutex.
*
@@ -24,7 +23,7 @@
typedef struct {
BEGIN_PRIVATE(LIBCR_IPC_MUTEX_H);
bool locked;
- _cr_ipc_sll_root waiters;
+ lm_sll_root waiters;
END_PRIVATE(LIBCR_IPC_MUTEX_H);
} cr_mutex_t;
diff --git a/libcr_ipc/include/libcr_ipc/rpc.h b/libcr_ipc/include/libcr_ipc/rpc.h
index 07ace95..f091685 100644
--- a/libcr_ipc/include/libcr_ipc/rpc.h
+++ b/libcr_ipc/include/libcr_ipc/rpc.h
@@ -9,10 +9,9 @@
#include <stdbool.h> /* for bool */
+#include <libmisc/linkedlist.h> /* for lm_sll_root */
#include <libmisc/macro.h> /* for LM_CAT2_() */
-#include <libcr_ipc/_linkedlist_pub.h>
-
/**
* CR_RPC_DECLARE(NAME, REQ_T, RESP_T) declares the following types
* and methods:
@@ -146,7 +145,7 @@ enum _cr_rpc_waiter_typ {
struct _cr_rpc {
enum _cr_rpc_waiter_typ waiter_typ;
- _cr_ipc_sll_root waiters;
+ lm_sll_root waiters;
};
void _cr_rpc_send_req(struct _cr_rpc *ch, void *req_ptr, size_t req_size, void *resp_ptr);
diff --git a/libcr_ipc/include/libcr_ipc/rwmutex.h b/libcr_ipc/include/libcr_ipc/rwmutex.h
index 924acce..d48abe9 100644
--- a/libcr_ipc/include/libcr_ipc/rwmutex.h
+++ b/libcr_ipc/include/libcr_ipc/rwmutex.h
@@ -9,10 +9,9 @@
#include <stdbool.h>
+#include <libmisc/linkedlist.h>
#include <libmisc/private.h>
-#include <libcr_ipc/_linkedlist_pub.h>
-
/**
* A cr_rwmutex_t is a fair read/write mutex.
*
@@ -29,7 +28,7 @@ typedef struct {
unsigned nreaders;
bool locked;
bool unpausing;
- _cr_ipc_sll_root waiters;
+ lm_sll_root waiters;
END_PRIVATE(LIBCR_IPC_RWMUTEX_H);
} cr_rwmutex_t;
diff --git a/libcr_ipc/include/libcr_ipc/sema.h b/libcr_ipc/include/libcr_ipc/sema.h
index ae8d93d..cc387f4 100644
--- a/libcr_ipc/include/libcr_ipc/sema.h
+++ b/libcr_ipc/include/libcr_ipc/sema.h
@@ -9,10 +9,9 @@
#include <stdbool.h>
+#include <libmisc/linkedlist.h>
#include <libmisc/private.h>
-#include <libcr_ipc/_linkedlist_pub.h>
-
/**
* A cr_sema_t is a fair unbounded[1] counting semaphore.
*
@@ -22,7 +21,7 @@ typedef struct {
BEGIN_PRIVATE(LIBCR_IPC_SEMA_H);
unsigned int cnt;
bool unpausing;
- _cr_ipc_sll_root waiters;
+ lm_sll_root waiters;
END_PRIVATE(LIBCR_IPC_SEMA_H);
} cr_sema_t;
diff --git a/libcr_ipc/mutex.c b/libcr_ipc/mutex.c
index 28debba..b0ebe05 100644
--- a/libcr_ipc/mutex.c
+++ b/libcr_ipc/mutex.c
@@ -9,10 +9,8 @@
#define IMPLEMENTATION_FOR_LIBCR_IPC_MUTEX_H YES
#include <libcr_ipc/mutex.h>
-#include "_linkedlist.h"
-
struct cr_mutex_waiter {
- cr_ipc_sll_node;
+ lm_sll_node;
cid_t cid;
};
@@ -26,7 +24,7 @@ void cr_mutex_lock(cr_mutex_t *mu) {
struct cr_mutex_waiter self = {
.cid = cr_getcid(),
};
- cr_ipc_sll_push_to_rear(&mu->waiters, &self);
+ lm_sll_push_to_rear(&mu->waiters, &self);
cr_pause_and_yield();
}
assert(mu->locked);
@@ -38,8 +36,8 @@ void cr_mutex_unlock(cr_mutex_t *mu) {
assert(mu->locked);
if (mu->waiters.front) {
- cr_unpause(cr_ipc_sll_node_cast(struct cr_mutex_waiter, mu->waiters.front)->cid);
- cr_ipc_sll_pop_from_front(&mu->waiters);
+ cr_unpause(lm_sll_node_cast(struct cr_mutex_waiter, mu->waiters.front)->cid);
+ lm_sll_pop_from_front(&mu->waiters);
} else
mu->locked = false;
}
diff --git a/libcr_ipc/rpc.c b/libcr_ipc/rpc.c
index a648fde..6d9422f 100644
--- a/libcr_ipc/rpc.c
+++ b/libcr_ipc/rpc.c
@@ -10,17 +10,15 @@
#include <libcr_ipc/rpc.h>
-#include "_linkedlist.h"
-
struct cr_rpc_requester {
- cr_ipc_sll_node;
+ lm_sll_node;
cid_t cid;
void *req_ptr; /* where to read req from */
void *resp_ptr; /* where to write resp to */
};
struct cr_rpc_responder {
- cr_ipc_sll_node;
+ lm_sll_node;
/* before enqueued | after dequeued */
/* -------------------+-------------------- */
cid_t cid; /* responder cid | requester cid */
@@ -34,8 +32,8 @@ void _cr_rpc_send_req(struct _cr_rpc *ch, void *req_ptr, size_t req_size, void *
if (ch->waiters.front && ch->waiter_typ != _CR_RPC_REQUESTER) { /* fast-path (still blocks) */
struct cr_rpc_responder *responder =
- cr_ipc_sll_node_cast(struct cr_rpc_responder, ch->waiters.front);
- cr_ipc_sll_pop_from_front(&ch->waiters);
+ lm_sll_node_cast(struct cr_rpc_responder, ch->waiters.front);
+ lm_sll_pop_from_front(&ch->waiters);
/* Copy the req to the responder's stack. */
memcpy(responder->ptr, req_ptr, req_size);
/* Notify the responder that we have done so. */
@@ -50,7 +48,7 @@ void _cr_rpc_send_req(struct _cr_rpc *ch, void *req_ptr, size_t req_size, void *
.req_ptr = req_ptr,
.resp_ptr = resp_ptr,
};
- cr_ipc_sll_push_to_rear(&ch->waiters, &self);
+ lm_sll_push_to_rear(&ch->waiters, &self);
/* Wait for a responder to both copy our req and sed
* `*resp_ptr`. */
cr_pause_and_yield();
@@ -65,8 +63,8 @@ void _cr_rpc_recv_req(struct _cr_rpc *ch, void *req_ptr, size_t req_size, void *
if (ch->waiters.front && ch->waiter_typ != _CR_RPC_RESPONDER) { /* non-blocking fast-path */
struct cr_rpc_requester *requester =
- cr_ipc_sll_node_cast(struct cr_rpc_requester, ch->waiters.front);
- cr_ipc_sll_pop_from_front(&ch->waiters);
+ lm_sll_node_cast(struct cr_rpc_requester, ch->waiters.front);
+ lm_sll_pop_from_front(&ch->waiters);
memcpy(req_ptr, requester->req_ptr, req_size);
*ret_requester = requester->cid;
@@ -76,7 +74,7 @@ void _cr_rpc_recv_req(struct _cr_rpc *ch, void *req_ptr, size_t req_size, void *
.cid = cr_getcid(),
.ptr = req_ptr,
};
- cr_ipc_sll_push_to_rear(&ch->waiters, &self);
+ lm_sll_push_to_rear(&ch->waiters, &self);
ch->waiter_typ = _CR_RPC_RESPONDER;
cr_pause_and_yield();
*ret_requester = self.cid;
diff --git a/libcr_ipc/rwmutex.c b/libcr_ipc/rwmutex.c
index 04016d6..4c5da81 100644
--- a/libcr_ipc/rwmutex.c
+++ b/libcr_ipc/rwmutex.c
@@ -9,10 +9,8 @@
#define IMPLEMENTATION_FOR_LIBCR_IPC_RWMUTEX_H YES
#include <libcr_ipc/rwmutex.h>
-#include "_linkedlist.h"
-
struct cr_rwmutex_waiter {
- cr_ipc_sll_node;
+ lm_sll_node;
bool is_reader;
cid_t cid;
};
@@ -25,13 +23,13 @@ void cr_rwmutex_lock(cr_rwmutex_t *mu) {
.is_reader = false,
.cid = cr_getcid(),
};
- cr_ipc_sll_push_to_rear(&mu->waiters, &self);
- if (mu->waiters.front != &self.cr_ipc_sll_node || mu->locked)
+ lm_sll_push_to_rear(&mu->waiters, &self);
+ if (mu->waiters.front != &self.lm_sll_node || mu->locked)
cr_pause_and_yield();
- assert(mu->waiters.front == &self.cr_ipc_sll_node);
+ assert(mu->waiters.front == &self.lm_sll_node);
/* We now hold the lock (and are mu->waiters.front). */
- cr_ipc_sll_pop_from_front(&mu->waiters);
+ lm_sll_pop_from_front(&mu->waiters);
assert(mu->nreaders == 0);
mu->locked = true;
mu->unpausing = false;
@@ -45,18 +43,17 @@ void cr_rwmutex_rlock(cr_rwmutex_t *mu) {
.is_reader = true,
.cid = cr_getcid(),
};
- cr_ipc_sll_push_to_rear(&mu->waiters, &self);
- if (mu->waiters.front != &self.cr_ipc_sll_node || (mu->locked && mu->nreaders == 0))
+ lm_sll_push_to_rear(&mu->waiters, &self);
+ if (mu->waiters.front != &self.lm_sll_node || (mu->locked && mu->nreaders == 0))
cr_pause_and_yield();
- assert(mu->waiters.front == &self.cr_ipc_sll_node);
+ assert(mu->waiters.front == &self.lm_sll_node);
/* We now hold the lock (and are mu->waiters.front). */
- cr_ipc_sll_pop_from_front(&mu->waiters);
+ lm_sll_pop_from_front(&mu->waiters);
mu->nreaders++;
mu->locked = true;
- struct cr_rwmutex_waiter *waiter = mu->waiters.front
- ? cr_ipc_sll_node_cast(struct cr_rwmutex_waiter, mu->waiters.front)
- : NULL;
+ struct cr_rwmutex_waiter *waiter =
+ lm_sll_node_cast(struct cr_rwmutex_waiter, mu->waiters.front);
if (waiter && waiter->is_reader) {
assert(mu->unpausing);
cr_unpause(waiter->cid);
@@ -74,7 +71,7 @@ void cr_rwmutex_unlock(cr_rwmutex_t *mu) {
assert(!mu->unpausing);
if (mu->waiters.front) {
struct cr_rwmutex_waiter *waiter =
- cr_ipc_sll_node_cast(struct cr_rwmutex_waiter, mu->waiters.front);
+ lm_sll_node_cast(struct cr_rwmutex_waiter, mu->waiters.front);
mu->unpausing = true;
cr_unpause(waiter->cid);
} else {
@@ -92,7 +89,7 @@ void cr_rwmutex_runlock(cr_rwmutex_t *mu) {
if (mu->nreaders == 0 && !mu->unpausing) {
if (mu->waiters.front) {
struct cr_rwmutex_waiter *waiter =
- cr_ipc_sll_node_cast(struct cr_rwmutex_waiter, mu->waiters.front);
+ lm_sll_node_cast(struct cr_rwmutex_waiter, mu->waiters.front);
assert(!waiter->is_reader);
mu->unpausing = true;
cr_unpause(waiter->cid);
diff --git a/libcr_ipc/sema.c b/libcr_ipc/sema.c
index 85add6c..cb984b6 100644
--- a/libcr_ipc/sema.c
+++ b/libcr_ipc/sema.c
@@ -9,10 +9,8 @@
#define IMPLEMENTATION_FOR_LIBCR_IPC_SEMA_H YES
#include <libcr_ipc/sema.h>
-#include "_linkedlist.h"
-
struct cr_sema_waiter {
- cr_ipc_sll_node;
+ lm_sll_node;
cid_t cid;
};
@@ -24,7 +22,7 @@ void cr_sema_signal(cr_sema_t *sema) {
sema->cnt++;
if (sema->waiters.front && !sema->unpausing) {
cr_unpause(
- cr_ipc_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid);
+ lm_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid);
sema->unpausing = true;
}
cr_restore_interrupts(saved);
@@ -37,7 +35,7 @@ void cr_sema_signal_from_intrhandler(cr_sema_t *sema) {
sema->cnt++;
if (sema->waiters.front && !sema->unpausing) {
cr_unpause_from_intrhandler(
- cr_ipc_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid);
+ lm_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid);
sema->unpausing = true;
}
}
@@ -51,15 +49,15 @@ void cr_sema_wait(cr_sema_t *sema) {
struct cr_sema_waiter self = {
.cid = cr_getcid(),
};
- cr_ipc_sll_push_to_rear(&sema->waiters, &self);
- if (sema->waiters.front != &self.cr_ipc_sll_node || !sema->cnt)
+ lm_sll_push_to_rear(&sema->waiters, &self);
+ if (sema->waiters.front != &self.lm_sll_node || !sema->cnt)
cr_pause_and_yield();
- assert(sema->waiters.front == &self.cr_ipc_sll_node && sema->cnt);
- cr_ipc_sll_pop_from_front(&sema->waiters);
+ assert(sema->waiters.front == &self.lm_sll_node && sema->cnt);
+ lm_sll_pop_from_front(&sema->waiters);
sema->cnt--;
if (sema->cnt && sema->waiters.front)
cr_unpause(
- cr_ipc_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid);
+ lm_sll_node_cast(struct cr_sema_waiter, sema->waiters.front)->cid);
else
sema->unpausing = false;
cr_restore_interrupts(saved);
diff --git a/libmisc/CMakeLists.txt b/libmisc/CMakeLists.txt
index 4599ead..c80e060 100644
--- a/libmisc/CMakeLists.txt
+++ b/libmisc/CMakeLists.txt
@@ -8,6 +8,7 @@ target_include_directories(libmisc PUBLIC INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/
target_sources(libmisc INTERFACE
assert.c
intercept.c
+ linkedlist.c
log.c
)
target_compile_options(libmisc INTERFACE "$<$<COMPILE_LANGUAGE:C>:-fplan9-extensions>")
diff --git a/libmisc/include/libmisc/linkedlist.h b/libmisc/include/libmisc/linkedlist.h
new file mode 100644
index 0000000..8adef66
--- /dev/null
+++ b/libmisc/include/libmisc/linkedlist.h
@@ -0,0 +1,46 @@
+/* libmisc/linkedlist.h - Singly- and doubly- linked lists
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#ifndef _LIBMISC_LINKEDLIST_H_
+#define _LIBMISC_LINKEDLIST_H_
+
+#include <libmisc/assert.h>
+#include <libmisc/macro.h>
+
+/* singly linked list *********************************************************/
+
+typedef struct _lm_sll_node {
+ struct _lm_sll_node *rear;
+} lm_sll_node;
+
+typedef struct {
+ lm_sll_node *front, *rear;
+} lm_sll_root;
+
+#define lm_sll_node_cast(node_typ, node_ptr) \
+ LM_CAST_FIELD_TO_STRUCT(node_typ, lm_sll_node, node_ptr)
+
+void lm_sll_push_to_rear(lm_sll_root *root, lm_sll_node *node);
+void lm_sll_pop_from_front(lm_sll_root *root);
+
+/* doubly linked list *********************************************************/
+
+typedef struct _lm_dll_node {
+ struct _lm_dll_node *front, *rear;
+} lm_dll_node;
+
+typedef struct {
+ lm_dll_node *front, *rear;
+} lm_dll_root;
+
+#define lm_dll_node_cast(node_typ, node_ptr) \
+ LM_CAST_FIELD_TO_STRUCT(node_typ, lm_dll_node, node_ptr)
+
+void lm_dll_push_to_rear(lm_dll_root *root, lm_dll_node *node);
+void lm_dll_remove(lm_dll_root *root, lm_dll_node *node);
+void lm_dll_pop_from_front(lm_dll_root *root);
+
+#endif /* _LIBMISC_LINKEDLIST_H_ */
diff --git a/libmisc/include/libmisc/macro.h b/libmisc/include/libmisc/macro.h
index b3e235c..6cb15fb 100644
--- a/libmisc/include/libmisc/macro.h
+++ b/libmisc/include/libmisc/macro.h
@@ -14,9 +14,20 @@
#define LM_NEVER_INLINE [[gnu::noinline]]
#define LM_FLATTEN [[gnu::flatten]]
-/* numeric */
+/* types */
#define LM_ARRAY_LEN(ary) (sizeof(ary)/sizeof((ary)[0]))
+
+#define LM_CAST_FIELD_TO_STRUCT(STRUCT_TYP, FIELD_NAME, PTR_TO_FIELD) ({ \
+ /* The _fptr assignment is to get the compiler to do type checking. */ \
+ typeof(((STRUCT_TYP *)NULL)->FIELD_NAME) *_fptr = (PTR_TO_FIELD); \
+ _fptr \
+ ? ((STRUCT_TYP*)( ((void*)_fptr) - offsetof(STRUCT_TYP, FIELD_NAME))) \
+ : NULL; \
+})
+
+/* numeric */
+
#define LM_CEILDIV(n, d) ( ((n)+(d)-1) / (d) ) /** Return ceil(n/d) */
#define LM_ROUND_UP(n, d) ( LM_CEILDIV(n, d) * (d) ) /** Return `n` rounded up to the nearest multiple of `d` */
#define LM_ROUND_DOWN(n, d) ( ((n)/(d)) * (d) ) /** Return `n` rounded down to the nearest multiple of `d` */
diff --git a/libcr_ipc/_linkedlist.c b/libmisc/linkedlist.c
index b27dba8..5fe0977 100644
--- a/libcr_ipc/_linkedlist.c
+++ b/libmisc/linkedlist.c
@@ -1,4 +1,4 @@
-/* libcr_ipc/_linkedlist.c - Common low-level linked lists for use in libcr_ipc
+/* libmisc/linkedlist.c - Singly- and doubly- linked lists
*
* Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
@@ -6,11 +6,11 @@
#include <stddef.h> /* for NULL */
-#include "_linkedlist.h"
+#include <libmisc/linkedlist.h>
/* singly linked list *********************************************************/
-void cr_ipc_sll_push_to_rear(_cr_ipc_sll_root *root, cr_ipc_sll_node *node) {
+void lm_sll_push_to_rear(lm_sll_root *root, lm_sll_node *node) {
assert(root);
node->rear = NULL;
if (root->rear)
@@ -20,7 +20,7 @@ void cr_ipc_sll_push_to_rear(_cr_ipc_sll_root *root, cr_ipc_sll_node *node) {
root->rear = node;
}
-void cr_ipc_sll_pop_from_front(_cr_ipc_sll_root *root) {
+void lm_sll_pop_from_front(lm_sll_root *root) {
assert(root);
assert(root->front);
root->front = root->front->rear;
@@ -30,7 +30,7 @@ void cr_ipc_sll_pop_from_front(_cr_ipc_sll_root *root) {
/* doubly linked list *********************************************************/
-void cr_ipc_dll_push_to_rear(_cr_ipc_dll_root *root, cr_ipc_dll_node *node) {
+void lm_dll_push_to_rear(lm_dll_root *root, lm_dll_node *node) {
assert(root);
assert(node);
node->front = root->rear;
@@ -42,7 +42,7 @@ void cr_ipc_dll_push_to_rear(_cr_ipc_dll_root *root, cr_ipc_dll_node *node) {
root->rear = node;
}
-void cr_ipc_dll_remove(_cr_ipc_dll_root *root, cr_ipc_dll_node *node) {
+void lm_dll_remove(lm_dll_root *root, lm_dll_node *node) {
assert(root);
assert(node);
if (node->front)
@@ -55,8 +55,8 @@ void cr_ipc_dll_remove(_cr_ipc_dll_root *root, cr_ipc_dll_node *node) {
root->rear = node->front;
}
-void cr_ipc_dll_pop_from_front(_cr_ipc_dll_root *root) {
+void lm_dll_pop_from_front(lm_dll_root *root) {
assert(root);
assert(root->front);
- cr_ipc_dll_remove(root, root->front);
+ lm_dll_remove(root, root->front);
}
diff --git a/libusb/include/libusb/tusb_helpers.h b/libusb/include/libusb/tusb_helpers.h
index 1b4e48e..0c35f62 100644
--- a/libusb/include/libusb/tusb_helpers.h
+++ b/libusb/include/libusb/tusb_helpers.h
@@ -1,7 +1,7 @@
/* Generated by `libusb/include/libusb/tusb_helpers.h.gen `. DO NOT EDIT! */
/* libusb/tusb_helpers.h - Preprocessor macros that I think should be included in TinyUSB
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
*
* SPDX-License-Identifier: MIT
*
diff --git a/libusb/include/libusb/tusb_helpers.h.gen b/libusb/include/libusb/tusb_helpers.h.gen
index 5a5d1ac..1de1d09 100755
--- a/libusb/include/libusb/tusb_helpers.h.gen
+++ b/libusb/include/libusb/tusb_helpers.h.gen
@@ -7,7 +7,7 @@ echo "/* Generated by \`$0 $*\`. DO NOT EDIT! */"
cat <<'EOT'
/* libusb/tusb_helpers.h - Preprocessor macros that I think should be included in TinyUSB
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
*
* SPDX-License-Identifier: MIT
*
@@ -70,12 +70,19 @@ fi
if [[ ! -f 3rd-party/MS-LCID.txt || 3rd-party/MS-LCID.txt -ot 3rd-party/MS-LCID.pdf ]]; then
pdftotext -layout 3rd-party/MS-LCID.pdf
fi
-<3rd-party/MS-LCID.txt \
- grep -E '^\s*0x[0-9A-F]{4}\s+[a-z]' | sed 's/,.*//' | grep -v reserved | # find the lines we're interested in
- sed -E 's/^\s*0x(..)(..)\s+(\S.*)/\2 \1 \3/p' | tr '[:lower:]-' '[:upper:]_' | # format them as 'PRIhex SUBhex UPPER_STR'
- sort |
- sed -E 's/(..) (..) (.*)/#define LANGID_\3 0x\2\1/' | # format them as '#define LANGID_UPPER_STR 0xSUBPRI'
- column --table --output-separator=' '
+{
+ {
+ # find the lines we're interested in
+ grep -E '^\s*0x[0-9A-F]{4}\s+[a-z]' | sed 's/,.*//' | grep -v reserved
+ } | {
+ # format them as 'PRIhex SUBhex UPPER_STR'
+ sed -E 's/^\s*0x(..)(..)\s+(\S.*)/\2 \1 \3/p' | tr '[:lower:]-' '[:upper:]_'
+ } | sort | {
+ # format them as '#define LANGID_UPPER_STR 0xSUBPRI'
+ sed -E 's/(..) (..) (.*)/#define LANGID_\3 0x\2\1/' |
+ column --table --output-separator=' '
+ }
+} <3rd-party/MS-LCID.txt
cat <<'EOT'
/** USB 2.0 ยง9.6.6 "Endpoint", field bEndpointAddress, bit 7 */
diff --git a/notes.md b/notes.md
index 8f2f44c..84c2e72 100644
--- a/notes.md
+++ b/notes.md
@@ -187,3 +187,7 @@ OpenBMC
- Sipeed NanoKVM
- https://github.com/stefanklug/picoKVM (~$20 Arduino, ~$5 HDMI
capture), non-IP
+
+----
+
+https://hackaday.com/2022/08/26/bit-banged-ethernet-on-the-raspberry-pi-pico/