This note records the first real kernel-side pthread_workqueue scaffold
landed in /usr/src against FreeBSD 15 stable/15.
The goal of this pass was narrow:
- reserve the syscall entry point;
- add the minimum kernel header and source scaffold;
- make the generated syscall surface update cleanly;
- prove the new path compiles under a debug kernel config.
This pass did not attempt real behavior yet. The syscall still returns
ENOTSUP for known operations and EINVAL for unknown ones when THRWORKQ
is enabled, and ENOSYS when it is not.
Source and config files:
/usr/src/sys/conf/options/usr/src/sys/conf/files/usr/src/sys/kern/syscalls.master/usr/src/sys/sys/thrworkq.h/usr/src/sys/kern/kern_thrworkq.c/usr/src/sys/amd64/conf/TWQDEBUG
Generated files updated through make -C /usr/src/sys/kern sysent:
/usr/src/sys/kern/init_sysent.c/usr/src/sys/kern/syscalls.c/usr/src/sys/sys/syscall.h/usr/src/sys/sys/syscall.mk/usr/src/sys/sys/sysproto.h/usr/src/lib/libsys/_libsys.h/usr/src/lib/libsys/syscalls.map
Slot 468 is now wired as:
twq_kernreturn(int op, void *arg2, int arg3, int arg4)
This keeps the eventual kernel ABI shaped around a Darwin-style command multiplexer rather than inheriting NextBSD's older work-item syscall model.
/usr/src/sys/sys/thrworkq.h now defines:
- the first
TWQ_OP_*command constants; TWQ_FEATURE_*bits needed for later userland negotiation;- the first SPI version constants;
struct twq_dispatch_config;- kernel-side lifecycle hook prototypes for later milestones.
/usr/src/sys/kern/kern_thrworkq.c currently provides:
sys_twq_kernreturn();- command validation for the known
TWQ_OP_*set; twq_proc_exec()andtwq_proc_exit()stubs for later lifecycle work.
/usr/src/sys/amd64/conf/TWQDEBUG now exists as the dedicated kernel config
for this project's bring-up work.
kern_thrworkq.c currently has to be listed as standard, not
optional thrworkq.
Reason:
- the syscall table is generated unconditionally from
syscalls.master; - that means
sys_twq_kernreturnmust always exist at link time; - the option gate therefore has to live inside the implementation for now.
So the correct early pattern is:
- always compile the file;
- return
ENOSYSwhen the option is not enabled; - keep the real behavior behind
#ifdef THRWORKQ.
This is small, but it materially changes how the feature gate should be carried through the early milestones.
Ran:
make -C /usr/src/sys/kern sysentThis completed successfully after making the generated output files writable.
Configured kernel objdir:
/tmp/twqobj/usr/src/amd64.amd64/sys/TWQDEBUG
Successful targeted builds:
make -C /tmp/twqobj/usr/src/amd64.amd64/sys/TWQDEBUG kern_thrworkq.o
make -C /tmp/twqobj/usr/src/amd64.amd64/sys/TWQDEBUG init_sysent.o
make -C /tmp/twqobj/usr/src/amd64.amd64/sys/TWQDEBUG syscalls.oArtifacts confirmed:
kern_thrworkq.oinit_sysent.osyscalls.o
Successful objdir-driven kernel build:
env SRCTOP=/usr/src make -C /tmp/twqobj/usr/src/amd64.amd64/sys/TWQDEBUG kernel -j4Important note:
- the direct objdir invocation needs
SRCTOP=/usr/src; - without that, parts of the kernel build may collapse
${SRCTOP}into an empty path and fail on unrelated include directories such as/sys/dev/ath.
With SRCTOP set correctly, the TWQDEBUG kernel linked successfully and
produced:
kernel.fullkernel.debugkernel
- the
twq_kernreturnsyscall shape is acceptable to FreeBSD's syscall generator; - the generated kernel and libsys surfaces update cleanly;
- the stub source compiles under the
TWQDEBUGkernel environment with-Werror; - there is no immediate structural blocker in
/usr/srcfor the first real scaffold.
- run a clean no-modules kernel build instead of the broad default
buildkernelsweep; - install the resulting
TWQDEBUGkernel into a guest image; - boot the guest and verify the new syscall path is inert but stable;
- confirm non-
THRWORKQkernels still behave correctly.
This is the first point where the project stopped being only strategy and became a real kernel port effort.
The scaffold is intentionally thin, but it already proves three critical things:
- the FreeBSD 15 tree can host the new syscall and header cleanly;
- the project can carry a Darwin-shaped control entry point without dragging in the old donor ABI;
- the next work can move into lifecycle hooks and real state management instead of revisiting the same bootstrap questions.