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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,13 @@ jobs:
sudo apt-get install -y clang
fi

# Force POSIX pthreads for TSan (C11 threads.h is uninstrumented)
- name: Configure with TSan
run: >
meson setup builddir-tsan
-Db_sanitize=thread
-Db_lundef=false
-Dthreads=posix
-Dtests=true
--buildtype=debug
env:
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ci-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,16 @@ jobs:
ASAN_OPTIONS: abort_on_error=1:halt_on_error=1
UBSAN_OPTIONS: abort_on_error=1:halt_on_error=1:print_stacktrace=1

# TSan: force POSIX pthreads via -Dthreads=posix.
# TSan only intercepts pthread calls; C11 <threads.h> functions
# (thrd_create, mtx_lock) are uninstrumented and cause false SEGV.
- name: Sanitizers / TSan
if: matrix.os == 'ubuntu-latest'
run: |
meson setup builddir-tsan \
-Db_sanitize=thread \
-Db_lundef=false \
-Dthreads=posix \
-Dtests=true \
--buildtype=debug
meson compile -C builddir-tsan
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ All notable changes to wirelog are documented in this file.
- **wl_easy Facade** (#445): Simplified high-level API (`wl_easy.h`) for common session workflows
- **String Operations** (#444): String-typed column functions (`strlen`, `cat`, `substr`, `contains`, `to_upper`, `to_lower`, `trim`, `str_replace`, `to_string`, `to_number`)
- **Path A Example** (#462): Standalone pcap adapter skeleton with CI compile-check against installed headers
- **C11 Threading Backend** (#494): Add C11 `<threads.h>` backend with auto-detection; POSIX/MSVC fallback preserved. `call_once` pattern for adapter registry initialization
- **Binary Size Gate** (#460): CI regression gate for `.text` section growth (5KB budget)
- **I/O Adapters User Guide** (#463): `docs/io-adapters.md` with Path A/B workflows, ABI policy, ownership rules, and thread-safety notes
- **Retraction Support** (#443): Fact retraction with recursive re-evaluation
Expand Down
9 changes: 3 additions & 6 deletions bench/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,9 @@ bench_workqueue_src = files(
subdir_wirelog / 'workqueue.c',
)

# Select threading backend based on platform
if host_machine.system() == 'windows'
bench_thread_src = files(subdir_wirelog / 'thread_msvc.c')
else
bench_thread_src = files(subdir_wirelog / 'thread_posix.c')
endif
# Reuse the same threading backend selected by wirelog/meson.build
# (C11 threads.h > POSIX pthreads > Windows MSVC).
bench_thread_src = wirelog_thread_src

# Skip bench_flowlog on Windows (uses POSIX getopt)
if host_machine.system() != 'windows'
Expand Down
18 changes: 8 additions & 10 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,14 @@ message(' Plugin loader (dlopen): ' + io_plugin_dlopen_option)
#Dependencies
#== == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==

#Optional : pthreads for threading
#pthreads for threading
threads_dep = []
if threads_option == 'enabled'
_td = dependency('threads', required: false)
if not _td.found()
_td = cc.find_library('pthread', required: false)
endif
if _td.found()
threads_dep = [_td]
endif
_td = dependency('threads', required: false)
if not _td.found()
_td = cc.find_library('pthread', required: false)
endif
if _td.found()
threads_dep = [_td]
endif

#Optional : zlib for IPC compression(future)
Expand Down Expand Up @@ -180,7 +178,7 @@ config_h.set_quoted('WIRELOG_VERSION', project_version)
config_h.set_quoted('WIRELOG_PLATFORM', platform)
config_h.set('WIRELOG_EMBEDDED', is_embedded)
config_h.set('WIRELOG_IPC', ipc_option == 'enabled')
config_h.set('WIRELOG_THREADS', threads_option == 'enabled')
config_h.set('WIRELOG_THREADS', true)

#Generate config header
config_h_file = configure_file(
Expand Down
6 changes: 3 additions & 3 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ option(
option(
'threads',
type: 'combo',
choices: ['disabled', 'enabled'],
value: 'enabled',
description: 'Enable pthreads support for multi-threaded execution'
choices: ['native', 'posix'],
value: 'native',
description: 'Threading backend: native (auto-detect C11/POSIX) or posix (force pthreads, required for TSan)'
)

option(
Expand Down
10 changes: 5 additions & 5 deletions tests/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ io_src = files(
)

# Select threading backend based on platform
if host_machine.system() == 'windows'
thread_src = files('../wirelog/thread_msvc.c',)
else
thread_src = files('../wirelog/thread_posix.c',)
endif
# Reuse the same threading backend selected by wirelog/meson.build
# (C11 threads.h > POSIX pthreads > Windows MSVC).
# wirelog_thread_src is defined in wirelog/meson.build and propagated
# to subdir builds via the parent scope.
thread_src = wirelog_thread_src

# ============================================================================
# Test Executables
Expand Down
28 changes: 14 additions & 14 deletions tests/test_io_adapter_concurrent.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
static int passed = 0, failed = 0;

/* ======================================================================== */
/* Concurrent Tests (POSIX only; skipped on Windows) */
/* Concurrent Tests (POSIX/C11; skipped on Windows) */
/* ======================================================================== */

#ifndef _WIN32

#include <pthread.h>
#include "wirelog/thread.h"

#define NTHREADS 8
#define FIND_ITERS 2000
Expand All @@ -60,11 +60,11 @@ test_concurrent_find(void)
{
TEST("concurrent find (csv built-in, 8 threads x 2000 iters)");

pthread_t threads[NTHREADS];
thread_t threads[NTHREADS];
for (int i = 0; i < NTHREADS; i++)
pthread_create(&threads[i], NULL, find_worker, NULL);
thread_create(&threads[i], find_worker, NULL);
for (int i = 0; i < NTHREADS; i++)
pthread_join(threads[i], NULL);
thread_join(&threads[i]);

/* After concurrent reads, csv must still be findable */
const wl_io_adapter_t *a = wl_io_find_adapter("csv");
Expand Down Expand Up @@ -109,7 +109,7 @@ test_concurrent_register_unregister(void)
{
TEST("concurrent register/unregister (8 threads x 2000 iters each)");

pthread_t threads[NTHREADS];
thread_t threads[NTHREADS];
reg_arg_t args[NTHREADS];

for (int i = 0; i < NTHREADS; i++) {
Expand All @@ -118,10 +118,10 @@ test_concurrent_register_unregister(void)
args[i].adapter.scheme = args[i].scheme;
args[i].adapter.abi_version = WL_IO_ABI_VERSION;
args[i].result = 0;
pthread_create(&threads[i], NULL, reg_unreg_worker, &args[i]);
thread_create(&threads[i], reg_unreg_worker, &args[i]);
}
for (int i = 0; i < NTHREADS; i++)
pthread_join(threads[i], NULL);
thread_join(&threads[i]);

int any_failed = 0;
for (int i = 0; i < NTHREADS; i++) {
Expand Down Expand Up @@ -165,21 +165,21 @@ test_mixed_readers_writers(void)
{
TEST("mixed readers + writers (4 find + 4 reg/unreg threads)");

pthread_t readers[4];
pthread_t writers[4];
thread_t readers[4];
thread_t writers[4];
reg_arg_t wargs[4];

for (int i = 0; i < 4; i++) {
snprintf(wargs[i].scheme, sizeof(wargs[i].scheme), "mixed_%d", i);
memset(&wargs[i].adapter, 0, sizeof(wargs[i].adapter));
wargs[i].adapter.scheme = wargs[i].scheme;
wargs[i].adapter.abi_version = WL_IO_ABI_VERSION;
pthread_create(&readers[i], NULL, mixed_find_worker, NULL);
pthread_create(&writers[i], NULL, mixed_reg_worker, &wargs[i]);
thread_create(&readers[i], mixed_find_worker, NULL);
thread_create(&writers[i], mixed_reg_worker, &wargs[i]);
}
for (int i = 0; i < 4; i++) {
pthread_join(readers[i], NULL);
pthread_join(writers[i], NULL);
thread_join(&readers[i]);
thread_join(&writers[i]);
}

/* Registry must still be consistent: csv findable, no dangling entries */
Expand Down
Loading
Loading