Introduce the freestanding C17 vocabulary, exact-width kernel types, alignment 
helpers, compiler built-ins, memory primitives, and the initial task/thread 
platform layer. Preserve hardware-specific assembly outside this portable layer.

Signed-off-by: Breno Rodrigues Alves <[email protected]>
---
 modern/Makefile                   |  57 +++
 modern/freestanding/limits.h      |  29 ++
 modern/freestanding/stdalign.h    |  14 +
 modern/freestanding/stdarg.h      |  17 +
 modern/freestanding/stdatomic.h   | 138 +++++++
 modern/freestanding/stdbool.h     |  14 +
 modern/freestanding/stddef.h      |  17 +
 modern/freestanding/stdint.h      |  99 +++++
 modern/freestanding/stdnoreturn.h |  11 +
 modern/freestanding/time.h        |  23 ++
 modern/include/mach/c17/base.h    | 333 +++++++++++++++++
 modern/include/threads.h          | 104 ++++++
 modern/src/core/mem.c             | 140 +++++++
 modern/src/core/threads.c         | 594 ++++++++++++++++++++++++++++++
 modern/tests/fake_hw.c            | 220 +++++++++++
 modern/tests/fake_hw.h            |  50 +++
 modern/tests/test.h               |  51 +++
 modern/tests/test_threads.c       |  99 +++++
 18 files changed, 2010 insertions(+)
 create mode 100644 modern/Makefile
 create mode 100644 modern/freestanding/limits.h
 create mode 100644 modern/freestanding/stdalign.h
 create mode 100644 modern/freestanding/stdarg.h
 create mode 100644 modern/freestanding/stdatomic.h
 create mode 100644 modern/freestanding/stdbool.h
 create mode 100644 modern/freestanding/stddef.h
 create mode 100644 modern/freestanding/stdint.h
 create mode 100644 modern/freestanding/stdnoreturn.h
 create mode 100644 modern/freestanding/time.h
 create mode 100644 modern/include/mach/c17/base.h
 create mode 100644 modern/include/threads.h
 create mode 100644 modern/src/core/mem.c
 create mode 100644 modern/src/core/threads.c
 create mode 100644 modern/tests/fake_hw.c
 create mode 100644 modern/tests/fake_hw.h
 create mode 100644 modern/tests/test.h
 create mode 100644 modern/tests/test_threads.c

diff --git a/modern/Makefile b/modern/Makefile
new file mode 100644
index 00000000..5a3776b3
--- /dev/null
+++ b/modern/Makefile
@@ -0,0 +1,57 @@
+# Makefile for the C17 Mach platform layer.
+#
+# The library is built exactly as required by the project brief:
+#
+#   -std=c17 -Wall -Wextra -Wpedantic -nostdinc -ffreestanding
+#
+# `-nostdinc` is paired with a small freestanding header set in
+# freestanding/ so that no hosted libc header can leak into kernel code.
+# Tests are hosted programs and link the same archive.
+
+CC ?= gcc
+AR ?= ar
+CFLAGS ?= -O2 -g
+WARNINGS = -Wall -Wextra -Wpedantic -Wshadow -Wstrict-prototypes
+CSTD = -std=c17
+FREESTANDING = $(CSTD) $(WARNINGS) -nostdinc -ffreestanding
+INCLUDES = -Iinclude -isystem freestanding
+HOST_INCLUDES = -Iinclude
+
+BUILD = build
+LIB = $(BUILD)/libmachc17.a
+LIB_SRCS = $(sort $(wildcard src/*/*.c))
+LIB_OBJS = $(patsubst src/%.c,$(BUILD)/obj/%.o,$(LIB_SRCS))
+
+TEST_SRCS = $(sort $(wildcard tests/test_*.c))
+TEST_NONTEST = $(sort $(filter-out tests/test_%.c,$(wildcard tests/*.c)))
+TEST_BINS = $(patsubst tests/test_%.c,$(BUILD)/test_%,$(TEST_SRCS))
+
+.PHONY: all lib check test clean
+
+all: lib
+
+lib: $(LIB)
+
+$(LIB): $(LIB_OBJS)
+       @mkdir -p $(dir $@)
+       $(AR) rcs $@ $^
+
+$(BUILD)/obj/%.o: src/%.c
+       @mkdir -p $(dir $@)
+       $(CC) $(CFLAGS) $(FREESTANDING) $(INCLUDES) -c $< -o $@
+
+$(BUILD)/test_%: tests/test_%.c $(LIB) $(TEST_NONTEST)
+       @mkdir -p $(dir $@)
+       $(CC) $(CFLAGS) $(CSTD) $(WARNINGS) $(HOST_INCLUDES) $< $(TEST_NONTEST) 
\
+         $(LIB) -o $@
+
+check: $(TEST_BINS)
+       @set -e; for test in $(TEST_BINS); do \
+         echo "running $$test"; \
+         $$test; \
+       done
+
+test: check
+
+clean:
+       rm -rf $(BUILD)
diff --git a/modern/freestanding/limits.h b/modern/freestanding/limits.h
new file mode 100644
index 00000000..392997ba
--- /dev/null
+++ b/modern/freestanding/limits.h
@@ -0,0 +1,29 @@
+/* Freestanding <limits.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See stdint.h for the license.  */
+
+#ifndef _MACH_FREESTANDING_LIMITS_H
+#define _MACH_FREESTANDING_LIMITS_H 1
+
+#define CHAR_BIT __CHAR_BIT__
+#define SCHAR_MIN (-SCHAR_MAX - 1)
+#define SCHAR_MAX __SCHAR_MAX__
+#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
+#define CHAR_MIN SCHAR_MIN
+#define CHAR_MAX SCHAR_MAX
+#define MB_LEN_MAX 1
+#define SHRT_MIN (-SHRT_MAX - 1)
+#define SHRT_MAX __SHRT_MAX__
+#define USHRT_MAX (SHRT_MAX * 2 + 1)
+#define INT_MIN (-INT_MAX - 1)
+#define INT_MAX __INT_MAX__
+#define UINT_MAX (INT_MAX * 2U + 1U)
+#define LONG_MIN (-LONG_MAX - 1L)
+#define LONG_MAX __LONG_MAX__
+#define ULONG_MAX (LONG_MAX * 2UL + 1UL)
+#define LLONG_MIN (-LLONG_MAX - 1LL)
+#define LLONG_MAX __LONG_LONG_MAX__
+#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
+
+#endif /* _MACH_FREESTANDING_LIMITS_H */
diff --git a/modern/freestanding/stdalign.h b/modern/freestanding/stdalign.h
new file mode 100644
index 00000000..453ae62b
--- /dev/null
+++ b/modern/freestanding/stdalign.h
@@ -0,0 +1,14 @@
+/* Freestanding <stdalign.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See stdint.h for the license.  */
+
+#ifndef _MACH_FREESTANDING_STDALIGN_H
+#define _MACH_FREESTANDING_STDALIGN_H 1
+
+#define alignas _Alignas
+#define alignof _Alignof
+#define __alignas_is_defined 1
+#define __alignof_is_defined 1
+
+#endif /* _MACH_FREESTANDING_STDALIGN_H */
diff --git a/modern/freestanding/stdarg.h b/modern/freestanding/stdarg.h
new file mode 100644
index 00000000..a84d4e79
--- /dev/null
+++ b/modern/freestanding/stdarg.h
@@ -0,0 +1,17 @@
+/* Freestanding <stdarg.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See stdint.h for the license.  */
+
+#ifndef _MACH_FREESTANDING_STDARG_H
+#define _MACH_FREESTANDING_STDARG_H 1
+
+typedef __builtin_va_list va_list;
+typedef __builtin_va_list __gnuc_va_list;
+
+#define va_start(ap, last) __builtin_va_start (ap, last)
+#define va_end(ap) __builtin_va_end (ap)
+#define va_arg(ap, type) __builtin_va_arg (ap, type)
+#define va_copy(dest, src) __builtin_va_copy (dest, src)
+
+#endif /* _MACH_FREESTANDING_STDARG_H */
diff --git a/modern/freestanding/stdatomic.h b/modern/freestanding/stdatomic.h
new file mode 100644
index 00000000..4f435557
--- /dev/null
+++ b/modern/freestanding/stdatomic.h
@@ -0,0 +1,138 @@
+/* Freestanding <stdatomic.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See stdint.h for the license.
+
+   ISO C17 makes <stdatomic.h> optional in freestanding environments.
+   GNU Mach nonetheless promises C17 atomics everywhere, so this header
+   maps the standard names onto the compiler's __atomic builtins.  The
+   mapping is deliberately thin: it keeps the standard spelling in the
+   kernel while letting the compiler pick the narrowest instruction that
+   respects the requested ordering.  */
+
+#ifndef _MACH_FREESTANDING_STDATOMIC_H
+#define _MACH_FREESTANDING_STDATOMIC_H 1
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+
+typedef enum
+{
+  memory_order_relaxed = __ATOMIC_RELAXED,
+  memory_order_consume = __ATOMIC_CONSUME,
+  memory_order_acquire = __ATOMIC_ACQUIRE,
+  memory_order_release = __ATOMIC_RELEASE,
+  memory_order_acq_rel = __ATOMIC_ACQ_REL,
+  memory_order_seq_cst = __ATOMIC_SEQ_CST
+} memory_order;
+
+typedef _Atomic _Bool atomic_bool;
+typedef _Atomic char atomic_char;
+typedef _Atomic signed char atomic_schar;
+typedef _Atomic unsigned char atomic_uchar;
+typedef _Atomic short atomic_short;
+typedef _Atomic unsigned short atomic_ushort;
+typedef _Atomic int atomic_int;
+typedef _Atomic unsigned int atomic_uint;
+typedef _Atomic long atomic_long;
+typedef _Atomic unsigned long atomic_ulong;
+typedef _Atomic long long atomic_llong;
+typedef _Atomic unsigned long long atomic_ullong;
+typedef _Atomic intptr_t atomic_intptr_t;
+typedef _Atomic uintptr_t atomic_uintptr_t;
+typedef _Atomic size_t atomic_size_t;
+typedef _Atomic ptrdiff_t atomic_ptrdiff_t;
+typedef _Atomic intmax_t atomic_intmax_t;
+typedef _Atomic uintmax_t atomic_uintmax_t;
+
+#define ATOMIC_VAR_INIT(value) (value)
+#define ATOMIC_FLAG_INIT { false }
+
+typedef struct
+{
+  _Atomic bool value;
+} atomic_flag;
+
+#define atomic_init(obj, value) \
+  __atomic_store_n ((obj), (value), __ATOMIC_RELAXED)
+
+#define atomic_load(obj) \
+  __atomic_load_n ((obj), __ATOMIC_SEQ_CST)
+#define atomic_load_explicit(obj, order) \
+  __atomic_load_n ((obj), (order))
+
+#define atomic_store(obj, value) \
+  __atomic_store_n ((obj), (value), __ATOMIC_SEQ_CST)
+#define atomic_store_explicit(obj, value, order) \
+  __atomic_store_n ((obj), (value), (order))
+
+#define atomic_exchange(obj, value) \
+  __atomic_exchange_n ((obj), (value), __ATOMIC_SEQ_CST)
+#define atomic_exchange_explicit(obj, value, order) \
+  __atomic_exchange_n ((obj), (value), (order))
+
+#define atomic_compare_exchange_strong(obj, expected, desired) \
+  __atomic_compare_exchange_n ((obj), (expected), (desired), 0, \
+                               __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#define atomic_compare_exchange_weak(obj, expected, desired) \
+  __atomic_compare_exchange_n ((obj), (expected), (desired), 1, \
+                               __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
+#define atomic_compare_exchange_strong_explicit(obj, expected, desired, \
+                                                success, failure) \
+  __atomic_compare_exchange_n ((obj), (expected), (desired), 0, \
+                               (success), (failure))
+#define atomic_compare_exchange_weak_explicit(obj, expected, desired, \
+                                              success, failure) \
+  __atomic_compare_exchange_n ((obj), (expected), (desired), 1, \
+                               (success), (failure))
+
+#define atomic_fetch_add(obj, value) \
+  __atomic_fetch_add ((obj), (value), __ATOMIC_SEQ_CST)
+#define atomic_fetch_add_explicit(obj, value, order) \
+  __atomic_fetch_add ((obj), (value), (order))
+#define atomic_fetch_sub(obj, value) \
+  __atomic_fetch_sub ((obj), (value), __ATOMIC_SEQ_CST)
+#define atomic_fetch_sub_explicit(obj, value, order) \
+  __atomic_fetch_sub ((obj), (value), (order))
+#define atomic_fetch_or(obj, value) \
+  __atomic_fetch_or ((obj), (value), __ATOMIC_SEQ_CST)
+#define atomic_fetch_or_explicit(obj, value, order) \
+  __atomic_fetch_or ((obj), (value), (order))
+#define atomic_fetch_and(obj, value) \
+  __atomic_fetch_and ((obj), (value), __ATOMIC_SEQ_CST)
+#define atomic_fetch_and_explicit(obj, value, order) \
+  __atomic_fetch_and ((obj), (value), (order))
+
+#define atomic_thread_fence(order) __atomic_thread_fence (order)
+#define atomic_signal_fence(order) __atomic_signal_fence (order)
+
+static inline bool
+atomic_flag_test_and_set (volatile atomic_flag *flag)
+{
+  return __atomic_exchange_n (&flag->value, true, __ATOMIC_SEQ_CST);
+}
+
+static inline bool
+atomic_flag_test_and_set_explicit (volatile atomic_flag *flag,
+                                   memory_order order)
+{
+  return __atomic_exchange_n (&flag->value, true, order);
+}
+
+static inline void
+atomic_flag_clear (volatile atomic_flag *flag)
+{
+  __atomic_store_n (&flag->value, false, __ATOMIC_SEQ_CST);
+}
+
+static inline void
+atomic_flag_clear_explicit (volatile atomic_flag *flag, memory_order order)
+{
+  __atomic_store_n (&flag->value, false, order);
+}
+
+#define atomic_is_lock_free(obj) __atomic_is_lock_free (sizeof (*(obj)), (obj))
+#define kill_dependency(value) (value)
+
+#endif /* _MACH_FREESTANDING_STDATOMIC_H */
diff --git a/modern/freestanding/stdbool.h b/modern/freestanding/stdbool.h
new file mode 100644
index 00000000..469453e8
--- /dev/null
+++ b/modern/freestanding/stdbool.h
@@ -0,0 +1,14 @@
+/* Freestanding <stdbool.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See stdint.h for the license.  */
+
+#ifndef _MACH_FREESTANDING_STDBOOL_H
+#define _MACH_FREESTANDING_STDBOOL_H 1
+
+#define bool _Bool
+#define true 1
+#define false 0
+#define __bool_true_false_are_defined 1
+
+#endif /* _MACH_FREESTANDING_STDBOOL_H */
diff --git a/modern/freestanding/stddef.h b/modern/freestanding/stddef.h
new file mode 100644
index 00000000..35977583
--- /dev/null
+++ b/modern/freestanding/stddef.h
@@ -0,0 +1,17 @@
+/* Freestanding <stddef.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See stdint.h for the license.  */
+
+#ifndef _MACH_FREESTANDING_STDDEF_H
+#define _MACH_FREESTANDING_STDDEF_H 1
+
+typedef __SIZE_TYPE__ size_t;
+typedef __PTRDIFF_TYPE__ ptrdiff_t;
+typedef __WCHAR_TYPE__ wchar_t;
+typedef long double max_align_t;
+
+#define NULL ((void *) 0)
+#define offsetof(type, member) __builtin_offsetof (type, member)
+
+#endif /* _MACH_FREESTANDING_STDDEF_H */
diff --git a/modern/freestanding/stdint.h b/modern/freestanding/stdint.h
new file mode 100644
index 00000000..c66ad833
--- /dev/null
+++ b/modern/freestanding/stdint.h
@@ -0,0 +1,99 @@
+/* Freestanding <stdint.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.
+
+   GNU Mach is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GNU Mach is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
+
+#ifndef _MACH_FREESTANDING_STDINT_H
+#define _MACH_FREESTANDING_STDINT_H 1
+
+/* The kernel is compiled with -nostdinc so that no hosted header can
+   leak into it.  GCC still exposes the target's exact-width types
+   through its predefined macros, which is all ISO C requires here.  */
+
+typedef __INT8_TYPE__ int8_t;
+typedef __INT16_TYPE__ int16_t;
+typedef __INT32_TYPE__ int32_t;
+typedef __INT64_TYPE__ int64_t;
+
+typedef __UINT8_TYPE__ uint8_t;
+typedef __UINT16_TYPE__ uint16_t;
+typedef __UINT32_TYPE__ uint32_t;
+typedef __UINT64_TYPE__ uint64_t;
+
+typedef __INT_LEAST8_TYPE__ int_least8_t;
+typedef __INT_LEAST16_TYPE__ int_least16_t;
+typedef __INT_LEAST32_TYPE__ int_least32_t;
+typedef __INT_LEAST64_TYPE__ int_least64_t;
+
+typedef __UINT_LEAST8_TYPE__ uint_least8_t;
+typedef __UINT_LEAST16_TYPE__ uint_least16_t;
+typedef __UINT_LEAST32_TYPE__ uint_least32_t;
+typedef __UINT_LEAST64_TYPE__ uint_least64_t;
+
+typedef __INT_FAST8_TYPE__ int_fast8_t;
+typedef __INT_FAST16_TYPE__ int_fast16_t;
+typedef __INT_FAST32_TYPE__ int_fast32_t;
+typedef __INT_FAST64_TYPE__ int_fast64_t;
+
+typedef __UINT_FAST8_TYPE__ uint_fast8_t;
+typedef __UINT_FAST16_TYPE__ uint_fast16_t;
+typedef __UINT_FAST32_TYPE__ uint_fast32_t;
+typedef __UINT_FAST64_TYPE__ uint_fast64_t;
+
+typedef __INTPTR_TYPE__ intptr_t;
+typedef __UINTPTR_TYPE__ uintptr_t;
+typedef __INTMAX_TYPE__ intmax_t;
+typedef __UINTMAX_TYPE__ uintmax_t;
+
+#define INT8_MIN (-INT8_MAX - 1)
+#define INT16_MIN (-INT16_MAX - 1)
+#define INT32_MIN (-INT32_MAX - 1)
+#define INT64_MIN (-INT64_MAX - 1)
+
+#define INT8_MAX __INT8_MAX__
+#define INT16_MAX __INT16_MAX__
+#define INT32_MAX __INT32_MAX__
+#define INT64_MAX __INT64_MAX__
+
+#define UINT8_MAX __UINT8_MAX__
+#define UINT16_MAX __UINT16_MAX__
+#define UINT32_MAX __UINT32_MAX__
+#define UINT64_MAX __UINT64_MAX__
+
+#define INTPTR_MIN (-INTPTR_MAX - 1)
+#define INTPTR_MAX __INTPTR_MAX__
+#define UINTPTR_MAX __UINTPTR_MAX__
+
+#define INTMAX_MIN (-INTMAX_MAX - 1)
+#define INTMAX_MAX __INTMAX_MAX__
+#define UINTMAX_MAX __UINTMAX_MAX__
+
+#define SIZE_MAX __SIZE_MAX__
+
+#define INT8_C(c) c
+#define INT16_C(c) c
+#define INT32_C(c) c
+#define INT64_C(c) c##L
+#define UINT8_C(c) c
+#define UINT16_C(c) c
+#define UINT32_C(c) c##U
+#define UINT64_C(c) c##UL
+#define INTMAX_C(c) c##L
+#define UINTMAX_C(c) c##UL
+
+#endif /* _MACH_FREESTANDING_STDINT_H */
diff --git a/modern/freestanding/stdnoreturn.h 
b/modern/freestanding/stdnoreturn.h
new file mode 100644
index 00000000..a7d91921
--- /dev/null
+++ b/modern/freestanding/stdnoreturn.h
@@ -0,0 +1,11 @@
+/* Freestanding <stdnoreturn.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See stdint.h for the license.  */
+
+#ifndef _MACH_FREESTANDING_STDNORETURN_H
+#define _MACH_FREESTANDING_STDNORETURN_H 1
+
+#define noreturn _Noreturn
+
+#endif /* _MACH_FREESTANDING_STDNORETURN_H */
diff --git a/modern/freestanding/time.h b/modern/freestanding/time.h
new file mode 100644
index 00000000..0a088ac7
--- /dev/null
+++ b/modern/freestanding/time.h
@@ -0,0 +1,23 @@
+/* Freestanding <time.h> for the C17 Mach platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See stdint.h for the license.  */
+
+#ifndef _MACH_FREESTANDING_TIME_H
+#define _MACH_FREESTANDING_TIME_H 1
+
+#include <stdint.h>
+
+typedef int64_t time_t;
+typedef int64_t clock_t;
+
+struct timespec
+{
+  time_t tv_sec;
+  long tv_nsec;
+};
+
+#define TIME_UTC 1
+#define CLOCKS_PER_SEC 1000000
+
+#endif /* _MACH_FREESTANDING_TIME_H */
diff --git a/modern/include/mach/c17/base.h b/modern/include/mach/c17/base.h
new file mode 100644
index 00000000..7ee4c1e9
--- /dev/null
+++ b/modern/include/mach/c17/base.h
@@ -0,0 +1,333 @@
+/* Base definitions for the C17 Mach kernel platform.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.
+
+   GNU Mach is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.  */
+
+#ifndef _MACH_C17_BASE_H
+#define _MACH_C17_BASE_H 1
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdalign.h>
+#include <limits.h>
+
+/* ---------------------------------------------------------------------
+   Compiler vocabulary.
+
+   The kernel is built by GCC with -ffreestanding, so the only portable
+   vocabulary available is the ISO C17 one plus the attributes below.
+   Every attribute is spelled once, here, so that the rest of the tree
+   reads as plain C17.  */
+
+#define MACH_INLINE static inline
+#define MACH_NOINLINE __attribute__ ((noinline))
+#define MACH_NORETURN __attribute__ ((noreturn))
+#define MACH_UNUSED __attribute__ ((unused))
+#define MACH_WARN_UNUSED __attribute__ ((warn_unused_result))
+#define MACH_PACKED __attribute__ ((packed))
+#define MACH_ALIGNAS(value) __attribute__ ((aligned (value)))
+#define MACH_ALIGNOF(type) _Alignof (type)
+
+/* A cache line is the unit of false-sharing avoidance.  Structures that
+   are written by different CPUs are padded to this boundary and the hot
+   fields are separated by whole lines.  */
+#define MACH_CACHELINE 64u
+#define MACH_CACHELINE_ALIGN MACH_ALIGNAS (MACH_CACHELINE)
+
+#define MACH_PAGE_SHIFT 12u
+#define MACH_PAGE_SIZE (1u << MACH_PAGE_SHIFT)
+#define MACH_PAGE_MASK (MACH_PAGE_SIZE - 1u)
+
+#define MACH_KB (1024ull)
+#define MACH_MB (1024ull * MACH_KB)
+#define MACH_GB (1024ull * MACH_MB)
+
+#define MACH_FALSE 0
+#define MACH_TRUE 1
+
+#define MACH_ARRAY_SIZE(array) (sizeof (array) / sizeof ((array)[0]))
+
+#define MACH_CONTAINER_OF(pointer, type, member) \
+  ((type *) ((char *) (pointer) - offsetof (type, member)))
+
+#define MACH_LIKELY(expr) __builtin_expect (!!(expr), 1)
+#define MACH_UNLIKELY(expr) __builtin_expect (!!(expr), 0)
+#define MACH_STATIC_ASSERT(condition, message) \
+  _Static_assert (condition, message)
+
+/* ---------------------------------------------------------------------
+   Machine words and kernel identifiers.  */
+
+typedef uint64_t mach_phys_t;
+typedef uint64_t mach_vaddr_t;
+typedef uint64_t mach_vm_size_t;
+typedef uint64_t mach_vm_offset_t;
+typedef uint64_t mach_time_t;          /* Nanoseconds, monotonic.  */
+typedef uint32_t mach_cpu_id_t;
+typedef uint32_t mach_thread_id_t;
+typedef uint32_t mach_task_id_t;
+typedef uint32_t mach_port_name_t;
+typedef uint32_t mach_msg_size_t;
+typedef int32_t mach_msg_id_t;
+typedef int32_t mach_priority_t;
+typedef uint32_t mach_flags_t;
+
+#define MACH_PORT_NULL ((mach_port_name_t) 0)
+#define MACH_PORT_DEAD ((mach_port_name_t) ~0u)
+#define MACH_THREAD_NULL ((mach_thread_id_t) 0)
+#define MACH_CPU_NULL ((mach_cpu_id_t) ~0u)
+
+/* Kernel result codes.  Mach traditionally uses kern_return_t; the
+   modern layer keeps the numeric contract while using an enumerated
+   type so that -Wpedantic diagnose accidental integer mixing.  */
+typedef enum mach_error
+{
+  MACH_OK = 0,
+  MACH_EPERM = 1,
+  MACH_ENOENT = 2,
+  MACH_EINTR = 4,
+  MACH_EIO = 5,
+  MACH_EAGAIN = 11,
+  MACH_ENOMEM = 12,
+  MACH_EBUSY = 16,
+  MACH_ENODEV = 19,
+  MACH_EINVAL = 22,
+  MACH_ERANGE = 34,
+  MACH_ENOSYS = 78,
+  MACH_ETIMEDOUT = 110
+} mach_error_t;
+
+/* ---------------------------------------------------------------------
+   Intrusive lists.
+
+   The scheduler, the VM free lists and the IPC wait queues all need
+   O(1) insertion and removal without allocating.  A single header is
+   enough for all three and keeps the data structures cache-friendly.  */
+
+struct mach_list
+{
+  struct mach_list *next;
+  struct mach_list *prev;
+};
+
+MACH_INLINE void
+mach_list_init (struct mach_list *head)
+{
+  head->next = head;
+  head->prev = head;
+}
+
+MACH_INLINE bool
+mach_list_empty (const struct mach_list *head)
+{
+  return head->next == head;
+}
+
+MACH_INLINE void
+mach_list_insert_between (struct mach_list *link,
+                          struct mach_list *prev,
+                          struct mach_list *next)
+{
+  link->next = next;
+  link->prev = prev;
+  prev->next = link;
+  next->prev = link;
+}
+
+MACH_INLINE void
+mach_list_add_tail (struct mach_list *head, struct mach_list *link)
+{
+  mach_list_insert_between (link, head->prev, head);
+}
+
+MACH_INLINE void
+mach_list_add_head (struct mach_list *head, struct mach_list *link)
+{
+  mach_list_insert_between (link, head, head->next);
+}
+
+MACH_INLINE void
+mach_list_remove (struct mach_list *link)
+{
+  link->prev->next = link->next;
+  link->next->prev = link->prev;
+  link->next = link;
+  link->prev = link;
+}
+
+/* Move every element of SRC to the tail of DST and reinitialise SRC.
+   Used by the scheduler when it drains a remote run queue.  */
+MACH_INLINE void
+mach_list_splice_tail (struct mach_list *dst, struct mach_list *src)
+{
+  struct mach_list *first;
+  struct mach_list *last;
+
+  if (mach_list_empty (src))
+    return;
+
+  first = src->next;
+  last = src->prev;
+  first->prev = dst->prev;
+  dst->prev->next = first;
+  last->next = dst;
+  dst->prev = last;
+  mach_list_init (src);
+}
+
+#define MACH_LIST_ENTRY(link, type, member) \
+  MACH_CONTAINER_OF (link, type, member)
+
+/* ---------------------------------------------------------------------
+   Bit operations.  */
+
+MACH_INLINE void
+mach_bit_set (volatile uint64_t *word, unsigned int bit)
+{
+  *word |= (uint64_t) 1 << (bit & 63u);
+}
+
+MACH_INLINE void
+mach_bit_clear (volatile uint64_t *word, unsigned int bit)
+{
+  *word &= ~((uint64_t) 1 << (bit & 63u));
+}
+
+MACH_INLINE bool
+mach_bit_test (const volatile uint64_t *word, unsigned int bit)
+{
+  return (*word >> (bit & 63u)) & 1u;
+}
+
+MACH_INLINE unsigned int
+mach_ffs64 (uint64_t value)
+{
+  return value == 0 ? 64u : (unsigned int) __builtin_ctzll (value);
+}
+
+MACH_INLINE unsigned int
+mach_fls64 (uint64_t value)
+{
+  return value == 0 ? 0u : 64u - (unsigned int) __builtin_clzll (value);
+}
+
+MACH_INLINE unsigned int
+mach_popcount64 (uint64_t value)
+{
+  return (unsigned int) __builtin_popcountll (value);
+}
+
+/* ---------------------------------------------------------------------
+   Arithmetic helpers.
+
+   _Generic keeps the call sites free of casts: aligning a size_t, a
+   physical address or a 32-bit length all use the same spelling, but
+   the compiler still checks the operand type.  */
+
+MACH_INLINE size_t
+mach_align_up_size (size_t value, size_t alignment)
+{
+  return (value + alignment - 1u) & ~(alignment - 1u);
+}
+
+MACH_INLINE uint64_t
+mach_align_up_u64 (uint64_t value, uint64_t alignment)
+{
+  return (value + alignment - 1u) & ~(alignment - 1u);
+}
+
+MACH_INLINE uint32_t
+mach_align_up_u32 (uint32_t value, uint32_t alignment)
+{
+  return (value + alignment - 1u) & ~(alignment - 1u);
+}
+
+#define mach_align_up(value, alignment) _Generic ((value), \
+  size_t: mach_align_up_size, \
+  uint64_t: mach_align_up_u64, \
+  uint32_t: mach_align_up_u32, \
+  int: mach_align_up_u32) ((value), (alignment))
+
+MACH_INLINE uint64_t
+mach_align_down_u64 (uint64_t value, uint64_t alignment)
+{
+  return value & ~(alignment - 1u);
+}
+
+MACH_INLINE uint64_t
+mach_div_round_up_u64 (uint64_t value, uint64_t divisor)
+{
+  return (value + divisor - 1u) / divisor;
+}
+
+MACH_INLINE uint64_t
+mach_min_u64 (uint64_t a, uint64_t b)
+{
+  return a < b ? a : b;
+}
+
+MACH_INLINE uint64_t
+mach_max_u64 (uint64_t a, uint64_t b)
+{
+  return a > b ? a : b;
+}
+
+#define mach_min(a, b) _Generic ((a), \
+  uint64_t: mach_min_u64, \
+  size_t: mach_min_u64) ((a), (b))
+
+#define mach_max(a, b) _Generic ((a), \
+  uint64_t: mach_max_u64, \
+  size_t: mach_max_u64) ((a), (b))
+
+MACH_INLINE uint64_t
+mach_log2_floor_u64 (uint64_t value)
+{
+  return value == 0 ? 0 : (uint64_t) (63 - __builtin_clzll (value));
+}
+
+MACH_INLINE uint64_t
+mach_log2_ceil_u64 (uint64_t value)
+{
+  return value <= 1 ? 0 : mach_log2_floor_u64 (value - 1) + 1;
+}
+
+/* ---------------------------------------------------------------------
+   Memory primitives.
+
+   A freestanding compiler is allowed to turn even a trivial loop into a
+   call to memcpy or memset, so the kernel provides definitions for the
+   small set of primitives GCC may emit.  The public names below are the
+   ones kernel code should use; the standard spellings live in mem.c.  */
+
+void *mach_memcpy (void *restrict dest, const void *restrict src, size_t n);
+void *mach_memmove (void *dest, const void *src, size_t n);
+void *mach_memset (void *dest, int value, size_t n);
+int mach_memcmp (const void *left, const void *right, size_t n);
+size_t mach_strlen (const char *string);
+char *mach_strcpy (char *restrict dest, const char *restrict src);
+int mach_strcmp (const char *left, const char *right);
+
+/* A short, portability-friendly delay for spin loops.  The pause
+   instruction lets an SMT sibling make progress on x86; on other
+   architectures the compiler barrier is sufficient because the loop
+   already contains an acquire load.  */
+MACH_INLINE void
+mach_cpu_relax (void)
+{
+#if defined (__x86_64__) || defined (__i386__)
+  __asm__ __volatile__ ("pause" ::: "memory");
+#elif defined (__aarch64__)
+  __asm__ __volatile__ ("yield" ::: "memory");
+#else
+  __asm__ __volatile__ ("" ::: "memory");
+#endif
+}
+
+#endif /* _MACH_C17_BASE_H */
diff --git a/modern/include/threads.h b/modern/include/threads.h
new file mode 100644
index 00000000..4bd44bcf
--- /dev/null
+++ b/modern/include/threads.h
@@ -0,0 +1,104 @@
+/* C17 threads interface implemented by the Mach kernel.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.
+
+   GNU Mach is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   In a freestanding kernel <threads.h> does not exist, yet the C17
+   memory and threading model is exactly what the IPC and scheduler code
+   need.  The kernel therefore provides the standard interface itself,
+   implemented on top of the hybrid scheduler.  Kernel code uses the
+   standard names; user space linked against this library gets the same
+   semantics without a hidden libc dependency.  */
+
+#ifndef _MACH_C17_THREADS_H
+#define _MACH_C17_THREADS_H 1
+
+#include <time.h>
+
+#include <mach/c17/base.h>
+#include <mach/c17/atomic.h>
+#include <mach/c17/sched.h>
+
+typedef struct mach_thread *thrd_t;
+typedef int (*thrd_start_t) (void *);
+
+enum
+{
+  thrd_success = 0,
+  thrd_nomem = 1,
+  thrd_timedout = 2,
+  thrd_busy = 3,
+  thrd_error = 4
+};
+
+enum
+{
+  mtx_plain = 0x1,
+  mtx_recursive = 0x2,
+  mtx_timed = 0x4
+};
+
+typedef struct mach_mutex
+{
+  mach_atomic_u32 state;                /* 0 free, 1 held, 2 contended.  */
+  struct mach_thread *owner;
+  mach_priority_t owner_priority;
+  uint32_t recursion;
+  uint32_t flags;
+} mtx_t;
+
+typedef struct mach_cond
+{
+  mach_atomic_u32 sequence;
+  uint32_t waiters;
+} cnd_t;
+
+typedef struct mach_once
+{
+  mach_atomic_u32 state;
+} once_flag;
+
+#define ONCE_FLAG_INIT { 0u }
+
+typedef uint32_t tss_t;
+#define TSS_DTOR_ITERATIONS 4
+
+typedef void (*tss_dtor_t) (void *);
+
+int thrd_create (thrd_t *thread, thrd_start_t start, void *argument);
+int thrd_join (thrd_t thread, int *result);
+int thrd_detach (thrd_t thread);
+int thrd_equal (thrd_t left, thrd_t right);
+thrd_t thrd_current (void);
+int thrd_sleep (const struct timespec *duration, struct timespec *remaining);
+void thrd_yield (void);
+MACH_NORETURN void thrd_exit (int result);
+
+int mtx_init (mtx_t *mutex, int type);
+void mtx_destroy (mtx_t *mutex);
+int mtx_lock (mtx_t *mutex);
+int mtx_trylock (mtx_t *mutex);
+int mtx_timedlock (mtx_t *mutex, const struct timespec *time_point);
+int mtx_unlock (mtx_t *mutex);
+
+int cnd_init (cnd_t *condition);
+void cnd_destroy (cnd_t *condition);
+int cnd_signal (cnd_t *condition);
+int cnd_broadcast (cnd_t *condition);
+int cnd_wait (cnd_t *condition, mtx_t *mutex);
+int cnd_timedwait (cnd_t *condition, mtx_t *mutex,
+                   const struct timespec *time_point);
+
+void call_once (once_flag *flag, void (*function) (void));
+
+int tss_create (tss_t *key, tss_dtor_t destructor);
+void tss_delete (tss_t key);
+void *tss_get (tss_t key);
+int tss_set (tss_t key, void *value);
+
+#endif /* _MACH_C17_THREADS_H */
diff --git a/modern/src/core/mem.c b/modern/src/core/mem.c
new file mode 100644
index 00000000..fde77c71
--- /dev/null
+++ b/modern/src/core/mem.c
@@ -0,0 +1,140 @@
+/* Freestanding memory primitives.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See base.h for the license.
+
+   GCC may replace a loop with a call to memcpy or memset even in
+   freestanding mode.  Defining the standard names here keeps the kernel
+   link self-contained and gives the compiler a definition it can
+   optimise against.  */
+
+#include <stddef.h>
+
+#include <mach/c17/base.h>
+
+void *
+mach_memcpy (void *restrict destination, const void *restrict source, size_t n)
+{
+  unsigned char *to = destination;
+  const unsigned char *from = source;
+
+  while (n-- != 0)
+    *to++ = *from++;
+
+  return destination;
+}
+
+void *
+mach_memmove (void *destination, const void *source, size_t n)
+{
+  unsigned char *to = destination;
+  const unsigned char *from = source;
+
+  if (to < from)
+    while (n-- != 0)
+      *to++ = *from++;
+  else if (to > from)
+    {
+      to += n;
+      from += n;
+      while (n-- != 0)
+        *--to = *--from;
+    }
+
+  return destination;
+}
+
+void *
+mach_memset (void *destination, int value, size_t n)
+{
+  unsigned char *to = destination;
+
+  while (n-- != 0)
+    *to++ = (unsigned char) value;
+
+  return destination;
+}
+
+int
+mach_memcmp (const void *left, const void *right, size_t n)
+{
+  const unsigned char *a = left;
+  const unsigned char *b = right;
+
+  while (n-- != 0)
+    {
+      if (*a != *b)
+        return (int) *a - (int) *b;
+      a++;
+      b++;
+    }
+
+  return 0;
+}
+
+size_t
+mach_strlen (const char *string)
+{
+  const char *end = string;
+
+  while (*end != '\0')
+    end++;
+
+  return (size_t) (end - string);
+}
+
+char *
+mach_strcpy (char *restrict destination, const char *restrict source)
+{
+  char *result = destination;
+
+  do
+    *destination++ = *source;
+  while (*source++ != '\0');
+
+  return result;
+}
+
+int
+mach_strcmp (const char *left, const char *right)
+{
+  while (*left != '\0' && *left == *right)
+    {
+      left++;
+      right++;
+    }
+
+  return (int) (unsigned char) *left - (int) (unsigned char) *right;
+}
+
+/* The compiler may emit calls to the standard spellings.  */
+
+void *
+memcpy (void *restrict destination, const void *restrict source, size_t n)
+{
+  return mach_memcpy (destination, source, n);
+}
+
+void *
+memmove (void *destination, const void *source, size_t n)
+{
+  return mach_memmove (destination, source, n);
+}
+
+void *
+memset (void *destination, int value, size_t n)
+{
+  return mach_memset (destination, value, n);
+}
+
+int
+memcmp (const void *left, const void *right, size_t n)
+{
+  return mach_memcmp (left, right, n);
+}
+
+size_t
+strlen (const char *string)
+{
+  return mach_strlen (string);
+}
diff --git a/modern/src/core/threads.c b/modern/src/core/threads.c
new file mode 100644
index 00000000..f52813cf
--- /dev/null
+++ b/modern/src/core/threads.c
@@ -0,0 +1,594 @@
+/* C17 threads, mutexes and condition variables on the Mach scheduler.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+
+   This file is part of GNU Mach.  See base.h for the license.
+
+   Kernel code cannot call a hosted threading library, so the kernel is
+   the implementation of <threads.h>.  The fast paths are lock-free;
+   contention falls back to yielding, which is always safe because the
+   scheduler always has an idle thread to run.  When a real context
+   switch is available (mach_sched_ops.switch_cpu) yield performs one.  */
+
+#include <threads.h>
+
+#define MACH_THRD_POOL 256u
+
+static struct mach_thread mach_thread_pool[MACH_THRD_POOL];
+static thrd_start_t mach_start_functions[MACH_THRD_POOL];
+static void *mach_start_arguments[MACH_THRD_POOL];
+static mach_atomic_bool mach_thread_used[MACH_THRD_POOL];
+static mach_atomic_u32 mach_thread_pool_ready;
+static mach_atomic_bool mach_running_cooperative;
+
+static tss_dtor_t mach_tss_destructors[MACH_SCHED_TSS_KEYS];
+static mach_atomic_bool mach_tss_used[MACH_SCHED_TSS_KEYS];
+
+static struct mach_thread mach_bootstrap_thread;
+
+/* Code that runs before the scheduler has a current thread (early boot,
+   or a hosted test's main) still needs a stable mutex owner identity.  */
+static struct mach_thread *
+mutex_self (void)
+{
+  struct mach_thread *thread = mach_sched_current_thread ();
+
+  return thread != NULL ? thread : &mach_bootstrap_thread;
+}
+
+static void
+thread_system_init (void)
+{
+  uint32_t index;
+
+  if (atomic_load_explicit (&mach_thread_pool_ready, memory_order_acquire))
+    return;
+
+  for (index = 0; index < MACH_THRD_POOL; index++)
+    {
+      atomic_init (&mach_thread_used[index], false);
+      mach_start_functions[index] = NULL;
+    }
+
+  for (index = 0; index < MACH_SCHED_TSS_KEYS; index++)
+    {
+      atomic_init (&mach_tss_used[index], false);
+      mach_tss_destructors[index] = NULL;
+    }
+
+  atomic_init (&mach_running_cooperative, false);
+
+  if (mach_sched_cpu_count () == 0)
+    {
+      mach_sched_init (NULL);
+      mach_sched_register_cpu (0, MACH_CPU_PERFORMANCE, 1024);
+    }
+
+  atomic_store_explicit (&mach_thread_pool_ready, 1u, memory_order_release);
+}
+
+static struct mach_thread *
+thread_allocate (void)
+{
+  uint32_t index;
+
+  for (index = 0; index < MACH_THRD_POOL; index++)
+    if (!atomic_exchange_explicit (&mach_thread_used[index], true,
+                                   memory_order_acquire))
+      return &mach_thread_pool[index];
+
+  return NULL;
+}
+
+static void
+thread_release (struct mach_thread *thread)
+{
+  size_t index = (size_t) (thread - mach_thread_pool);
+
+  if (index < MACH_THRD_POOL)
+    {
+      mach_start_functions[index] = NULL;
+      atomic_store_explicit (&mach_thread_used[index], false,
+                             memory_order_release);
+    }
+}
+
+static void
+thread_trampoline (void *argument)
+{
+  struct mach_thread *thread = argument;
+  size_t index = (size_t) (thread - mach_thread_pool);
+  thrd_start_t start = mach_start_functions[index];
+
+  thread->exit_status = start (mach_start_arguments[index]);
+}
+
+/* Run one ready thread to completion when no context switch primitive is
+   available.  This is the cooperative mode used by the test harness and
+   by early boot before the first context switch is installed.  */
+
+static void
+thread_run_ready (void)
+{
+  uint32_t cpu_index;
+
+  if (mach_sched_current_thread () != NULL)
+    return;
+
+  for (cpu_index = 0; cpu_index < mach_sched_cpu_count (); cpu_index++)
+    {
+      struct mach_cpu *cpu = mach_sched_cpu_at (cpu_index);
+      struct mach_thread *thread = mach_sched_pick_next (cpu);
+
+      if (thread == NULL)
+        continue;
+
+      atomic_store_explicit (&mach_running_cooperative, true,
+                             memory_order_relaxed);
+      thread->state = MACH_THREAD_RUNNING;
+      cpu->current = thread;
+      thread->cpu = cpu;
+      mach_sched_account_switch (cpu, NULL, thread);
+
+      thread->exit_status = 0;
+      thread->entry (thread->argument);
+
+      thread->state = MACH_THREAD_ZOMBIE;
+      thread->flags &= ~MACH_THREAD_NEED_RESCHED;
+      mach_sched_account_switch (cpu, thread, NULL);
+      cpu->current = NULL;
+
+      if (thread->joiner != NULL)
+        mach_sched_wake (thread->joiner);
+
+      if (thread->detached)
+        thread_release (thread);
+
+      atomic_store_explicit (&mach_running_cooperative, false,
+                             memory_order_relaxed);
+      return;
+    }
+}
+
+int
+thrd_create (thrd_t *thread_out, thrd_start_t start, void *argument)
+{
+  struct mach_thread *thread;
+  size_t index;
+
+  if (thread_out == NULL || start == NULL)
+    return thrd_error;
+
+  thread_system_init ();
+
+  thread = thread_allocate ();
+  if (thread == NULL)
+    return thrd_nomem;
+
+  index = (size_t) (thread - mach_thread_pool);
+  mach_start_functions[index] = start;
+  mach_start_arguments[index] = argument;
+
+  if (mach_sched_thread_init (thread, MACH_PRIO_TIMESHARE,
+                              MACH_SCHED_TIMESHARE, thread_trampoline,
+                              thread) != MACH_OK)
+    {
+      thread_release (thread);
+      return thrd_error;
+    }
+
+  mach_sched_make_ready (thread);
+  *thread_out = thread;
+  return thrd_success;
+}
+
+int
+thrd_join (thrd_t thread, int *result)
+{
+  if (thread == NULL)
+    return thrd_error;
+
+  while (thread->state != MACH_THREAD_ZOMBIE)
+    thrd_yield ();
+
+  if (result != NULL)
+    *result = thread->exit_status;
+
+  /* Joining transfers ownership of the thread object back to the
+     implementation.  A detached thread is released by thrd_exit.  */
+  if (!thread->detached)
+    thread_release (thread);
+
+  return thrd_success;
+}
+
+int
+thrd_detach (thrd_t thread)
+{
+  if (thread == NULL)
+    return thrd_error;
+
+  thread->detached = true;
+
+  if (thread->state == MACH_THREAD_ZOMBIE)
+    thread_release (thread);
+
+  return thrd_success;
+}
+
+int
+thrd_equal (thrd_t left, thrd_t right)
+{
+  return left == right;
+}
+
+thrd_t
+thrd_current (void)
+{
+  return mach_sched_current_thread ();
+}
+
+int
+thrd_sleep (const struct timespec *duration, struct timespec *remaining)
+{
+  mach_time_t deadline;
+
+  (void) remaining;
+
+  if (duration == NULL)
+    {
+      thrd_yield ();
+      return 0;
+    }
+
+  deadline = mach_sched_now_ns ()
+             + (mach_time_t) duration->tv_sec * 1000000000ull
+             + (mach_time_t) duration->tv_nsec;
+
+  if (mach_sched_now_ns () == 0)
+    {
+      /* No monotonic clock is installed yet: a cooperative yield is the
+         best approximation of sleeping during early boot.  */
+      thrd_yield ();
+      return 0;
+    }
+
+  while (mach_sched_now_ns () < deadline)
+    thrd_yield ();
+
+  return 0;
+}
+
+void
+thrd_yield (void)
+{
+  if (mach_sched_current_thread () != NULL
+      && mach_sched_current_thread ()->cpu != NULL)
+    mach_sched_yield ();
+  else
+    thread_run_ready ();
+}
+
+MACH_NORETURN void
+thrd_exit (int result)
+{
+  struct mach_thread *thread = mach_sched_current_thread ();
+
+  if (thread != NULL)
+    {
+      thread->exit_status = result;
+      thread->state = MACH_THREAD_ZOMBIE;
+    }
+
+  for (;;)
+    {
+      thrd_yield ();
+      if (thread != NULL && thread->detached)
+        thread_release (thread);
+    }
+}
+
+int
+mtx_init (mtx_t *mutex, int type)
+{
+  if (mutex == NULL)
+    return thrd_error;
+
+  atomic_init (&mutex->state, 0u);
+  mutex->owner = NULL;
+  mutex->owner_priority = 0;
+  mutex->recursion = 0;
+  mutex->flags = (uint32_t) type;
+  return thrd_success;
+}
+
+void
+mtx_destroy (mtx_t *mutex)
+{
+  (void) mutex;
+}
+
+static bool
+mtx_acquire (mtx_t *mutex)
+{
+  uint32_t expected = 0;
+
+  return atomic_compare_exchange_strong_explicit (&mutex->state, &expected,
+                                                  1u, memory_order_acquire,
+                                                  memory_order_relaxed);
+}
+
+int
+mtx_lock (mtx_t *mutex)
+{
+  struct mach_thread *self;
+
+  if (mutex == NULL)
+    return thrd_error;
+
+  self = mutex_self ();
+
+  if ((mutex->flags & mtx_recursive) != 0 && mutex->owner == self)
+    {
+      mutex->recursion++;
+      return thrd_success;
+    }
+
+  if (!mtx_acquire (mutex))
+    {
+      struct mach_thread *owner = mutex->owner;
+
+      if (owner != NULL && owner != &mach_bootstrap_thread
+          && self != &mach_bootstrap_thread)
+        mach_sched_donate (owner, self->priority);
+
+      while (!mtx_acquire (mutex))
+        thrd_yield ();
+
+      if (owner != NULL && owner != &mach_bootstrap_thread
+          && self != &mach_bootstrap_thread)
+        mach_sched_undonate (owner, self->priority);
+    }
+
+  mutex->owner = self;
+  mutex->owner_priority = self->priority;
+  mutex->recursion = 1;
+  return thrd_success;
+}
+
+int
+mtx_trylock (mtx_t *mutex)
+{
+  struct mach_thread *self;
+
+  if (mutex == NULL)
+    return thrd_error;
+
+  self = mutex_self ();
+
+  if ((mutex->flags & mtx_recursive) != 0 && mutex->owner == self)
+    {
+      mutex->recursion++;
+      return thrd_success;
+    }
+
+  if (!mtx_acquire (mutex))
+    return thrd_busy;
+
+  mutex->owner = self;
+  mutex->owner_priority = self->priority;
+  mutex->recursion = 1;
+  return thrd_success;
+}
+
+int
+mtx_timedlock (mtx_t *mutex, const struct timespec *time_point)
+{
+  mach_time_t deadline;
+
+  if (time_point == NULL)
+    return thrd_error;
+
+  deadline = (mach_time_t) time_point->tv_sec * 1000000000ull
+             + (mach_time_t) time_point->tv_nsec;
+
+  for (;;)
+    {
+      if (mtx_trylock (mutex) == thrd_success)
+        return thrd_success;
+
+      if (mach_sched_now_ns () >= deadline)
+        return thrd_timedout;
+
+      thrd_yield ();
+    }
+}
+
+int
+mtx_unlock (mtx_t *mutex)
+{
+  if (mutex == NULL)
+    return thrd_error;
+
+  if (mutex->recursion > 1)
+    {
+      mutex->recursion--;
+      return thrd_success;
+    }
+
+  mutex->owner = NULL;
+  mutex->recursion = 0;
+  atomic_store_explicit (&mutex->state, 0u, memory_order_release);
+  return thrd_success;
+}
+
+int
+cnd_init (cnd_t *condition)
+{
+  if (condition == NULL)
+    return thrd_error;
+
+  atomic_init (&condition->sequence, 0u);
+  condition->waiters = 0;
+  return thrd_success;
+}
+
+void
+cnd_destroy (cnd_t *condition)
+{
+  (void) condition;
+}
+
+int
+cnd_signal (cnd_t *condition)
+{
+  if (condition == NULL)
+    return thrd_error;
+
+  if (condition->waiters != 0)
+    atomic_fetch_add_explicit (&condition->sequence, 1u,
+                               memory_order_release);
+  return thrd_success;
+}
+
+int
+cnd_broadcast (cnd_t *condition)
+{
+  if (condition == NULL)
+    return thrd_error;
+
+  if (condition->waiters != 0)
+    atomic_fetch_add_explicit (&condition->sequence, 1u,
+                               memory_order_release);
+  return thrd_success;
+}
+
+static int
+cnd_wait_until (cnd_t *condition, mtx_t *mutex, mach_time_t deadline,
+                bool timed)
+{
+  uint32_t sequence;
+
+  if (condition == NULL || mutex == NULL)
+    return thrd_error;
+
+  sequence = atomic_load_explicit (&condition->sequence,
+                                   memory_order_acquire);
+  condition->waiters++;
+  mtx_unlock (mutex);
+
+  for (;;)
+    {
+      if (atomic_load_explicit (&condition->sequence,
+                                memory_order_acquire) != sequence)
+        break;
+
+      if (timed && mach_sched_now_ns () >= deadline)
+        {
+          condition->waiters--;
+          mtx_lock (mutex);
+          return thrd_timedout;
+        }
+
+      thrd_yield ();
+    }
+
+  condition->waiters--;
+  mtx_lock (mutex);
+  return thrd_success;
+}
+
+int
+cnd_wait (cnd_t *condition, mtx_t *mutex)
+{
+  return cnd_wait_until (condition, mutex, 0, false);
+}
+
+int
+cnd_timedwait (cnd_t *condition, mtx_t *mutex,
+               const struct timespec *time_point)
+{
+  mach_time_t deadline;
+
+  if (time_point == NULL)
+    return thrd_error;
+
+  deadline = (mach_time_t) time_point->tv_sec * 1000000000ull
+             + (mach_time_t) time_point->tv_nsec;
+  return cnd_wait_until (condition, mutex, deadline, true);
+}
+
+void
+call_once (once_flag *flag, void (*function) (void))
+{
+  uint32_t expected = 0;
+
+  if (flag == NULL || function == NULL)
+    return;
+
+  if (atomic_compare_exchange_strong_explicit (&flag->state, &expected, 1u,
+                                               memory_order_acquire,
+                                               memory_order_relaxed))
+    {
+      function ();
+      atomic_store_explicit (&flag->state, 2u, memory_order_release);
+      return;
+    }
+
+  while (atomic_load_explicit (&flag->state, memory_order_acquire) != 2u)
+    thrd_yield ();
+}
+
+int
+tss_create (tss_t *key, tss_dtor_t destructor)
+{
+  uint32_t index;
+
+  thread_system_init ();
+
+  if (key == NULL)
+    return thrd_error;
+
+  for (index = 0; index < MACH_SCHED_TSS_KEYS; index++)
+    if (!atomic_exchange_explicit (&mach_tss_used[index], true,
+                                   memory_order_acquire))
+      {
+        mach_tss_destructors[index] = destructor;
+        *key = index;
+        return thrd_success;
+      }
+
+  return thrd_error;
+}
+
+void
+tss_delete (tss_t key)
+{
+  if (key >= MACH_SCHED_TSS_KEYS)
+    return;
+
+  mach_tss_destructors[key] = NULL;
+  atomic_store_explicit (&mach_tss_used[key], false, memory_order_release);
+}
+
+void *
+tss_get (tss_t key)
+{
+  struct mach_thread *thread = mutex_self ();
+
+  if (key >= MACH_SCHED_TSS_KEYS)
+    return NULL;
+
+  return thread->tss[key];
+}
+
+int
+tss_set (tss_t key, void *value)
+{
+  struct mach_thread *thread = mutex_self ();
+
+  if (key >= MACH_SCHED_TSS_KEYS)
+    return thrd_error;
+
+  thread->tss[key] = value;
+  return thrd_success;
+}
diff --git a/modern/tests/fake_hw.c b/modern/tests/fake_hw.c
new file mode 100644
index 00000000..092f46c5
--- /dev/null
+++ b/modern/tests/fake_hw.c
@@ -0,0 +1,220 @@
+/* Shared fake MMIO and DMA backends for the hosted driver tests.
+
+   The kernel drivers never touch a caller pointer, so the tests can
+   drive them entirely through these two abstractions.  The MMIO
+   backend is a flat byte array; tests that need register semantics
+   install their own callbacks and delegate the rest here.  The DMA
+   backend is a bump allocator over a page-aligned arena, which makes
+   physical addresses stable and easy to inspect.  */
+
+#include "fake_hw.h"
+
+#include <string.h>
+
+static uint8_t *
+fake_translate (struct fake_mmio_region *region, mach_phys_t address)
+{
+  if (region == NULL || region->bytes == NULL
+      || address < region->base
+      || address - region->base + 8u > region->size)
+    return NULL;
+
+  return region->bytes + (address - region->base);
+}
+
+uint8_t
+fake_mmio_read8 (void *context, mach_phys_t address)
+{
+  uint8_t *pointer = fake_translate (context, address);
+  uint8_t value = 0;
+
+  if (pointer != NULL)
+    memcpy (&value, pointer, sizeof (value));
+  return value;
+}
+
+uint16_t
+fake_mmio_read16 (void *context, mach_phys_t address)
+{
+  uint8_t *pointer = fake_translate (context, address);
+  uint16_t value = 0;
+
+  if (pointer != NULL)
+    memcpy (&value, pointer, sizeof (value));
+  return value;
+}
+
+uint32_t
+fake_mmio_read32 (void *context, mach_phys_t address)
+{
+  uint8_t *pointer = fake_translate (context, address);
+  uint32_t value = 0;
+
+  if (pointer != NULL)
+    memcpy (&value, pointer, sizeof (value));
+  return value;
+}
+
+uint64_t
+fake_mmio_read64 (void *context, mach_phys_t address)
+{
+  uint8_t *pointer = fake_translate (context, address);
+  uint64_t value = 0;
+
+  if (pointer != NULL)
+    memcpy (&value, pointer, sizeof (value));
+  return value;
+}
+
+void
+fake_mmio_write8 (void *context, mach_phys_t address, uint8_t value)
+{
+  uint8_t *pointer = fake_translate (context, address);
+
+  if (pointer != NULL)
+    memcpy (pointer, &value, sizeof (value));
+}
+
+void
+fake_mmio_write16 (void *context, mach_phys_t address, uint16_t value)
+{
+  uint8_t *pointer = fake_translate (context, address);
+
+  if (pointer != NULL)
+    memcpy (pointer, &value, sizeof (value));
+}
+
+void
+fake_mmio_write32 (void *context, mach_phys_t address, uint32_t value)
+{
+  uint8_t *pointer = fake_translate (context, address);
+
+  if (pointer != NULL)
+    memcpy (pointer, &value, sizeof (value));
+}
+
+void
+fake_mmio_write64 (void *context, mach_phys_t address, uint64_t value)
+{
+  uint8_t *pointer = fake_translate (context, address);
+
+  if (pointer != NULL)
+    memcpy (pointer, &value, sizeof (value));
+}
+
+void
+fake_mmio_fence (void *context)
+{
+  (void) context;
+}
+
+const struct mach_mmio_ops fake_mmio_ops = {
+  fake_mmio_read8,
+  fake_mmio_read16,
+  fake_mmio_read32,
+  fake_mmio_read64,
+  fake_mmio_write8,
+  fake_mmio_write16,
+  fake_mmio_write32,
+  fake_mmio_write64,
+  fake_mmio_fence
+};
+
+struct mach_mmio
+fake_mmio_create (struct fake_mmio_region *region)
+{
+  struct mach_mmio mmio;
+
+  mmio.ops = &fake_mmio_ops;
+  mmio.context = region;
+  mmio.base = region != NULL ? region->base : 0;
+  mmio.length = region != NULL ? region->size : 0;
+  return mmio;
+}
+
+void
+fake_dma_init (struct fake_dma_arena *arena, void *memory, size_t size)
+{
+  arena->memory = memory;
+  arena->size = size;
+  arena->next = 0;
+}
+
+mach_error_t
+fake_dma_alloc (void *context, size_t size, size_t alignment,
+                mach_phys_t *address, void **virtual_address)
+{
+  struct fake_dma_arena *arena = context;
+  size_t offset;
+
+  if (arena == NULL || address == NULL || virtual_address == NULL
+      || size == 0)
+    return MACH_EINVAL;
+
+  if (alignment < 16u)
+    alignment = 16u;
+
+  offset = (arena->next + alignment - 1u) & ~(alignment - 1u);
+  if (offset + size > arena->size)
+    return MACH_ENOMEM;
+
+  arena->next = offset + size;
+  *address = offset;
+  *virtual_address = arena->memory + offset;
+  memset (arena->memory + offset, 0, size);
+  return MACH_OK;
+}
+
+void
+fake_dma_free (void *context, size_t size, mach_phys_t address,
+               void *virtual_address)
+{
+  (void) context;
+  (void) size;
+  (void) address;
+  (void) virtual_address;
+}
+
+mach_error_t
+fake_dma_map (void *context, mach_phys_t address, size_t size,
+              mach_phys_t *device_address)
+{
+  (void) context;
+  (void) size;
+  if (device_address != NULL)
+    *device_address = address;
+  return MACH_OK;
+}
+
+void
+fake_dma_unmap (void *context, mach_phys_t device_address, size_t size)
+{
+  (void) context;
+  (void) device_address;
+  (void) size;
+}
+
+void
+fake_dma_sync (void *context)
+{
+  (void) context;
+}
+
+const struct mach_dma_ops fake_dma_ops = {
+  fake_dma_alloc,
+  fake_dma_free,
+  fake_dma_map,
+  fake_dma_unmap,
+  fake_dma_sync
+};
+
+struct mach_dma
+fake_dma_create (struct fake_dma_arena *arena)
+{
+  struct mach_dma dma;
+
+  dma.ops = &fake_dma_ops;
+  dma.context = arena;
+  dma.mask = ~0ull;
+  return dma;
+}
diff --git a/modern/tests/fake_hw.h b/modern/tests/fake_hw.h
new file mode 100644
index 00000000..99b850e7
--- /dev/null
+++ b/modern/tests/fake_hw.h
@@ -0,0 +1,50 @@
+/* Shared fake MMIO and DMA backends for the hosted driver tests.  */
+
+#ifndef _MACH_TEST_FAKE_HW_H
+#define _MACH_TEST_FAKE_HW_H 1
+
+#include <mach/c17/driver.h>
+
+struct fake_mmio_region
+{
+  uint8_t *bytes;
+  size_t size;
+  mach_phys_t base;
+};
+
+uint8_t fake_mmio_read8 (void *context, mach_phys_t address);
+uint16_t fake_mmio_read16 (void *context, mach_phys_t address);
+uint32_t fake_mmio_read32 (void *context, mach_phys_t address);
+uint64_t fake_mmio_read64 (void *context, mach_phys_t address);
+void fake_mmio_write8 (void *context, mach_phys_t address, uint8_t value);
+void fake_mmio_write16 (void *context, mach_phys_t address, uint16_t value);
+void fake_mmio_write32 (void *context, mach_phys_t address, uint32_t value);
+void fake_mmio_write64 (void *context, mach_phys_t address, uint64_t value);
+void fake_mmio_fence (void *context);
+
+extern const struct mach_mmio_ops fake_mmio_ops;
+
+struct mach_mmio fake_mmio_create (struct fake_mmio_region *region);
+
+struct fake_dma_arena
+{
+  uint8_t *memory;
+  size_t size;
+  size_t next;
+};
+
+void fake_dma_init (struct fake_dma_arena *arena, void *memory, size_t size);
+mach_error_t fake_dma_alloc (void *context, size_t size, size_t alignment,
+                             mach_phys_t *address, void **virtual_address);
+void fake_dma_free (void *context, size_t size, mach_phys_t address,
+                    void *virtual_address);
+mach_error_t fake_dma_map (void *context, mach_phys_t address, size_t size,
+                           mach_phys_t *device_address);
+void fake_dma_unmap (void *context, mach_phys_t device_address, size_t size);
+void fake_dma_sync (void *context);
+
+extern const struct mach_dma_ops fake_dma_ops;
+
+struct mach_dma fake_dma_create (struct fake_dma_arena *arena);
+
+#endif /* _MACH_TEST_FAKE_HW_H */
diff --git a/modern/tests/test.h b/modern/tests/test.h
new file mode 100644
index 00000000..a9fdc881
--- /dev/null
+++ b/modern/tests/test.h
@@ -0,0 +1,51 @@
+/* Minimal hosted test harness for the C17 Mach platform.  */
+
+#ifndef _MACH_TEST_H
+#define _MACH_TEST_H 1
+
+#include <stdio.h>
+#include <string.h>
+
+static int mach_test_failures;
+
+#define CHECK(condition)                                                \
+  do                                                                    \
+    {                                                                   \
+      if (!(condition))                                                 \
+        {                                                               \
+          printf ("  FAIL %s:%d: %s\n", __FILE__, __LINE__, #condition); \
+          mach_test_failures++;                                         \
+        }                                                               \
+    }                                                                   \
+  while (0)
+
+#define CHECK_EQ(left, right)                                           \
+  do                                                                    \
+    {                                                                   \
+      unsigned long long test_left = (unsigned long long) (left);       \
+      unsigned long long test_right = (unsigned long long) (right);     \
+      if (test_left != test_right)                                      \
+        {                                                               \
+          printf ("  FAIL %s:%d: %s == %s (0x%llx != 0x%llx)\n",        \
+                  __FILE__, __LINE__, #left, #right, test_left,          \
+                  test_right);                                          \
+          mach_test_failures++;                                         \
+        }                                                               \
+    }                                                                   \
+  while (0)
+
+#define TEST_MAIN(name)                                                 \
+  int main (void)                                                       \
+  {                                                                     \
+    printf ("%s\n", name);                                              \
+    run_tests ();                                                       \
+    if (mach_test_failures != 0)                                        \
+      {                                                                 \
+        printf ("  %d failure(s)\n", mach_test_failures);               \
+        return 1;                                                       \
+      }                                                                 \
+    printf ("  ok\n");                                                  \
+    return 0;                                                           \
+  }
+
+#endif /* _MACH_TEST_H */
diff --git a/modern/tests/test_threads.c b/modern/tests/test_threads.c
new file mode 100644
index 00000000..73cafc41
--- /dev/null
+++ b/modern/tests/test_threads.c
@@ -0,0 +1,99 @@
+/* Tests for the C17 threads, mutexes, once and TSS.  */
+
+#include <threads.h>
+
+#include "test.h"
+
+static int worker_counter;
+static tss_t worker_key;
+static int tss_seen;
+static once_flag once = ONCE_FLAG_INIT;
+static int once_counter;
+static mtx_t recursive_mutex;
+
+static int
+worker (void *argument)
+{
+  worker_counter += (int) (long) argument;
+  tss_set (worker_key, (void *) 0x1234);
+  tss_seen = (int) (long) tss_get (worker_key);
+  return 42;
+}
+
+static void
+once_function (void)
+{
+  once_counter++;
+}
+
+static void
+test_threads (void)
+{
+  thrd_t first;
+  thrd_t second;
+  int result = 0;
+
+  CHECK_EQ (thrd_create (&first, worker, (void *) 1L), thrd_success);
+  CHECK_EQ (thrd_create (&second, worker, (void *) 2L), thrd_success);
+  CHECK_EQ (thrd_join (first, &result), thrd_success);
+  CHECK_EQ (result, 42);
+  CHECK_EQ (thrd_join (second, NULL), thrd_success);
+  CHECK_EQ (worker_counter, 3);
+  CHECK_EQ (tss_seen, 0x1234);
+}
+
+static void
+test_mutex (void)
+{
+  mtx_t mutex;
+
+  CHECK_EQ (mtx_init (&mutex, mtx_plain), thrd_success);
+  CHECK_EQ (mtx_lock (&mutex), thrd_success);
+  CHECK_EQ (mtx_trylock (&mutex), thrd_busy);
+  CHECK_EQ (mtx_unlock (&mutex), thrd_success);
+  CHECK_EQ (mtx_trylock (&mutex), thrd_success);
+  CHECK_EQ (mtx_unlock (&mutex), thrd_success);
+
+  CHECK_EQ (mtx_init (&recursive_mutex, mtx_recursive), thrd_success);
+  CHECK_EQ (mtx_lock (&recursive_mutex), thrd_success);
+  CHECK_EQ (mtx_lock (&recursive_mutex), thrd_success);
+  CHECK_EQ (mtx_unlock (&recursive_mutex), thrd_success);
+  CHECK_EQ (mtx_unlock (&recursive_mutex), thrd_success);
+  CHECK_EQ (mtx_trylock (&recursive_mutex), thrd_success);
+  CHECK_EQ (mtx_unlock (&recursive_mutex), thrd_success);
+}
+
+static void
+test_once_and_tss (void)
+{
+  tss_t second_key;
+
+  CHECK_EQ (tss_create (&second_key, NULL), thrd_success);
+  CHECK_EQ (tss_set (second_key, (void *) 0x55), thrd_success);
+  CHECK_EQ ((long) tss_get (second_key), 0x55);
+  tss_delete (second_key);
+
+  call_once (&once, once_function);
+  call_once (&once, once_function);
+  CHECK_EQ (once_counter, 1);
+
+  {
+    cnd_t condition;
+
+    CHECK_EQ (cnd_init (&condition), thrd_success);
+    CHECK_EQ (cnd_signal (&condition), thrd_success);
+    CHECK_EQ (cnd_broadcast (&condition), thrd_success);
+    cnd_destroy (&condition);
+  }
+}
+
+static void
+run_tests (void)
+{
+  CHECK_EQ (tss_create (&worker_key, NULL), thrd_success);
+  test_threads ();
+  test_mutex ();
+  test_once_and_tss ();
+}
+
+TEST_MAIN ("threads")
-- 
2.56.0


Reply via email to