feat: add sel_alloc_thread_id ownership check in eval_select and gc_sweep (6-10)
This commit is contained in:
parent
742d79ee55
commit
b722e5cb3d
4 changed files with 59 additions and 0 deletions
|
|
@ -2226,6 +2226,32 @@ test_gc_clear_marks_exported(void)
|
|||
sel_optimize_test_reset();
|
||||
}
|
||||
|
||||
/* ── Task 8: sel_alloc_thread_id ownership check ─────────────────────────*/
|
||||
|
||||
static void
|
||||
test_sel_register_alloc_thread(void)
|
||||
{
|
||||
sel_optimize_test_reset(); /* resets sel_alloc_thread_id to 0 */
|
||||
sel_optimize_set(1);
|
||||
sel_node_table_init();
|
||||
|
||||
/* Should not crash when unregistered (id=0 means skip check) */
|
||||
xce_select_node_t* n = makeSelectNode(SEL_TRUE, 0, 0);
|
||||
TEST_ASSERT_NOT_NULL(n);
|
||||
|
||||
/* Register current thread */
|
||||
sel_register_alloc_thread();
|
||||
|
||||
/* makeSelectNode from same thread must still work */
|
||||
xce_select_node_t* n2 = makeSelectNode(SEL_FALSE, 0, 0);
|
||||
TEST_ASSERT_NOT_NULL(n2);
|
||||
|
||||
gc_clear_marks();
|
||||
gc_sweep_select_nodes(NULL, 0);
|
||||
sel_node_table_fini();
|
||||
sel_optimize_test_reset();
|
||||
}
|
||||
|
||||
/* ── Top-level runner ─────────────────────────────────────────────────────*/
|
||||
|
||||
void
|
||||
|
|
@ -2337,5 +2363,8 @@ test_select(void)
|
|||
/* ── Phase 6 prep: exported GC mark primitives ───────────────────── */
|
||||
RUN_TEST(test_gc_clear_marks_exported);
|
||||
|
||||
/* ── Task 8: sel_alloc_thread_id ownership check ─────────────────── */
|
||||
RUN_TEST(test_sel_register_alloc_thread);
|
||||
|
||||
xstring_table_fini();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#define UNIT_TEST 1 /* expose sel_optimize_test_reset in resreq.h */
|
||||
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -23,6 +24,7 @@
|
|||
/* ── optimize level ───────────────────────────────────────────────────── */
|
||||
|
||||
static _Atomic int g_sel_optimize_level = -1; /* -1 = unset */
|
||||
static pthread_t sel_alloc_thread_id; /* 0 = unregistered — skip checks */
|
||||
|
||||
void sel_optimize_set(int level)
|
||||
{
|
||||
|
|
@ -184,6 +186,12 @@ void sel_optimize_test_reset(void)
|
|||
{
|
||||
sel_node_table_fini();
|
||||
atomic_store_explicit(&g_sel_optimize_level, -1, memory_order_seq_cst);
|
||||
sel_alloc_thread_id = 0;
|
||||
}
|
||||
|
||||
void sel_register_alloc_thread(void)
|
||||
{
|
||||
sel_alloc_thread_id = pthread_self();
|
||||
}
|
||||
|
||||
/* ── node construction ───────────────────────────────────────────────── */
|
||||
|
|
@ -643,6 +651,10 @@ int eval_select(const xce_select_node_t* node, select_eval_ctx_t* ctx)
|
|||
if (sel_get_optimize_level() <= 0) {
|
||||
ERROR("eval_select called with optimize_level <= 0"); abort();
|
||||
}
|
||||
if (sel_alloc_thread_id != 0 && !pthread_equal(pthread_self(), sel_alloc_thread_id)) {
|
||||
ERROR("eval_select called from non-allocator thread");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* bitmap cache hit */
|
||||
if (node->node_id < ctx->bool_bits_cap) {
|
||||
|
|
@ -863,6 +875,10 @@ void gc_sweep_select_nodes(const xce_sched_job_t** live_jobs, size_t njobs)
|
|||
if (sel_node_table.table == NULL) {
|
||||
return;
|
||||
}
|
||||
if (sel_alloc_thread_id != 0 && !pthread_equal(pthread_self(), sel_alloc_thread_id)) {
|
||||
ERROR("gc_sweep_select_nodes called from non-allocator thread");
|
||||
return;
|
||||
}
|
||||
|
||||
int caps = sel_node_table.nodes.caps;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue