@@ -14,8 +14,11 @@ static ZTEST_DMEM int case_type;
1414
1515static K_THREAD_STACK_DEFINE (tstack , STACK_SIZE );
1616static K_THREAD_STACK_DEFINE (test_stack , STACK_SIZE ) ;
17+ static K_THREAD_STACK_DEFINE (reuse_stack1 , STACK_SIZE ) ;
18+ static K_THREAD_STACK_DEFINE (reuse_stack2 , STACK_SIZE ) ;
1719static struct k_thread tdata ;
1820static struct k_thread test_tdata ;
21+ static struct k_thread reuse_tdata ;
1922
2023/* identifiers for each negative test scenario */
2124enum {
@@ -32,14 +35,21 @@ enum {
3235 THREAD_PRIORITY_GET_NULL ,
3336 THREAD_WAKEUP_NULL ,
3437 THREAD_CREATE_SUPERVISOR ,
35- THREAD_CREATE_ESSENTIAL
38+ THREAD_CREATE_ESSENTIAL ,
39+ THREAD_REUSE_ACTIVE_THREAD_ID
3640} neg_case ;
3741
3842static void test_thread (void * p1 , void * p2 , void * p3 )
3943{
4044 /* intentionally empty target thread */
4145}
4246
47+ static void long_running_thread (void * p1 , void * p2 , void * p3 )
48+ {
49+ /* Sleep for a long time to keep thread active */
50+ k_sleep (K_FOREVER );
51+ }
52+
4353static void tThread_entry_negative (void * p1 , void * p2 , void * p3 )
4454{
4555 ARG_UNUSED (p2 );
@@ -149,6 +159,16 @@ static void tThread_entry_negative(void *p1, void *p2, void *p3)
149159 K_PRIO_PREEMPT (THREAD_TEST_PRIORITY ),
150160 K_USER | K_ESSENTIAL , K_NO_WAIT );
151161 break ;
162+ case THREAD_REUSE_ACTIVE_THREAD_ID :
163+ ztest_set_fault_valid (true);
164+ /* Create first thread that will run for a while */
165+ k_thread_create (& reuse_tdata , reuse_stack1 , STACK_SIZE , long_running_thread , NULL ,
166+ NULL , NULL , K_PRIO_PREEMPT (THREAD_TEST_PRIORITY + 1 ), perm ,
167+ K_NO_WAIT );
168+ /* Try to reuse the same thread structure while it's still active */
169+ k_thread_create (& reuse_tdata , reuse_stack2 , STACK_SIZE , test_thread , NULL , NULL ,
170+ NULL , K_PRIO_PREEMPT (THREAD_TEST_PRIORITY ), perm , K_NO_WAIT );
171+ break ;
152172 default :
153173 TC_PRINT ("should not be here!\n" );
154174 break ;
@@ -382,6 +402,38 @@ ZTEST_USER(thread_error_case, test_thread_create_stack_size_overflow)
382402 create_negative_test_thread (THREAD_CREATE_STACK_SIZE_OVERFLOW );
383403}
384404
405+ /**
406+ * @brief Verify that k_thread_create() asserts if a thread pointer is
407+ * reused while the thread pointer is in use.
408+ *
409+ * @ingroup kernel_thread_tests
410+ *
411+ * @details
412+ * A thread structure must not be reused for a new thread while the
413+ * thread it currently backs is still active, so this must be detected
414+ * instead of silently corrupting the running thread's state.
415+ *
416+ * This test runs in kernel mode, a worker thread arms the ztest
417+ * fatal-error hook and then makes the offending call. The call must
418+ * not return -- reaching the code after it fails the test -- so a pass
419+ * means the error really was caught.
420+ *
421+ * Test steps:
422+ * - Spawn a worker thread and arm the ztest fatal-error hook.
423+ * - Create a first thread that keeps running, then try to reuse its thread
424+ * structure to create a second thread from the same worker thread.
425+ * - Join the worker thread.
426+ *
427+ * Expected result:
428+ * - The call raises the expected fatal error and never returns.
429+ *
430+ * @see k_thread_create()
431+ */
432+ ZTEST (thread_error_case , test_thread_reuse_active_thread_id )
433+ {
434+ create_negative_test_thread (THREAD_REUSE_ACTIVE_THREAD_ID );
435+ }
436+
385437/**
386438 * @brief Verify that k_thread_suspend() rejects a NULL thread pointer.
387439 *
0 commit comments