diff --git a/build-all.log b/build-all.log new file mode 100644 index 00000000..dbdac945 --- /dev/null +++ b/build-all.log @@ -0,0 +1,442 @@ +[1/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.o +[2/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_context_save.c.o +[3/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_timer_interrupt.c.o +[4/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.o +[5/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.o +[6/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.o +[7/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.o +[8/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_interrupt_control.c.o +[9/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.o +[10/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.o +[11/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.o +[12/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.o +[13/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_context_restore.c.o +[14/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_system_return.c.o +[15/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_stack_build.c.o +[16/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.o +[17/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_schedule.c.o +[18/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.o +[19/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.o +[20/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.o +[21/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_release.c.o +[22/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.o +[23/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.o +[24/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_initialize_low_level.c.o +[25/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.o +[26/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.o +[27/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.o +[28/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.o +[29/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.o +[30/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.o +[31/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.o +[32/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_release.c.o +[33/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.o +[34/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.o +[35/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.o +[36/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.o +[37/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.o +[38/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.o +[39/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.o +[40/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.o +[41/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_misra.c.o +[42/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.o +[43/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.o +[44/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.o +[45/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.o +[46/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.o +[47/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.o +[48/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.o +[49/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.o +[50/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.o +[51/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.o +[52/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.o +[53/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.o +[54/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.o +[55/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.o +[56/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.o +[57/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_create.c.o +[58/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.o +[59/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.o +[60/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.o +[61/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.o +[62/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.o +[63/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.o +[64/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.o +[65/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.o +[66/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_send.c.o +[67/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.o +[68/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.o +[69/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.o +[70/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.o +[71/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.o +[72/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.o +[73/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.o +[74/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.o +[75/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.o +[76/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.o +[77/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.o +[78/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.o +[79/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.o +[80/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_create.c.o +[81/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.o +[82/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.o +[83/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.o +[84/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.o +[85/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.o +[86/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.o +[87/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.o +[88/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.o +[89/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.o +[90/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.o +[91/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.o +[92/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.o +[93/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.o +[94/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.o +[95/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.o +[96/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.o +[97/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.o +[98/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.o +[99/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_time_get.c.o +[100/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.o +[101/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.o +[102/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.o +[103/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.o +[104/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.o +[105/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.o +[106/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_create.c.o +[107/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.o +[108/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_change.c.o +[109/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.o +[110/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.o +[111/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.o +[112/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.o +[113/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.o +[114/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_time_set.c.o +[115/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.o +[116/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.o +[117/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.o +[118/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.o +[119/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.o +[120/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.o +[121/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.o +[122/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.o +[123/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.o +[124/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.o +[125/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.o +[126/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.o +[127/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.o +[128/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.o +[129/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.o +[130/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.o +[131/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.o +[132/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.o +[133/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.o +[134/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.o +[135/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.o +[136/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.o +[137/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.o +[138/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.o +[139/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_release.c.o +[140/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.o +[141/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.o +[142/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.o +[143/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.o +[144/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.o +[145/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_release.c.o +[146/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.o +[147/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.o +[148/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.o +[149/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.o +[150/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.o +[151/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.o +[152/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.o +[153/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.o +[154/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.o +[155/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.o +[156/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.o +[157/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.o +[158/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_create.c.o +[159/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.o +[160/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.o +[161/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.o +[162/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.o +[163/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.o +[164/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.o +[165/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_send.c.o +[166/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.o +[167/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.o +[168/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.o +[169/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.o +[170/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.o +[171/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.o +[172/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.o +[173/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.o +[174/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.o +[175/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.o +[176/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.o +[177/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.o +[178/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.o +[179/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.o +[180/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_create.c.o +[181/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.o +[182/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.o +[183/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.o +[184/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.o +[185/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.o +[186/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.o +[187/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.o +[188/441] Building C object regression/CMakeFiles/test_weak_defaults.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/shared/regression/testcontrol_weak_defaults.c.o +[189/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_change.c.o +[190/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.o +[191/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.o +[192/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.o +[193/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_shell_entry.c.o +[194/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_create.c.o +[195/441] Building C object samples/CMakeFiles/sample_threadx.dir/fake.c.o +[196/441] Building C object regression/CMakeFiles/threadx_initialize_kernel_setup_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_initialize_kernel_setup_test.c.o +[197/441] Building C object samples/CMakeFiles/sample_threadx.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/ports/linux/gnu/example_build/sample_threadx.c.o +[198/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_delete.c.o +[199/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.o +[200/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_delete.c.o +[201/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/thread_transition/threadx_thread_transition_configuration_test.c.o +[202/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_terminate.c.o +[203/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_terminate.c.o +[204/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_reset.c.o +[205/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_initialize.c.o +[206/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_reset.c.o +[207/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_shell_entry.c.o +[208/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_delete.c.o +[209/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_terminate.c.o +[210/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_reset.c.o +[211/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/thread_transition/threadx_thread_transition_configuration_test.c.o +[212/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_reset.c.o +[213/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_delete.c.o +[214/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_shell_entry.c.o +[215/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_terminate.c.o +[216/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_terminate.c.o +[217/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_initialize.c.o +[218/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_delete.c.o +[219/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_delete.c.o +[220/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_reset.c.o +[221/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_terminate.c.o +[222/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_reset.c.o +[223/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/thread_transition/threadx_thread_transition_configuration_test.c.o +[224/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_shell_entry.c.o +[225/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_initialize.c.o +[226/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_delete.c.o +[227/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_terminate.c.o +[228/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_reset.c.o +[229/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/thread_transition/threadx_thread_transition_configuration_test.c.o +[230/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_terminate.c.o +[231/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_reset.c.o +[232/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_initialize.c.o +[233/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_delete.c.o +[234/441] Linking C executable thread_transition/tx_tt_ni +[235/441] Linking C executable thread_transition/tx_tt_ni_no_error_checking +[236/441] Linking C executable thread_transition/tx_tt_ni_no_notify +[237/441] Linking C executable thread_transition/tx_tt_no_error_checking +[238/441] Linking C shared library threadx/libthreadx.so +[239/441] Generating tx_initialize_low_level.c for test +[240/441] Building C object regression/CMakeFiles/threadx_block_memory_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_thread_terminate_test.c.o +[241/441] Building C object regression/CMakeFiles/threadx_block_memory_error_detection_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_error_detection_test.c.o +[242/441] Building C object regression/CMakeFiles/threadx_byte_memory_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_suspension_test.c.o +[243/441] Building C object regression/CMakeFiles/threadx_block_memory_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_information_test.c.o +[244/441] Building C object regression/CMakeFiles/threadx_block_memory_prioritize_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_prioritize_test.c.o +[245/441] Building C object regression/CMakeFiles/threadx_block_memory_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_suspension_timeout_test.c.o +[246/441] Building C object regression/CMakeFiles/threadx_byte_memory_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_information_test.c.o +[247/441] Building C object regression/CMakeFiles/threadx_block_memory_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_basic_test.c.o +[248/441] Building C object regression/CMakeFiles/threadx_block_memory_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_suspension_test.c.o +[249/441] Building C object regression/CMakeFiles/threadx_byte_memory_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_suspension_timeout_test.c.o +[250/441] Building C object regression/CMakeFiles/threadx_byte_memory_prioritize_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_prioritize_test.c.o +[251/441] Building C object regression/CMakeFiles/threadx_byte_memory_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_basic_test.c.o +[252/441] Building C object regression/CMakeFiles/test_utility.dir/tx_initialize_low_level.c.o +[253/441] Building C object regression/CMakeFiles/threadx_byte_memory_thread_contention_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_thread_contention_test.c.o +[254/441] Building C object regression/CMakeFiles/test_utility.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/testcontrol.c.o +[255/441] Building C object regression/CMakeFiles/threadx_byte_memory_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_thread_terminate_test.c.o +[256/441] Building C object regression/CMakeFiles/threadx_interrupt_control_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_interrupt_control_test.c.o +[257/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_different_bits_consume_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_different_bits_consume_test.c.o +[258/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_test.c.o +[259/441] Building C object regression/CMakeFiles/threadx_event_flag_isr_wait_abort_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_isr_wait_abort_test.c.o +[260/441] Building C object regression/CMakeFiles/threadx_event_flag_isr_set_clear_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_isr_set_clear_test.c.o +[261/441] Building C object regression/CMakeFiles/threadx_event_flag_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_basic_test.c.o +[262/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_consume_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_consume_test.c.o +[263/441] Building C object regression/CMakeFiles/threadx_event_flag_single_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_single_thread_terminate_test.c.o +[264/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_different_bits_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_different_bits_test.c.o +[265/441] Building C object regression/CMakeFiles/threadx_event_flag_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_thread_terminate_test.c.o +[266/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_timeout_test.c.o +[267/441] Building C object regression/CMakeFiles/threadx_event_flag_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_information_test.c.o +[268/441] Building C object regression/CMakeFiles/threadx_mutex_delete_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_delete_test.c.o +[269/441] Building C object regression/CMakeFiles/threadx_mutex_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_basic_test.c.o +[270/441] Linking C executable samples/sample_threadx +[271/441] Linking C executable regression/threadx_initialize_kernel_setup_test +[272/441] Linking C executable regression/threadx_block_memory_suspension_test +[273/441] Linking C executable regression/threadx_block_memory_basic_test +[274/441] Linking C executable regression/threadx_block_memory_error_detection_test +[275/441] Linking C executable regression/threadx_block_memory_information_test +[276/441] Linking C executable regression/threadx_byte_memory_suspension_timeout_test +[277/441] Linking C executable regression/threadx_byte_memory_prioritize_test +[278/441] Linking C executable regression/threadx_block_memory_thread_terminate_test +[279/441] Linking C executable regression/threadx_byte_memory_information_test +[280/441] Linking C executable regression/threadx_byte_memory_suspension_test +[281/441] Linking C executable regression/threadx_event_flag_basic_test +[282/441] Linking C executable regression/threadx_byte_memory_basic_test +[283/441] Linking C executable regression/threadx_byte_memory_thread_contention_test +[284/441] Linking C executable regression/threadx_block_memory_suspension_timeout_test +[285/441] Linking C executable regression/threadx_block_memory_prioritize_test +[286/441] Linking C executable regression/threadx_event_flag_information_test +[287/441] Linking C executable regression/threadx_byte_memory_thread_terminate_test +[288/441] Building C object regression/CMakeFiles/threadx_mutex_preemption_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_preemption_test.c.o +[289/441] Building C object regression/CMakeFiles/threadx_mutex_no_preemption_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_no_preemption_test.c.o +[290/441] Linking C executable regression/threadx_event_flag_isr_set_clear_test +[291/441] Linking C executable regression/threadx_event_flag_isr_wait_abort_test +[292/441] Building C object regression/CMakeFiles/threadx_mutex_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_information_test.c.o +[293/441] Building C object regression/CMakeFiles/threadx_mutex_nested_priority_inheritance_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_nested_priority_inheritance_test.c.o +[294/441] Building C object regression/CMakeFiles/threadx_mutex_priority_inheritance_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_priority_inheritance_test.c.o +[295/441] Building C object regression/CMakeFiles/threadx_mutex_proritize_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_proritize_test.c.o +[296/441] Building C object regression/CMakeFiles/threadx_mutex_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_thread_terminate_test.c.o +[297/441] Building C object regression/CMakeFiles/threadx_mutex_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_suspension_timeout_test.c.o +[298/441] Linking C executable regression/threadx_event_flag_suspension_consume_test +[299/441] Linking C executable regression/threadx_event_flag_single_thread_terminate_test +[300/441] Linking C executable regression/threadx_event_flag_suspension_different_bits_consume_test +[301/441] Linking C executable regression/threadx_event_flag_suspension_timeout_test +[302/441] Linking C executable regression/threadx_interrupt_control_test +[303/441] Linking C executable regression/threadx_event_flag_suspension_test +[304/441] Linking C executable regression/threadx_event_flag_thread_terminate_test +[305/441] Linking C executable regression/threadx_mutex_basic_test +[306/441] Linking C executable regression/threadx_event_flag_suspension_different_bits_test +[307/441] Linking C executable regression/threadx_mutex_delete_test +[308/441] Building C object regression/CMakeFiles/threadx_queue_basic_four_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_four_word_test.c.o +[309/441] Building C object regression/CMakeFiles/threadx_queue_basic_eight_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_eight_word_test.c.o +[310/441] Building C object regression/CMakeFiles/threadx_queue_basic_one_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_one_word_test.c.o +[311/441] Linking C executable regression/threadx_mutex_no_preemption_test +[312/441] Linking C executable regression/threadx_mutex_preemption_test +[313/441] Building C object regression/CMakeFiles/threadx_queue_flush_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_flush_test.c.o +[314/441] Building C object regression/CMakeFiles/threadx_queue_empty_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_empty_suspension_test.c.o +[315/441] Building C object regression/CMakeFiles/threadx_queue_flush_no_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_flush_no_suspension_test.c.o +[316/441] Building C object regression/CMakeFiles/threadx_queue_basic_max_message_size_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_max_message_size_test.c.o +[317/441] Building C object regression/CMakeFiles/threadx_queue_basic_two_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_two_word_test.c.o +[318/441] Building C object regression/CMakeFiles/threadx_queue_basic_sixteen_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_sixteen_word_test.c.o +[319/441] Linking C executable regression/threadx_mutex_nested_priority_inheritance_test +[320/441] Linking C executable regression/threadx_mutex_priority_inheritance_test +[321/441] Building C object regression/CMakeFiles/threadx_queue_front_send_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_front_send_test.c.o +[322/441] Building C object regression/CMakeFiles/threadx_queue_full_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_full_suspension_test.c.o +[323/441] Building C object regression/CMakeFiles/threadx_queue_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_information_test.c.o +[324/441] Linking C executable regression/threadx_mutex_information_test +[325/441] Linking C executable regression/threadx_mutex_suspension_timeout_test +[326/441] Building C object regression/CMakeFiles/threadx_queue_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_suspension_timeout_test.c.o +[327/441] Building C object regression/CMakeFiles/threadx_queue_prioritize.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_prioritize.c.o +[328/441] Linking C executable regression/threadx_mutex_thread_terminate_test +[329/441] Linking C executable regression/threadx_mutex_proritize_test +[330/441] Building C object regression/CMakeFiles/threadx_queue_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_thread_terminate_test.c.o +[331/441] Building C object regression/CMakeFiles/threadx_semaphore_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_basic_test.c.o +[332/441] Building C object regression/CMakeFiles/threadx_semaphore_ceiling_put_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_ceiling_put_test.c.o +[333/441] Building C object regression/CMakeFiles/threadx_semaphore_delete_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_delete_test.c.o +[334/441] Linking C executable regression/threadx_queue_basic_eight_word_test +[335/441] Linking C executable regression/threadx_queue_basic_four_word_test +[336/441] Linking C executable regression/threadx_queue_basic_one_word_test +[337/441] Linking C executable regression/threadx_queue_flush_no_suspension_test +[338/441] Linking C executable regression/threadx_queue_empty_suspension_test +[339/441] Linking C executable regression/threadx_queue_basic_max_message_size_test +[340/441] Linking C executable regression/threadx_queue_basic_two_word_test +[341/441] Linking C executable regression/threadx_queue_flush_test +[342/441] Linking C executable regression/threadx_queue_basic_sixteen_word_test +[343/441] Building C object regression/CMakeFiles/threadx_semaphore_non_preemption_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_non_preemption_test.c.o +[344/441] Building C object regression/CMakeFiles/threadx_semaphore_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_information_test.c.o +[345/441] Building C object regression/CMakeFiles/threadx_semaphore_preemption_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_preemption_test.c.o +[346/441] Linking C executable regression/threadx_queue_full_suspension_test +[347/441] Linking C executable regression/threadx_queue_front_send_test +[348/441] Building C object regression/CMakeFiles/threadx_semaphore_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_timeout_test.c.o +[349/441] Building C object regression/CMakeFiles/threadx_semaphore_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_thread_terminate_test.c.o +[350/441] Building C object regression/CMakeFiles/threadx_thread_basic_time_slice_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_basic_time_slice_test.c.o +[351/441] Building C object regression/CMakeFiles/threadx_semaphore_prioritize.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_prioritize.c.o +[352/441] Building C object regression/CMakeFiles/threadx_thread_basic_execution_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_basic_execution_test.c.o +[353/441] Linking C executable regression/threadx_queue_suspension_timeout_test +[354/441] Linking C executable regression/threadx_queue_information_test +[355/441] Building C object regression/CMakeFiles/threadx_thread_completed_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_completed_test.c.o +[356/441] Building C object regression/CMakeFiles/threadx_thread_create_preemption_threshold_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_create_preemption_threshold_test.c.o +[357/441] Building C object regression/CMakeFiles/threadx_thread_delayed_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_delayed_suspension_test.c.o +[358/441] Linking C executable regression/threadx_queue_prioritize +[359/441] Linking C executable regression/threadx_semaphore_basic_test +[360/441] Linking C executable regression/threadx_queue_thread_terminate_test +[361/441] Linking C executable regression/threadx_semaphore_ceiling_put_test +[362/441] Building C object regression/CMakeFiles/threadx_thread_misaligned_stack_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_misaligned_stack_test.c.o +[363/441] Linking C executable regression/threadx_semaphore_delete_test +[364/441] Building C object regression/CMakeFiles/threadx_thread_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_information_test.c.o +[365/441] Building C object regression/CMakeFiles/threadx_thread_multiple_sleep_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multiple_sleep_test.c.o +[366/441] Building C object regression/CMakeFiles/threadx_thread_multiple_non_current_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multiple_non_current_test.c.o +[367/441] Building C object regression/CMakeFiles/threadx_thread_multiple_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multiple_suspension_test.c.o +[368/441] Building C object regression/CMakeFiles/threadx_thread_multiple_time_slice_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multiple_time_slice_test.c.o +[369/441] Building C object regression/CMakeFiles/threadx_thread_multi_level_preemption_threshold_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c.o +[370/441] Linking C executable regression/threadx_semaphore_non_preemption_test +[371/441] Linking C executable regression/threadx_semaphore_information_test +[372/441] Linking C executable regression/threadx_semaphore_timeout_test +[373/441] Linking C executable regression/threadx_semaphore_preemption_test +[374/441] Linking C executable regression/threadx_semaphore_thread_terminate_test +[375/441] Linking C executable regression/threadx_semaphore_prioritize +[376/441] Linking C executable regression/threadx_thread_basic_time_slice_test +[377/441] Building C object regression/CMakeFiles/threadx_thread_preemptable_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_preemptable_suspension_test.c.o +[378/441] Linking C executable regression/threadx_thread_basic_execution_test +[379/441] Linking C executable regression/threadx_thread_completed_test +[380/441] Building C object regression/CMakeFiles/threadx_thread_preemption_change_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_preemption_change_test.c.o +[381/441] Linking C executable regression/threadx_thread_delayed_suspension_test +[382/441] Linking C executable regression/threadx_thread_create_preemption_threshold_test +[383/441] Building C object regression/CMakeFiles/threadx_thread_reset_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_reset_test.c.o +[384/441] Building C object regression/CMakeFiles/threadx_thread_relinquish_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_relinquish_test.c.o +[385/441] Building C object regression/CMakeFiles/threadx_thread_priority_change.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_priority_change.c.o +[386/441] Building C object regression/CMakeFiles/threadx_thread_simple_sleep_non_clear_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_simple_sleep_non_clear_test.c.o +[387/441] Linking C executable regression/threadx_thread_misaligned_stack_test +[388/441] Building C object regression/CMakeFiles/threadx_thread_simple_sleep_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_simple_sleep_test.c.o +[389/441] Building C object regression/CMakeFiles/threadx_thread_simple_suspend_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_simple_suspend_test.c.o +[390/441] Building C object regression/CMakeFiles/threadx_thread_sleep_for_100ticks_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_sleep_for_100ticks_test.c.o +[391/441] Building C object regression/CMakeFiles/threadx_thread_sleep_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_sleep_terminate_test.c.o +[392/441] Building C object regression/CMakeFiles/threadx_thread_stack_checking_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_stack_checking_test.c.o +[393/441] Linking C executable regression/threadx_thread_multiple_non_current_test +[394/441] Linking C executable regression/threadx_thread_multiple_suspension_test +[395/441] Building C object regression/CMakeFiles/threadx_thread_stack_fill_value_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_stack_fill_value_test.c.o +[396/441] Linking C executable regression/threadx_thread_multiple_sleep_test +[397/441] Linking C executable regression/threadx_thread_information_test +[398/441] Linking C executable regression/threadx_thread_multiple_time_slice_test +[399/441] Building C object regression/CMakeFiles/threadx_thread_time_slice_change_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_time_slice_change_test.c.o +[400/441] Building C object regression/CMakeFiles/threadx_thread_terminate_delete_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_terminate_delete_test.c.o +[401/441] Building C object regression/CMakeFiles/threadx_thread_wait_abort_and_isr_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c.o +[402/441] Building C object regression/CMakeFiles/threadx_thread_wait_abort_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_wait_abort_test.c.o +[403/441] Linking C executable regression/threadx_thread_multi_level_preemption_threshold_test +[404/441] Building C object regression/CMakeFiles/threadx_thread_exit_callback_transition_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_exit_callback_transition_test.c.o +[405/441] Linking C executable regression/threadx_thread_preemptable_suspension_test +[406/441] Building C object regression/CMakeFiles/threadx_time_get_set_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_time_get_set_test.c.o +[407/441] Linking C executable regression/threadx_thread_preemption_change_test +[408/441] Linking C executable regression/threadx_thread_reset_test +[409/441] Linking C executable regression/threadx_thread_priority_change +[410/441] Linking C executable regression/threadx_thread_relinquish_test +[411/441] Linking C executable regression/threadx_thread_simple_suspend_test +[412/441] Linking C executable regression/threadx_thread_simple_sleep_test +[413/441] Building C object regression/CMakeFiles/threadx_timer_activate_deactivate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_activate_deactivate_test.c.o +[414/441] Linking C executable regression/threadx_thread_simple_sleep_non_clear_test +[415/441] Linking C executable regression/threadx_thread_sleep_terminate_test +[416/441] Building C object regression/CMakeFiles/threadx_timer_deactivate_accuracy_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_deactivate_accuracy_test.c.o +[417/441] Linking C executable regression/threadx_thread_sleep_for_100ticks_test +[418/441] Linking C executable regression/threadx_thread_stack_checking_test +[419/441] Building C object regression/CMakeFiles/threadx_timer_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_information_test.c.o +[420/441] Building C object regression/CMakeFiles/threadx_timer_large_timer_accuracy_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_large_timer_accuracy_test.c.o +[421/441] Building C object regression/CMakeFiles/threadx_timer_multiple_accuracy_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_multiple_accuracy_test.c.o +[422/441] Building C object regression/CMakeFiles/threadx_timer_multiple_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_multiple_test.c.o +[423/441] Building C object regression/CMakeFiles/threadx_timer_simple_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_simple_test.c.o +[424/441] Building C object regression/CMakeFiles/threadx_trace_entry_update_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_trace_entry_update_test.c.o +[425/441] Linking C executable regression/threadx_thread_time_slice_change_test +[426/441] Linking C executable regression/threadx_thread_stack_fill_value_test +[427/441] Building C object regression/CMakeFiles/threadx_trace_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_trace_basic_test.c.o +[428/441] Linking C executable regression/threadx_thread_terminate_delete_test +[429/441] Linking C executable regression/threadx_thread_exit_callback_transition_test +[430/441] Linking C executable regression/threadx_thread_wait_abort_and_isr_test +[431/441] Linking C executable regression/threadx_thread_wait_abort_test +[432/441] Linking C executable regression/threadx_time_get_set_test +[433/441] Linking C executable regression/threadx_timer_activate_deactivate_test +[434/441] Linking C executable regression/threadx_timer_deactivate_accuracy_test +[435/441] Linking C executable regression/threadx_timer_large_timer_accuracy_test +[436/441] Linking C executable regression/threadx_timer_multiple_accuracy_test +[437/441] Linking C executable regression/threadx_timer_information_test +[438/441] Linking C executable regression/threadx_timer_simple_test +[439/441] Linking C executable regression/threadx_timer_multiple_test +[440/441] Linking C executable regression/threadx_trace_entry_update_test +[441/441] Linking C executable regression/threadx_trace_basic_test +BUILD_RC=0 diff --git a/common_modules/module_lib/src/txm_module_object_deallocate.c b/common_modules/module_lib/src/txm_module_object_deallocate.c index 480c6100..e0c0d6c4 100644 --- a/common_modules/module_lib/src/txm_module_object_deallocate.c +++ b/common_modules/module_lib/src/txm_module_object_deallocate.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -36,14 +38,18 @@ * WHAT TO DO: remove any call to txm_module_object_deallocate() from your * module. The corresponding tx_*_delete() call already handles everything. * - * RISK: calling txm_module_object_deallocate() on a live kernel object (one - * whose tx_*_delete() has not yet been called) frees the backing pool memory - * while the object is still referenced by the kernel, which is undefined - * behaviour (use-after-free). + * BEHAVIOUR: calling txm_module_object_deallocate() on a live kernel object + * (one whose tx_*_delete() has not yet been called) returns TX_DELETE_ERROR + * and changes nothing. The Module Manager will not release the memory of a + * created object, because the kernel goes on using those bytes as a control + * block after the byte pool has handed them to somebody else. Storage that + * was allocated but never made into an object is still released, so cleaning + * up after a create that failed or was abandoned still works. */ #pragma message("txm_module_object_deallocate() is deprecated and must not be used. " \ "Call tx_*_delete() instead; the Module Manager dispatch layer " \ - "releases pool memory automatically on success.") + "releases pool memory automatically on success. Deallocating a " \ + "live kernel object returns TX_DELETE_ERROR.") /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -64,7 +70,8 @@ /* */ /* OUTPUT */ /* */ -/* status Completion status */ +/* status Completion status, TX_DELETE_ERROR*/ +/* if a live object is there */ /* */ /* CALLS */ /* */ diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 6b75be7f..0160a1d1 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -15,6 +15,8 @@ // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -3285,41 +3287,6 @@ static ALIGN_TYPE _txm_module_manager_txm_module_object_deallocate_dispatch(TXM_ { ALIGN_TYPE return_value; -TXM_MODULE_ALLOCATED_OBJECT *object_ptr; -ALIGN_TYPE object_end; -ALIGN_TYPE object_pool_end; - - if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) - { - /* Is the object pool created? */ - if (_txm_module_manager_object_pool_created == TX_TRUE) - { - - /* Get the module allocated object. */ - object_ptr = ((TXM_MODULE_ALLOCATED_OBJECT *) param_0) - 1; - - /* Get the end address of the object pool. */ - object_pool_end = (ALIGN_TYPE) (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size); - - /* Check that the pointer is in the object pool. */ - if ((ALIGN_TYPE) object_ptr < (ALIGN_TYPE) _txm_module_manager_object_pool.tx_byte_pool_start || - (ALIGN_TYPE) object_ptr >= (ALIGN_TYPE) object_pool_end) - { - /* Pointer is outside of the object pool. */ - return(TXM_MODULE_INVALID_MEMORY); - } - - /* Get the end addresses of the object. */ - object_end = ((ALIGN_TYPE) object_ptr) + sizeof(TXM_MODULE_ALLOCATED_OBJECT) + object_ptr -> txm_module_object_size; - - /* Check that the object is in the object pool. */ - if (object_end >= object_pool_end) - { - /* Object is outside of the object pool. */ - return(TXM_MODULE_INVALID_MEMORY); - } - } - } return_value = (ALIGN_TYPE) _txm_module_manager_object_deallocate( (VOID *) param_0 diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h index 2630fe29..22b9570e 100644 --- a/common_modules/module_manager/inc/txm_module_manager_util.h +++ b/common_modules/module_manager/inc/txm_module_manager_util.h @@ -162,6 +162,7 @@ TXM_MODULE_ALLOCATED_OBJECT UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size); UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type); UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type); +UINT _txm_module_manager_live_object_check(ALIGN_TYPE object_ptr); UINT _txm_module_manager_util_code_allocation_size_and_alignment_get(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_alignment_dest, ULONG *code_allocation_size_dest); #endif diff --git a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c index 43d96f3c..dd4c105d 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c +++ b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c @@ -44,9 +44,7 @@ /* DEPRECATED. This function is called internally by the Module */ /* Manager dispatch layer after a successful tx_*_delete() call from */ /* a module. It must not be called directly by module or application */ -/* code. Calling it on a live kernel object (one whose tx_*_delete() */ -/* has not yet been called) frees the backing pool memory while the */ -/* object is still referenced by the kernel (use-after-free). */ +/* code. */ /* */ /* Module authors: remove any explicit call to */ /* txm_module_object_deallocate(). Calling the appropriate */ @@ -59,6 +57,13 @@ /* header from in front of the address the caller supplied. An */ /* address that names none of this module's allocations returns */ /* TX_PTR_ERROR and is not dereferenced. */ +/* Memory holding a live kernel object is not given back. Such a */ +/* request returns TX_DELETE_ERROR and changes nothing: the object */ +/* stays created, the allocation stays on the module's allocation */ +/* list, and the memory stays owned by the module. Storage that was */ +/* allocated but never made into an object is still released, so a */ +/* module can still clean up after a create that failed or was */ +/* abandoned. */ /* */ /* INPUT */ /* */ @@ -74,6 +79,7 @@ /* _txe_mutex_put Release module instance mutex */ /* _txm_module_manager_allocated_object_find */ /* Find the module's allocation */ +/* _txm_module_manager_live_object_check Check for a live object */ /* _txe_byte_release Release object back to pool */ /* */ /* */ @@ -130,6 +136,35 @@ UINT return_value; /* Set return value to invalid pointer. */ return_value = TX_PTR_ERROR; } + + /* Determine if a live kernel object is in this memory. + + Releasing the memory of a created object leaves the kernel holding the + only references to it. The object stays on the created list for its + type, a thread stays on the ready or suspension list it was on and stays + schedulable, and an active timer stays on the timer list. None of those + consult a control block ID, so nothing about the freed memory stops the + kernel using it: a created list walk reads a name pointer out of it, a + create or delete of another object of the same type writes through the + links in it, the scheduler restores a context from the stack pointer in + it, and timer expiration calls the function pointer in it. The byte pool + is meanwhile free to hand those bytes to the next allocation, so what the + kernel goes on reading as a control block is whatever the next owner of + the memory puts there. + + This is asked before the allocation is unlinked, so a refusal leaves the + allocation list, the object and the memory exactly as they were. What is + refused is releasing the memory of an object that is still created; an + allocation that was never made into an object, or one whose object has + been deleted, is released as before, which is what keeps cleanup after a + failed or abandoned create working and what makes the release the delete + dispatchers perform after a successful delete go through. */ + else if (_txm_module_manager_live_object_check((ALIGN_TYPE) object_ptr) == TX_TRUE) + { + + /* Set return value to indicate the object must be deleted first. */ + return_value = TX_DELETE_ERROR; + } else { diff --git a/common_modules/module_manager/src/txm_module_manager_util.c b/common_modules/module_manager/src/txm_module_manager_util.c index ba7e5a29..756120fa 100644 --- a/common_modules/module_manager/src/txm_module_manager_util.c +++ b/common_modules/module_manager/src/txm_module_manager_util.c @@ -1021,13 +1021,18 @@ UINT exact_object; /* This function determines whether an address is the exact address */ /* of an object on the kernel's created list for a module object type. */ /* */ -/* This is how an object the application created and shared with a */ -/* module is authenticated. Such an object is not in the manager's */ -/* object pool and the manager has no allocation record of it, so the */ -/* kernel's own created list is the only record of it that a module */ -/* cannot influence. Being on that list establishes at once that the */ -/* address is an object start, that the object is of this type, and */ -/* that it is created. */ +/* The created list is the record the create and delete services */ +/* maintain, so being on it establishes at once that the address is an */ +/* object start rather than an address inside an object, that the */ +/* object is of this type, and that it has not been deleted. It is */ +/* also the only record of an object the application created and */ +/* shared with a module, since the manager allocated no such object. */ +/* */ +/* Nothing the module can influence is consulted. In particular the */ +/* control block ID is not: a module can arrange for the value of an */ +/* ID to appear inside memory it owns, and distinct object types of */ +/* equal size exist, so an ID is not evidence that an object is there */ +/* nor of what type it is. */ /* */ /* INPUT */ /* */ @@ -1045,6 +1050,7 @@ UINT exact_object; /* */ /* CALLED BY */ /* */ +/* _txm_module_manager_live_object_check Module object liveness check */ /* _txm_module_manager_param_check_typed_object_for_use */ /* Module object authentication */ /* */ @@ -1402,6 +1408,96 @@ UINT status; } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_live_object_check PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether an address is the exact address */ +/* of a live kernel object of any type the Module Manager knows. */ +/* */ +/* It answers the question object deallocation has to ask before it */ +/* gives memory back: is the kernel still going to use these bytes as */ +/* a control block. Deallocation is told an address and nothing else, */ +/* so unlike the checks a typed service makes it cannot be given the */ +/* type to look for, and every type has to be looked for in turn. */ +/* */ +/* The eight created lists are searched whatever the size of the */ +/* allocation at the address. Skipping a type whose control block is */ +/* larger than the allocation would be sound only if every object had */ +/* been created through a size-checked path, and a module running */ +/* without memory protection creates objects without one. */ +/* */ +/* Each list is searched in its own interrupts-disabled window rather */ +/* than all of them in one, so the longest window is bounded by the */ +/* number of objects of a single type. The whole search costs one pass */ +/* over the objects the system has created, and is paid once per */ +/* object deallocation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Address of object memory area */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE A live kernel object is there */ +/* TX_FALSE Anything else */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_created_object_type_check */ +/* Check one kernel created list */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_object_deallocate Deallocate object memory */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_live_object_check(ALIGN_TYPE object_ptr) +{ + +UINT object_type; +UINT status; + + + /* Assume no live object is there. */ + status = TX_FALSE; + + /* The eight module object types that have a kernel created list occupy a + contiguous range, so each is asked in turn by walking the range. A value in + the range that the per-type check does not recognise answers TX_FALSE, so a + type the manager stops knowing does not silently pass this search. */ + for (object_type = ((UINT) TXM_BLOCK_POOL_OBJECT); object_type <= ((UINT) TXM_TIMER_OBJECT); object_type++) + { + + if (_txm_module_manager_created_object_type_check(object_ptr, object_type) == TX_TRUE) + { + + /* An address is the start of at most one object, so there is nothing + further to look for. */ + status = TX_TRUE; + break; + } + } + + return(status); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ diff --git a/ctest-all.log b/ctest-all.log new file mode 100644 index 00000000..51a050e1 --- /dev/null +++ b/ctest-all.log @@ -0,0 +1,220 @@ +Test project /tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/cmake/build/default_build_coverage + Start 1: default_build_coverage::threadx_block_memory_basic_test + 1/107 Test #1: default_build_coverage::threadx_block_memory_basic_test ............................. Passed 0.08 sec + Start 2: default_build_coverage::threadx_block_memory_error_detection_test + 2/107 Test #2: default_build_coverage::threadx_block_memory_error_detection_test ................... Passed 0.01 sec + Start 3: default_build_coverage::threadx_block_memory_information_test + 3/107 Test #3: default_build_coverage::threadx_block_memory_information_test ....................... Passed 0.02 sec + Start 4: default_build_coverage::threadx_block_memory_prioritize_test + 4/107 Test #4: default_build_coverage::threadx_block_memory_prioritize_test ........................ Passed 0.03 sec + Start 5: default_build_coverage::threadx_block_memory_suspension_test + 5/107 Test #5: default_build_coverage::threadx_block_memory_suspension_test ........................ Passed 0.01 sec + Start 6: default_build_coverage::threadx_block_memory_suspension_timeout_test + 6/107 Test #6: default_build_coverage::threadx_block_memory_suspension_timeout_test ................ Passed 0.65 sec + Start 7: default_build_coverage::threadx_block_memory_thread_terminate_test + 7/107 Test #7: default_build_coverage::threadx_block_memory_thread_terminate_test .................. Passed 0.01 sec + Start 8: default_build_coverage::threadx_byte_memory_basic_test + 8/107 Test #8: default_build_coverage::threadx_byte_memory_basic_test .............................. Passed 0.03 sec + Start 9: default_build_coverage::threadx_byte_memory_information_test + 9/107 Test #9: default_build_coverage::threadx_byte_memory_information_test ........................ Passed 0.02 sec + Start 10: default_build_coverage::threadx_byte_memory_prioritize_test + 10/107 Test #10: default_build_coverage::threadx_byte_memory_prioritize_test ......................... Passed 0.03 sec + Start 11: default_build_coverage::threadx_byte_memory_suspension_test + 11/107 Test #11: default_build_coverage::threadx_byte_memory_suspension_test ......................... Passed 0.01 sec + Start 12: default_build_coverage::threadx_byte_memory_suspension_timeout_test + 12/107 Test #12: default_build_coverage::threadx_byte_memory_suspension_timeout_test ................. Passed 0.65 sec + Start 13: default_build_coverage::threadx_byte_memory_thread_contention_test + 13/107 Test #13: default_build_coverage::threadx_byte_memory_thread_contention_test .................. Passed 1.36 sec + Start 14: default_build_coverage::threadx_byte_memory_thread_terminate_test + 14/107 Test #14: default_build_coverage::threadx_byte_memory_thread_terminate_test ................... Passed 0.01 sec + Start 15: default_build_coverage::threadx_event_flag_basic_test + 15/107 Test #15: default_build_coverage::threadx_event_flag_basic_test ............................... Passed 0.07 sec + Start 16: default_build_coverage::threadx_event_flag_information_test + 16/107 Test #16: default_build_coverage::threadx_event_flag_information_test ......................... Passed 0.01 sec + Start 17: default_build_coverage::threadx_event_flag_isr_set_clear_test + 17/107 Test #17: default_build_coverage::threadx_event_flag_isr_set_clear_test ....................... Passed 0.91 sec + Start 18: default_build_coverage::threadx_event_flag_isr_wait_abort_test + 18/107 Test #18: default_build_coverage::threadx_event_flag_isr_wait_abort_test ...................... Passed 0.81 sec + Start 19: default_build_coverage::threadx_event_flag_single_thread_terminate_test + 19/107 Test #19: default_build_coverage::threadx_event_flag_single_thread_terminate_test ............. Passed 0.31 sec + Start 20: default_build_coverage::threadx_event_flag_suspension_consume_test + 20/107 Test #20: default_build_coverage::threadx_event_flag_suspension_consume_test .................. Passed 0.01 sec + Start 21: default_build_coverage::threadx_event_flag_suspension_different_bits_consume_test + 21/107 Test #21: default_build_coverage::threadx_event_flag_suspension_different_bits_consume_test ... Passed 0.01 sec + Start 22: default_build_coverage::threadx_event_flag_suspension_different_bits_test + 22/107 Test #22: default_build_coverage::threadx_event_flag_suspension_different_bits_test ........... Passed 0.01 sec + Start 23: default_build_coverage::threadx_event_flag_suspension_test + 23/107 Test #23: default_build_coverage::threadx_event_flag_suspension_test .......................... Passed 0.01 sec + Start 24: default_build_coverage::threadx_event_flag_suspension_timeout_test + 24/107 Test #24: default_build_coverage::threadx_event_flag_suspension_timeout_test .................. Passed 0.68 sec + Start 25: default_build_coverage::threadx_event_flag_thread_terminate_test + 25/107 Test #25: default_build_coverage::threadx_event_flag_thread_terminate_test .................... Passed 0.01 sec + Start 26: default_build_coverage::threadx_interrupt_control_test + 26/107 Test #26: default_build_coverage::threadx_interrupt_control_test .............................. Passed 0.03 sec + Start 27: default_build_coverage::threadx_mutex_basic_test + 27/107 Test #27: default_build_coverage::threadx_mutex_basic_test .................................... Passed 0.09 sec + Start 28: default_build_coverage::threadx_mutex_delete_test + 28/107 Test #28: default_build_coverage::threadx_mutex_delete_test ................................... Passed 0.01 sec + Start 29: default_build_coverage::threadx_mutex_information_test + 29/107 Test #29: default_build_coverage::threadx_mutex_information_test .............................. Passed 0.01 sec + Start 30: default_build_coverage::threadx_mutex_nested_priority_inheritance_test + 30/107 Test #30: default_build_coverage::threadx_mutex_nested_priority_inheritance_test .............. Passed 0.10 sec + Start 31: default_build_coverage::threadx_mutex_no_preemption_test + 31/107 Test #31: default_build_coverage::threadx_mutex_no_preemption_test ............................ Passed 0.01 sec + Start 32: default_build_coverage::threadx_mutex_preemption_test + 32/107 Test #32: default_build_coverage::threadx_mutex_preemption_test ............................... Passed 0.01 sec + Start 33: default_build_coverage::threadx_mutex_priority_inheritance_test + 33/107 Test #33: default_build_coverage::threadx_mutex_priority_inheritance_test ..................... Passed 0.21 sec + Start 34: default_build_coverage::threadx_mutex_proritize_test + 34/107 Test #34: default_build_coverage::threadx_mutex_proritize_test ................................ Passed 0.03 sec + Start 35: default_build_coverage::threadx_mutex_suspension_timeout_test + 35/107 Test #35: default_build_coverage::threadx_mutex_suspension_timeout_test ....................... Passed 0.37 sec + Start 36: default_build_coverage::threadx_mutex_thread_terminate_test + 36/107 Test #36: default_build_coverage::threadx_mutex_thread_terminate_test ......................... Passed 0.01 sec + Start 37: default_build_coverage::threadx_queue_basic_eight_word_test + 37/107 Test #37: default_build_coverage::threadx_queue_basic_eight_word_test ......................... Passed 0.00 sec + Start 38: default_build_coverage::threadx_queue_basic_four_word_test + 38/107 Test #38: default_build_coverage::threadx_queue_basic_four_word_test .......................... Passed 0.00 sec + Start 39: default_build_coverage::threadx_queue_basic_one_word_test + 39/107 Test #39: default_build_coverage::threadx_queue_basic_one_word_test ........................... Passed 0.07 sec + Start 40: default_build_coverage::threadx_queue_basic_sixteen_word_test + 40/107 Test #40: default_build_coverage::threadx_queue_basic_sixteen_word_test ....................... Passed 0.01 sec + Start 41: default_build_coverage::threadx_queue_basic_two_word_test + 41/107 Test #41: default_build_coverage::threadx_queue_basic_two_word_test ........................... Passed 0.00 sec + Start 42: default_build_coverage::threadx_queue_basic_max_message_size_test + 42/107 Test #42: default_build_coverage::threadx_queue_basic_max_message_size_test ................... Passed 0.00 sec + Start 43: default_build_coverage::threadx_queue_empty_suspension_test + 43/107 Test #43: default_build_coverage::threadx_queue_empty_suspension_test ......................... Passed 0.01 sec + Start 44: default_build_coverage::threadx_queue_flush_no_suspension_test + 44/107 Test #44: default_build_coverage::threadx_queue_flush_no_suspension_test ...................... Passed 0.00 sec + Start 45: default_build_coverage::threadx_queue_flush_test + 45/107 Test #45: default_build_coverage::threadx_queue_flush_test .................................... Passed 0.01 sec + Start 46: default_build_coverage::threadx_queue_front_send_test + 46/107 Test #46: default_build_coverage::threadx_queue_front_send_test ............................... Passed 0.01 sec + Start 47: default_build_coverage::threadx_queue_full_suspension_test + 47/107 Test #47: default_build_coverage::threadx_queue_full_suspension_test .......................... Passed 0.01 sec + Start 48: default_build_coverage::threadx_queue_information_test + 48/107 Test #48: default_build_coverage::threadx_queue_information_test .............................. Passed 0.00 sec + Start 49: default_build_coverage::threadx_queue_prioritize + 49/107 Test #49: default_build_coverage::threadx_queue_prioritize .................................... Passed 0.03 sec + Start 50: default_build_coverage::threadx_queue_suspension_timeout_test + 50/107 Test #50: default_build_coverage::threadx_queue_suspension_timeout_test ....................... Passed 0.36 sec + Start 51: default_build_coverage::threadx_queue_thread_terminate_test + 51/107 Test #51: default_build_coverage::threadx_queue_thread_terminate_test ......................... Passed 0.01 sec + Start 52: default_build_coverage::threadx_semaphore_basic_test + 52/107 Test #52: default_build_coverage::threadx_semaphore_basic_test ................................ Passed 0.07 sec + Start 53: default_build_coverage::threadx_semaphore_ceiling_put_test + 53/107 Test #53: default_build_coverage::threadx_semaphore_ceiling_put_test .......................... Passed 0.01 sec + Start 54: default_build_coverage::threadx_semaphore_delete_test + 54/107 Test #54: default_build_coverage::threadx_semaphore_delete_test ............................... Passed 0.01 sec + Start 55: default_build_coverage::threadx_semaphore_information_test + 55/107 Test #55: default_build_coverage::threadx_semaphore_information_test .......................... Passed 0.00 sec + Start 56: default_build_coverage::threadx_semaphore_non_preemption_test + 56/107 Test #56: default_build_coverage::threadx_semaphore_non_preemption_test ....................... Passed 0.01 sec + Start 57: default_build_coverage::threadx_semaphore_preemption_test + 57/107 Test #57: default_build_coverage::threadx_semaphore_preemption_test ........................... Passed 0.01 sec + Start 58: default_build_coverage::threadx_semaphore_prioritize + 58/107 Test #58: default_build_coverage::threadx_semaphore_prioritize ................................ Passed 0.03 sec + Start 59: default_build_coverage::threadx_semaphore_thread_terminate_test + 59/107 Test #59: default_build_coverage::threadx_semaphore_thread_terminate_test ..................... Passed 0.01 sec + Start 60: default_build_coverage::threadx_semaphore_timeout_test + 60/107 Test #60: default_build_coverage::threadx_semaphore_timeout_test .............................. Passed 0.36 sec + Start 61: default_build_coverage::threadx_thread_basic_execution_test + 61/107 Test #61: default_build_coverage::threadx_thread_basic_execution_test ......................... Passed 0.05 sec + Start 62: default_build_coverage::threadx_thread_basic_time_slice_test + 62/107 Test #62: default_build_coverage::threadx_thread_basic_time_slice_test ........................ Passed 0.20 sec + Start 63: default_build_coverage::threadx_thread_completed_test + 63/107 Test #63: default_build_coverage::threadx_thread_completed_test ............................... Passed 0.02 sec + Start 64: default_build_coverage::threadx_thread_create_preemption_threshold_test + 64/107 Test #64: default_build_coverage::threadx_thread_create_preemption_threshold_test ............. Passed 0.03 sec + Start 65: default_build_coverage::threadx_thread_delayed_suspension_test + 65/107 Test #65: default_build_coverage::threadx_thread_delayed_suspension_test ...................... Passed 7.26 sec + Start 66: default_build_coverage::threadx_thread_information_test + 66/107 Test #66: default_build_coverage::threadx_thread_information_test ............................. Passed 0.01 sec + Start 67: default_build_coverage::threadx_thread_misaligned_stack_test + 67/107 Test #67: default_build_coverage::threadx_thread_misaligned_stack_test ........................ Passed 0.06 sec + Start 68: default_build_coverage::threadx_thread_multi_level_preemption_threshold_test + 68/107 Test #68: default_build_coverage::threadx_thread_multi_level_preemption_threshold_test ........ Passed 0.02 sec + Start 69: default_build_coverage::threadx_thread_multiple_non_current_test + 69/107 Test #69: default_build_coverage::threadx_thread_multiple_non_current_test .................... Passed 0.01 sec + Start 70: default_build_coverage::threadx_thread_multiple_sleep_test + 70/107 Test #70: default_build_coverage::threadx_thread_multiple_sleep_test .......................... Passed 1.02 sec + Start 71: default_build_coverage::threadx_thread_multiple_suspension_test + 71/107 Test #71: default_build_coverage::threadx_thread_multiple_suspension_test ..................... Passed 0.01 sec + Start 72: default_build_coverage::threadx_thread_multiple_time_slice_test + 72/107 Test #72: default_build_coverage::threadx_thread_multiple_time_slice_test ..................... Passed 0.54 sec + Start 73: default_build_coverage::threadx_thread_preemptable_suspension_test + 73/107 Test #73: default_build_coverage::threadx_thread_preemptable_suspension_test .................. Passed 0.01 sec + Start 74: default_build_coverage::threadx_thread_preemption_change_test + 74/107 Test #74: default_build_coverage::threadx_thread_preemption_change_test ....................... Passed 0.01 sec + Start 75: default_build_coverage::threadx_thread_priority_change + 75/107 Test #75: default_build_coverage::threadx_thread_priority_change .............................. Passed 0.18 sec + Start 76: default_build_coverage::threadx_thread_relinquish_test + 76/107 Test #76: default_build_coverage::threadx_thread_relinquish_test .............................. Passed 0.01 sec + Start 77: default_build_coverage::threadx_thread_reset_test + 77/107 Test #77: default_build_coverage::threadx_thread_reset_test ................................... Passed 0.01 sec + Start 78: default_build_coverage::threadx_thread_simple_sleep_non_clear_test + 78/107 Test #78: default_build_coverage::threadx_thread_simple_sleep_non_clear_test .................. Passed 0.20 sec + Start 79: default_build_coverage::threadx_thread_simple_sleep_test + 79/107 Test #79: default_build_coverage::threadx_thread_simple_sleep_test ............................ Passed 0.19 sec + Start 80: default_build_coverage::threadx_thread_simple_suspend_test + 80/107 Test #80: default_build_coverage::threadx_thread_simple_suspend_test .......................... Passed 0.00 sec + Start 81: default_build_coverage::threadx_thread_sleep_for_100ticks_test + 81/107 Test #81: default_build_coverage::threadx_thread_sleep_for_100ticks_test ...................... Passed 1.01 sec + Start 82: default_build_coverage::threadx_thread_sleep_terminate_test + 82/107 Test #82: default_build_coverage::threadx_thread_sleep_terminate_test ......................... Passed 0.05 sec + Start 83: default_build_coverage::threadx_thread_stack_checking_test + 83/107 Test #83: default_build_coverage::threadx_thread_stack_checking_test .......................... Passed 0.01 sec + Start 84: default_build_coverage::threadx_thread_stack_fill_value_test + 84/107 Test #84: default_build_coverage::threadx_thread_stack_fill_value_test ........................ Passed 0.01 sec + Start 85: default_build_coverage::threadx_thread_terminate_delete_test + 85/107 Test #85: default_build_coverage::threadx_thread_terminate_delete_test ........................ Passed 0.00 sec + Start 86: default_build_coverage::threadx_thread_exit_callback_transition_test + 86/107 Test #86: default_build_coverage::threadx_thread_exit_callback_transition_test ................ Passed 0.25 sec + Start 87: default_build_coverage::threadx_thread_time_slice_change_test + 87/107 Test #87: default_build_coverage::threadx_thread_time_slice_change_test ....................... Passed 0.10 sec + Start 88: default_build_coverage::threadx_thread_wait_abort_and_isr_test + 88/107 Test #88: default_build_coverage::threadx_thread_wait_abort_and_isr_test ...................... Passed 0.22 sec + Start 89: default_build_coverage::threadx_thread_wait_abort_test + 89/107 Test #89: default_build_coverage::threadx_thread_wait_abort_test .............................. Passed 0.01 sec + Start 90: default_build_coverage::threadx_time_get_set_test + 90/107 Test #90: default_build_coverage::threadx_time_get_set_test ................................... Passed 0.37 sec + Start 91: default_build_coverage::threadx_timer_activate_deactivate_test + 91/107 Test #91: default_build_coverage::threadx_timer_activate_deactivate_test ...................... Passed 0.86 sec + Start 92: default_build_coverage::threadx_timer_deactivate_accuracy_test + 92/107 Test #92: default_build_coverage::threadx_timer_deactivate_accuracy_test ...................... Passed 0.40 sec + Start 93: default_build_coverage::threadx_timer_information_test + 93/107 Test #93: default_build_coverage::threadx_timer_information_test .............................. Passed 1.61 sec + Start 94: default_build_coverage::threadx_timer_large_timer_accuracy_test + 94/107 Test #94: default_build_coverage::threadx_timer_large_timer_accuracy_test ..................... Passed 1.11 sec + Start 95: default_build_coverage::threadx_timer_multiple_accuracy_test + 95/107 Test #95: default_build_coverage::threadx_timer_multiple_accuracy_test ........................ Passed 3.05 sec + Start 96: default_build_coverage::threadx_timer_multiple_test + 96/107 Test #96: default_build_coverage::threadx_timer_multiple_test ................................. Passed 6.07 sec + Start 97: default_build_coverage::threadx_timer_simple_test + 97/107 Test #97: default_build_coverage::threadx_timer_simple_test ................................... Passed 1.65 sec + Start 98: default_build_coverage::threadx_trace_basic_test + 98/107 Test #98: default_build_coverage::threadx_trace_basic_test .................................... Passed 0.01 sec + Start 99: default_build_coverage::threadx_trace_entry_update_test + 99/107 Test #99: default_build_coverage::threadx_trace_entry_update_test ............................. Passed 0.05 sec + Start 100: default_build_coverage::threadx_initialize_kernel_setup_test +100/107 Test #100: default_build_coverage::threadx_initialize_kernel_setup_test ........................ Passed 0.00 sec + Start 101: default_build_coverage::threadx_thread_transition_ni_test +101/107 Test #101: default_build_coverage::threadx_thread_transition_ni_test ........................... Passed 0.00 sec + Start 102: default_build_coverage::threadx_thread_transition_ni_no_error_checking_test +102/107 Test #102: default_build_coverage::threadx_thread_transition_ni_no_error_checking_test ......... Passed 0.00 sec + Start 103: default_build_coverage::threadx_thread_transition_ni_no_notify_test +103/107 Test #103: default_build_coverage::threadx_thread_transition_ni_no_notify_test ................. Passed 0.00 sec + Start 104: default_build_coverage::threadx_thread_transition_no_error_checking_test +104/107 Test #104: default_build_coverage::threadx_thread_transition_no_error_checking_test ............ Passed 0.00 sec + Start 105: default_build_coverage::threadx_module_manager_thread_kernel_stack_test +105/107 Test #105: default_build_coverage::threadx_module_manager_thread_kernel_stack_test ............. Passed 0.00 sec + Start 106: default_build_coverage::threadx_module_manager_object_authentication_test +106/107 Test #106: default_build_coverage::threadx_module_manager_object_authentication_test ........... Passed 0.00 sec + Start 107: default_build_coverage::threadx_module_manager_delete_ownership_test +107/107 Test #107: default_build_coverage::threadx_module_manager_delete_ownership_test ................ Passed 0.00 sec + +100% tests passed out of 107 + +Total Test time (real) = 34.26 sec +CTEST_RC=0 diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index 695a1fe5..cfc0835c 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -127,3 +127,29 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_delete_ownership_test threadx_module_manager_delete_ownership_test) + +# This test drives the allocation and deallocation services directly rather than +# through a dispatcher, so it needs none of the dispatch table and no guard list. +add_executable( + threadx_module_manager_live_object_deallocation_test + ${SOURCE_DIR}/threadx_module_manager_live_object_deallocation_test.c + ${module_manager_dir}/src/txm_module_manager_util.c + ${module_manager_dir}/src/txm_module_manager_object_allocate.c + ${module_manager_dir}/src/txm_module_manager_object_deallocate.c) + +target_include_directories( + threadx_module_manager_live_object_deallocation_test + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_a7_module_dir}/inc) + +target_compile_options( + threadx_module_manager_live_object_deallocation_test + PRIVATE -Wall + -Wextra + -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_live_object_deallocation_test + threadx_module_manager_live_object_deallocation_test) diff --git a/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c b/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c new file mode 100644 index 00000000..3eaf95c6 --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c @@ -0,0 +1,1223 @@ +/*************************************************************************** + * Copyright (c) 2026 Eclipse ThreadX contributors + * + * This program and the accompanying materials are made available under the + * terms of the MIT License which is available at + * https://opensource.org/licenses/MIT. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager live kernel object deallocation */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A module allocates the memory for its kernel objects from the Module Manager's + object pool, and can ask for that memory back by address. The manager gave that + memory back whatever was in it, including a control block the kernel was still + using: the object stays on the created list for its type, a thread stays on the + ready or suspension list it was on and stays schedulable, and an active timer + stays on the timer list. None of those consult a control block ID, so nothing + about the freed memory stops the kernel reading a name pointer out of it, + writing through the created links in it, restoring a context from the stack + pointer in it, or calling the timeout function pointer in it -- while the byte + pool is free to have handed those same bytes to the next allocation. + + The manager now refuses to release the memory of an object that is still + created, and answers the question from the kernel's created lists rather than + from the control block, because a control block is not evidence: an allocation + that was never made into an object can carry the value of an ID, and objects of + distinct types share a size. + + This test drives that refusal on the host. The object pool behind it is + modelled -- a bump allocator that hands back the block it most recently + released, so that the address of a freed object can be seen to come back -- but + the two records the manager consults are built the way the system builds them: + the module allocation list by running the real + _txm_module_manager_object_allocate, and the kernel created lists the way the + create and delete services maintain them. + + What the test asserts is that memory is given back when, and only when, no live + kernel object is in it: refused for every one of the eight object types, and + still released for storage that was never created, for storage carrying nothing + but a plausible ID, and for an object that has been deleted -- which is the + release the delete dispatchers perform, and the one this must not break. */ + +#include + +#include "threadx_module_manager_host_test_port.h" + +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Define the stand-in interrupt lock the port shim counts through. */ + +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + + +/* Define the modelled object pool. */ + +#define TEST_POOL_BYTES ((ULONG) 8192) +#define TEST_MODULE_MEMORY_BYTES 512U + +static union +{ + ALIGN_TYPE test_pool_alignment; + UCHAR test_pool_bytes[TEST_POOL_BYTES]; +} test_pool_arena; + +static ULONG test_pool_offset; + + +/* Define the memory that stands for the calling module's own code and data. */ + +static union +{ + ALIGN_TYPE test_data_alignment; + UCHAR test_data_bytes[TEST_MODULE_MEMORY_BYTES]; +} test_module_data; + +static union +{ + ALIGN_TYPE test_code_alignment; + UCHAR test_code_bytes[TEST_MODULE_MEMORY_BYTES]; +} test_module_code; + + +/* Define an object that stands for one the application owns and shared with a + module. It lives outside the pool, so the manager has no allocation record of + it and the kernel created list is the only record of it there is. */ + +static TX_QUEUE test_host_queue; + + +/* Define the thread that stands for the module thread making the request. The + manager takes the calling module from it. */ + +static TX_THREAD test_current_thread; + + +/* Define the block the modelled pool most recently released, so that a later + allocation of the same size lands on the address a freed object had, and so + that a case can see whether anything was released at all. */ + +static UCHAR *test_released_start; +static ULONG test_released_bytes; +static ULONG test_releases; + + +/* Define the manager state the code under test reaches for. */ + +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; +TX_MUTEX _txm_module_manager_mutex; +TX_THREAD *_tx_thread_current_ptr; + + +/* Define the kernel created lists the liveness check walks. */ + +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + + +static UINT test_failures; +static ULONG test_checks; + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + test_checks++; + + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Report every module object type the manager knows, and the name, control block + size and control block ID of each, so that the cases below can be written once + and run against all of them. */ + +typedef struct TEST_OBJECT_KIND_STRUCT +{ + UINT test_kind_type; + const char *test_kind_name; + ULONG test_kind_size; + ULONG test_kind_id; +} TEST_OBJECT_KIND; + +static const TEST_OBJECT_KIND test_object_kinds[] = +{ + { TXM_BLOCK_POOL_OBJECT, "block pool", (ULONG) sizeof(TX_BLOCK_POOL), TX_BLOCK_POOL_ID }, + { TXM_BYTE_POOL_OBJECT, "byte pool", (ULONG) sizeof(TX_BYTE_POOL), TX_BYTE_POOL_ID }, + { TXM_EVENT_FLAGS_OBJECT, "event flags", (ULONG) sizeof(TX_EVENT_FLAGS_GROUP), TX_EVENT_FLAGS_ID }, + { TXM_MUTEX_OBJECT, "mutex", (ULONG) sizeof(TX_MUTEX), TX_MUTEX_ID }, + { TXM_QUEUE_OBJECT, "queue", (ULONG) sizeof(TX_QUEUE), TX_QUEUE_ID }, + { TXM_SEMAPHORE_OBJECT, "semaphore", (ULONG) sizeof(TX_SEMAPHORE), TX_SEMAPHORE_ID }, + { TXM_THREAD_OBJECT, "thread", (ULONG) sizeof(TX_THREAD), TX_THREAD_ID }, + { TXM_TIMER_OBJECT, "timer", (ULONG) sizeof(TX_TIMER), TX_TIMER_ID } +}; + +#define TEST_OBJECT_KIND_COUNT (sizeof(test_object_kinds) / sizeof(test_object_kinds[0])) + + +/* Round a request up the way _tx_byte_allocate does. */ +static ULONG test_round_up(ULONG memory_size) +{ + return((((memory_size + ((ULONG) sizeof(ALIGN_TYPE))) - ((ULONG) 1)) / ((ULONG) sizeof(ALIGN_TYPE))) * ((ULONG) sizeof(ALIGN_TYPE))); +} + + +/* Stand in for the byte pool the manager allocates object memory from. + + The two size bounds are the real ones. The placement is a bump allocator with + one refinement: a request that exactly fits the block most recently released is + given that block back. A first-fit byte pool reuses freed memory, and the cases + about an address that has been released need the address to actually come back. */ +UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option) +{ + +ULONG rounded_size; +UCHAR *block_start; + + + (VOID) wait_option; + + if ((pool_ptr != &_txm_module_manager_object_pool) || (memory_ptr == TX_NULL)) + { + return(TX_POOL_ERROR); + } + + if (memory_size == ((ULONG) 0)) + { + return(TX_SIZE_ERROR); + } + + if (memory_size > pool_ptr -> tx_byte_pool_size) + { + return(TX_SIZE_ERROR); + } + + rounded_size = test_round_up(memory_size); + + if ((test_released_start != TX_NULL) && (test_released_bytes == rounded_size)) + { + block_start = test_released_start; + test_released_start = TX_NULL; + test_released_bytes = ((ULONG) 0); + } + else + { + if ((test_pool_offset + rounded_size) > TEST_POOL_BYTES) + { + return(TX_NO_MEMORY); + } + + block_start = &test_pool_arena.test_pool_bytes[test_pool_offset]; + test_pool_offset = test_pool_offset + rounded_size; + } + + pool_ptr -> tx_byte_pool_available = pool_ptr -> tx_byte_pool_available - rounded_size; + + *memory_ptr = (VOID *) block_start; + + return(TX_SUCCESS); +} + + +/* Stand in for the release side, remembering the block so it can come back, and + counting releases so that a case can see whether one happened. */ +UINT _txe_byte_release(VOID *memory_ptr) +{ + +UCHAR *block_start; + + + block_start = (UCHAR *) memory_ptr; + + if ((block_start < test_pool_arena.test_pool_bytes) || + (block_start >= &test_pool_arena.test_pool_bytes[TEST_POOL_BYTES])) + { + return(TX_PTR_ERROR); + } + + test_releases++; + + /* The model does not track block lengths, and the only released block a case + needs to come back is the one it just released, whose length it knows. The + length is recorded by the caller through test_release_size. */ + test_released_start = block_start; + + return(TX_SUCCESS); +} + + +/* Tell the model how long the block just released was. */ +static VOID test_release_size(ULONG object_size) +{ + test_released_bytes = test_round_up(object_size + ((ULONG) sizeof(TXM_MODULE_ALLOCATED_OBJECT))); +} + + +/* Stand in for the protection mutex. */ +UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) +{ + (VOID) mutex_ptr; + (VOID) wait_option; + + return(TX_SUCCESS); +} + + +UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) +{ + (VOID) mutex_ptr; + + return(TX_SUCCESS); +} + + +/* Stand in for the module port's data range check. */ +UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +{ + +ULONG data_start; +ULONG data_end; + + + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; + data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); + + if ((obj_ptr >= data_start) && (obj_ptr < data_end)) + { + return(TX_TRUE); + } + + return(TX_FALSE); +} + + +/* Stand in for the port primitive a manager source under test refers to but that + no case here exercises. */ +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +/* Do to an object what the kernel's create service does: write the control block + ID, and link the object onto the created list for its type. + + The chain each list is built as ends in a self-link on its oldest member rather + than closing back on the head, so that a walk bounded by the created count + visits every member and a walk that ignored the count would not run off the + end. What is being tested is the bound, not the model. */ +static VOID test_object_create(VOID *object_ptr, UINT object_type) +{ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + { + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *) object_ptr; + + block_pool_ptr -> tx_block_pool_id = TX_BLOCK_POOL_ID; + block_pool_ptr -> tx_block_pool_created_next = (_tx_block_pool_created_ptr == TX_NULL) ? block_pool_ptr : _tx_block_pool_created_ptr; + _tx_block_pool_created_ptr = block_pool_ptr; + _tx_block_pool_created_count++; + break; + } + + case TXM_BYTE_POOL_OBJECT: + { + TX_BYTE_POOL *byte_pool_ptr = (TX_BYTE_POOL *) object_ptr; + + byte_pool_ptr -> tx_byte_pool_id = TX_BYTE_POOL_ID; + byte_pool_ptr -> tx_byte_pool_created_next = (_tx_byte_pool_created_ptr == TX_NULL) ? byte_pool_ptr : _tx_byte_pool_created_ptr; + _tx_byte_pool_created_ptr = byte_pool_ptr; + _tx_byte_pool_created_count++; + break; + } + + case TXM_EVENT_FLAGS_OBJECT: + { + TX_EVENT_FLAGS_GROUP *event_flags_ptr = (TX_EVENT_FLAGS_GROUP *) object_ptr; + + event_flags_ptr -> tx_event_flags_group_id = TX_EVENT_FLAGS_ID; + event_flags_ptr -> tx_event_flags_group_created_next = (_tx_event_flags_created_ptr == TX_NULL) ? event_flags_ptr : _tx_event_flags_created_ptr; + _tx_event_flags_created_ptr = event_flags_ptr; + _tx_event_flags_created_count++; + break; + } + + case TXM_MUTEX_OBJECT: + { + TX_MUTEX *mutex_ptr = (TX_MUTEX *) object_ptr; + + mutex_ptr -> tx_mutex_id = TX_MUTEX_ID; + mutex_ptr -> tx_mutex_created_next = (_tx_mutex_created_ptr == TX_NULL) ? mutex_ptr : _tx_mutex_created_ptr; + _tx_mutex_created_ptr = mutex_ptr; + _tx_mutex_created_count++; + break; + } + + case TXM_QUEUE_OBJECT: + { + TX_QUEUE *queue_ptr = (TX_QUEUE *) object_ptr; + + queue_ptr -> tx_queue_id = TX_QUEUE_ID; + queue_ptr -> tx_queue_created_next = (_tx_queue_created_ptr == TX_NULL) ? queue_ptr : _tx_queue_created_ptr; + _tx_queue_created_ptr = queue_ptr; + _tx_queue_created_count++; + break; + } + + case TXM_SEMAPHORE_OBJECT: + { + TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *) object_ptr; + + semaphore_ptr -> tx_semaphore_id = TX_SEMAPHORE_ID; + semaphore_ptr -> tx_semaphore_created_next = (_tx_semaphore_created_ptr == TX_NULL) ? semaphore_ptr : _tx_semaphore_created_ptr; + _tx_semaphore_created_ptr = semaphore_ptr; + _tx_semaphore_created_count++; + break; + } + + case TXM_THREAD_OBJECT: + { + TX_THREAD *thread_ptr = (TX_THREAD *) object_ptr; + + thread_ptr -> tx_thread_id = TX_THREAD_ID; + thread_ptr -> tx_thread_created_next = (_tx_thread_created_ptr == TX_NULL) ? thread_ptr : _tx_thread_created_ptr; + _tx_thread_created_ptr = thread_ptr; + _tx_thread_created_count++; + break; + } + + case TXM_TIMER_OBJECT: + default: + { + TX_TIMER *timer_ptr = (TX_TIMER *) object_ptr; + + timer_ptr -> tx_timer_id = TX_TIMER_ID; + timer_ptr -> tx_timer_created_next = (_tx_timer_created_ptr == TX_NULL) ? timer_ptr : _tx_timer_created_ptr; + _tx_timer_created_ptr = timer_ptr; + _tx_timer_created_count++; + break; + } + } +} + + +/* Do to an object what the kernel's delete service does: clear the control block + ID, and take the object off the created list for its type. + + Every case that deletes has one object of that type on the list, which is the + shape that matters here, so the model empties the list rather than unlinking a + member of a longer one. */ +static VOID test_object_delete(VOID *object_ptr, UINT object_type) +{ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + + ((TX_BLOCK_POOL *) object_ptr) -> tx_block_pool_id = TX_CLEAR_ID; + _tx_block_pool_created_ptr = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 0); + break; + + case TXM_BYTE_POOL_OBJECT: + + ((TX_BYTE_POOL *) object_ptr) -> tx_byte_pool_id = TX_CLEAR_ID; + _tx_byte_pool_created_ptr = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 0); + break; + + case TXM_EVENT_FLAGS_OBJECT: + + ((TX_EVENT_FLAGS_GROUP *) object_ptr) -> tx_event_flags_group_id = TX_CLEAR_ID; + _tx_event_flags_created_ptr = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 0); + break; + + case TXM_MUTEX_OBJECT: + + ((TX_MUTEX *) object_ptr) -> tx_mutex_id = TX_CLEAR_ID; + _tx_mutex_created_ptr = TX_NULL; + _tx_mutex_created_count = ((ULONG) 0); + break; + + case TXM_QUEUE_OBJECT: + + ((TX_QUEUE *) object_ptr) -> tx_queue_id = TX_CLEAR_ID; + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + break; + + case TXM_SEMAPHORE_OBJECT: + + ((TX_SEMAPHORE *) object_ptr) -> tx_semaphore_id = TX_CLEAR_ID; + _tx_semaphore_created_ptr = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 0); + break; + + case TXM_THREAD_OBJECT: + + ((TX_THREAD *) object_ptr) -> tx_thread_id = TX_CLEAR_ID; + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = ((ULONG) 0); + break; + + case TXM_TIMER_OBJECT: + default: + + ((TX_TIMER *) object_ptr) -> tx_timer_id = TX_CLEAR_ID; + _tx_timer_created_ptr = TX_NULL; + _tx_timer_created_count = ((ULONG) 0); + break; + } +} + + +/* Break the created list for a type after its first member, and tell the kernel it + is longer than it is. A search bounded only by the count would run off the end of + the chain; this is what makes the second bound observable for every type. */ +static VOID test_object_orphan(VOID *object_ptr, UINT object_type) +{ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + + ((TX_BLOCK_POOL *) object_ptr) -> tx_block_pool_created_next = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 64); + break; + + case TXM_BYTE_POOL_OBJECT: + + ((TX_BYTE_POOL *) object_ptr) -> tx_byte_pool_created_next = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 64); + break; + + case TXM_EVENT_FLAGS_OBJECT: + + ((TX_EVENT_FLAGS_GROUP *) object_ptr) -> tx_event_flags_group_created_next = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 64); + break; + + case TXM_MUTEX_OBJECT: + + ((TX_MUTEX *) object_ptr) -> tx_mutex_created_next = TX_NULL; + _tx_mutex_created_count = ((ULONG) 64); + break; + + case TXM_QUEUE_OBJECT: + + ((TX_QUEUE *) object_ptr) -> tx_queue_created_next = TX_NULL; + _tx_queue_created_count = ((ULONG) 64); + break; + + case TXM_SEMAPHORE_OBJECT: + + ((TX_SEMAPHORE *) object_ptr) -> tx_semaphore_created_next = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 64); + break; + + case TXM_THREAD_OBJECT: + + ((TX_THREAD *) object_ptr) -> tx_thread_created_next = TX_NULL; + _tx_thread_created_count = ((ULONG) 64); + break; + + case TXM_TIMER_OBJECT: + default: + + ((TX_TIMER *) object_ptr) -> tx_timer_created_next = TX_NULL; + _tx_timer_created_count = ((ULONG) 64); + break; + } +} + + +/* Read the control block ID word of an object. */ +static ULONG test_object_id(VOID *object_ptr) +{ + return(*((ULONG *) object_ptr)); +} + + +/* Plant a value at an offset into an allocation, and report what was there. */ +static ULONG test_plant(VOID *object_ptr, ULONG offset, ULONG value) +{ + +ULONG *word_ptr; +ULONG previous; + + + word_ptr = (ULONG *) (VOID *) (((UCHAR *) object_ptr) + offset); + previous = *word_ptr; + *word_ptr = value; + + return(previous); +} + + +/* Bring the pool, the created lists and the modules back to a known state. + + Everything is reset together deliberately. The allocation lists point into the + pool and the created lists point at objects in it, so a case that left either + behind would have the next case reading the wreckage of an earlier one rather + than what it was written to check. */ +static VOID test_reset(TXM_MODULE_INSTANCE *module_a, TXM_MODULE_INSTANCE *module_b) +{ + +UINT index; + + + for (index = 0U; index < (UINT) TEST_POOL_BYTES; index++) + { + test_pool_arena.test_pool_bytes[index] = (UCHAR) 0; + } + + for (index = 0U; index < TEST_MODULE_MEMORY_BYTES; index++) + { + test_module_data.test_data_bytes[index] = (UCHAR) 0; + test_module_code.test_code_bytes[index] = (UCHAR) 0; + } + + test_pool_offset = ((ULONG) 0); + test_released_start = TX_NULL; + test_released_bytes = ((ULONG) 0); + test_releases = ((ULONG) 0); + + _txm_module_manager_object_pool.tx_byte_pool_id = TX_BYTE_POOL_ID; + _txm_module_manager_object_pool.tx_byte_pool_start = test_pool_arena.test_pool_bytes; + _txm_module_manager_object_pool.tx_byte_pool_size = TEST_POOL_BYTES; + _txm_module_manager_object_pool.tx_byte_pool_available = TEST_POOL_BYTES; + _txm_module_manager_object_pool_created = TX_TRUE; + + _tx_block_pool_created_ptr = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 0); + _tx_byte_pool_created_ptr = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 0); + _tx_event_flags_created_ptr = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 0); + _tx_mutex_created_ptr = TX_NULL; + _tx_mutex_created_count = ((ULONG) 0); + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + _tx_semaphore_created_ptr = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 0); + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = ((ULONG) 0); + _tx_timer_created_ptr = TX_NULL; + _tx_timer_created_count = ((ULONG) 0); + + module_a -> txm_module_instance_object_list_count = ((ULONG) 0); + module_a -> txm_module_instance_object_list_head = TX_NULL; + module_b -> txm_module_instance_object_list_count = ((ULONG) 0); + module_b -> txm_module_instance_object_list_head = TX_NULL; + + /* The requesting thread belongs to module A throughout. It is not in the pool + and not on a created list, so it is nothing the cases below can find. */ + test_current_thread.tx_thread_module_instance_ptr = module_a; + _tx_thread_current_ptr = &test_current_thread; +} + + +/* Allocate object memory for a module through the real manager path. */ +static VOID *test_allocate(TXM_MODULE_INSTANCE *module_instance, ULONG object_size) +{ + +VOID *object_ptr; +UINT status; + + + object_ptr = TX_NULL; + status = _txm_module_manager_object_allocate(&object_ptr, object_size, module_instance); + + if (status != TX_SUCCESS) + { + printf("FAIL: the modelled pool refused an allocation of %lu bytes (status %u)\n", + (unsigned long) object_size, status); + test_failures++; + + return(TX_NULL); + } + + return(object_ptr); +} + + +/* Allocate and create one object of a type, the way a module does. */ +static VOID *test_allocate_and_create(TXM_MODULE_INSTANCE *module_instance, const TEST_OBJECT_KIND *kind) +{ + +VOID *object_ptr; + + + object_ptr = test_allocate(module_instance, kind -> test_kind_size); + + if (object_ptr != TX_NULL) + { + test_object_create(object_ptr, kind -> test_kind_type); + } + + return(object_ptr); +} + + +/* Ask the manager to give an address back, and report what it said. Whatever it + decided, it must have left the interrupt lock as it found it. */ +static ULONG test_deallocate(VOID *object_ptr) +{ + +ULONG status; + + + test_interrupt_disable_depth = 0U; + test_interrupt_disable_max_depth = 0U; + test_interrupt_restore_underflows = 0U; + + status = (ULONG) _txm_module_manager_object_deallocate(object_ptr); + + if ((test_interrupt_disable_depth != 0U) || (test_interrupt_restore_underflows != 0U)) + { + printf("FAIL: deallocation left the interrupt lock unbalanced (depth %u, underflows %u)\n", + test_interrupt_disable_depth, test_interrupt_restore_underflows); + test_failures++; + } + + return(status); +} + + +/* Ask the manager whether a live kernel object is at an address, with the same + accounting. */ +static ULONG test_live_check(VOID *object_ptr) +{ + +ULONG status; + + + test_interrupt_disable_depth = 0U; + test_interrupt_disable_max_depth = 0U; + test_interrupt_restore_underflows = 0U; + + status = (ULONG) _txm_module_manager_live_object_check((ALIGN_TYPE) object_ptr); + + if ((test_interrupt_disable_depth != 0U) || (test_interrupt_restore_underflows != 0U)) + { + printf("FAIL: the liveness check left the interrupt lock unbalanced (depth %u, underflows %u)\n", + test_interrupt_disable_depth, test_interrupt_restore_underflows); + test_failures++; + } + + return(status); +} + + +int main(void) +{ + +TXM_MODULE_INSTANCE module_a; +TXM_MODULE_INSTANCE module_b; +const TEST_OBJECT_KIND *kind; +const TEST_OBJECT_KIND *other_kind; +VOID *object; +VOID *other_object; +VOID *raw_object; +VOID *reused_object; +ULONG index; +ULONG other_index; +ULONG saved; +ULONG status; +char description[160]; + + + /* Report expectations before anything can crash, so that a case that brings + the process down is still preceded by everything that passed. */ + setvbuf(stdout, TX_NULL, _IONBF, 0); + + test_failures = 0U; + test_checks = ((ULONG) 0); + + /* Set up two memory-protected modules. Module A does the asking throughout; + module B is there to own allocations A did not make. */ + module_a.txm_module_instance_property_flags = TXM_MODULE_MEMORY_PROTECTION; + module_a.txm_module_instance_code_start = (VOID *) test_module_code.test_code_bytes; + module_a.txm_module_instance_code_end = (VOID *) &test_module_code.test_code_bytes[TEST_MODULE_MEMORY_BYTES - 1U]; + module_a.txm_module_instance_data_start = (VOID *) test_module_data.test_data_bytes; + module_a.txm_module_instance_data_end = (VOID *) &test_module_data.test_data_bytes[TEST_MODULE_MEMORY_BYTES - 1U]; + + module_b = module_a; + + /**********************************************************************/ + /* The reported call: giving back the memory of a live object. */ + /**********************************************************************/ + + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, kind); + + (void) snprintf(description, sizeof(description), + "a live %s is on the created list before anything is asked", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_TRUE); + + /* The scan has to have run with interrupts disabled, which is the + protection the created lists are maintained under. */ + test_expect("...found with interrupts disabled, one deep", + (ULONG) test_interrupt_disable_max_depth, ((ULONG) 1)); + + status = test_deallocate(object); + + (void) snprintf(description, sizeof(description), + "the memory of a live %s is not given back", kind -> test_kind_name); + test_expect(description, status, (ULONG) TX_DELETE_ERROR); + + test_expect("...nothing was released to the pool", test_releases, ((ULONG) 0)); + + test_expect("...the allocation is still on the module's list", + module_a.txm_module_instance_object_list_count, ((ULONG) 1)); + + test_expect("...at the head of it", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), + (ULONG) TX_TRUE); + + (void) snprintf(description, sizeof(description), + "...the %s still carries its control block ID", kind -> test_kind_name); + test_expect(description, test_object_id(object), kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "...and is still a live %s", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_TRUE); + + /* Deleting it is what makes the memory releasable, and the release the + delete dispatchers perform after a successful delete then goes through. */ + test_object_delete(object, kind -> test_kind_type); + + (void) snprintf(description, sizeof(description), + "a deleted %s is no longer live", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_FALSE); + + test_release_size(kind -> test_kind_size); + status = test_deallocate(object); + + test_expect("and its memory is given back", status, (ULONG) TX_SUCCESS); + + test_expect("...leaving the module's allocation list empty", + module_a.txm_module_instance_object_list_count, ((ULONG) 0)); + + /* The address is free to come back now, which is what the kernel would + have been sharing with the next owner had the live object been freed. */ + reused_object = test_allocate(&module_a, kind -> test_kind_size); + + test_expect("...and the address free to be handed out again", + (ULONG) (reused_object == object), (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* Storage that is not an object is still released. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* An allocation that was never made into an object. This is what a module has + after a create that failed or was abandoned, and releasing it is the reason + the request exists at all. */ + raw_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("an uncreated allocation holds no live object", + test_live_check(raw_object), (ULONG) TX_FALSE); + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("and its memory is given back", + test_deallocate(raw_object), (ULONG) TX_SUCCESS); + test_expect("...leaving the module's allocation list empty", + module_a.txm_module_instance_object_list_count, ((ULONG) 0)); + + /* An allocation carrying nothing but the value of a control block ID. A + control block ID is not evidence that an object is there, and refusing on + one would strand memory a module is entitled to have back. */ + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + raw_object = test_allocate(&module_a, kind -> test_kind_size); + (VOID) test_plant(raw_object, ((ULONG) 0), kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "an uncreated allocation carrying a %s ID holds no live object", kind -> test_kind_name); + test_expect(description, test_live_check(raw_object), (ULONG) TX_FALSE); + + test_release_size(kind -> test_kind_size); + + test_expect("...and its memory is given back", + test_deallocate(raw_object), (ULONG) TX_SUCCESS); + } + + /**********************************************************************/ + /* The allocation size is not what decides it. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* A module running without memory protection creates objects through no + size-checked path, so an object can be at the start of an allocation far + larger than its control block. Deciding which created lists to search from + the size of the allocation would miss it. */ + object = test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); + test_object_create(object, TXM_QUEUE_OBJECT); + + test_expect("a queue at the start of a thread-sized allocation is live", + test_live_check(object), (ULONG) TX_TRUE); + test_expect("and the memory is not given back", + test_deallocate(object), (ULONG) TX_DELETE_ERROR); + test_expect("...with nothing released to the pool", test_releases, ((ULONG) 0)); + + /**********************************************************************/ + /* Only the exact address of an object counts. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + kind = &test_object_kinds[6]; + object = test_allocate_and_create(&module_a, kind); + + /* Every aligned interior offset of a live object, with that object's own ID + planted at the offset. None of them is the address of an object. */ + for (index = (ULONG) sizeof(ULONG); index < kind -> test_kind_size; index = index + ((ULONG) sizeof(ULONG))) + { + saved = test_plant(object, index, kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "an address %lu bytes into a live thread holds no live object", (unsigned long) index); + test_expect(description, test_live_check((VOID *) (((UCHAR *) object) + index)), (ULONG) TX_FALSE); + + (VOID) test_plant(object, index, saved); + } + + test_expect("the address one past a live thread holds no live object", + test_live_check((VOID *) (((UCHAR *) object) + kind -> test_kind_size)), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* Every type is searched, and each type only finds its own. */ + /**********************************************************************/ + + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + /* One object of this type, and one allocation of every other type's size + that was never created. Only the created one is found, whatever ID the + others are carrying. */ + object = test_allocate_and_create(&module_a, kind); + + for (other_index = ((ULONG) 0); other_index < (ULONG) TEST_OBJECT_KIND_COUNT; other_index++) + { + if (other_index == index) + { + continue; + } + + other_kind = &test_object_kinds[other_index]; + other_object = test_allocate(&module_a, other_kind -> test_kind_size); + (VOID) test_plant(other_object, ((ULONG) 0), other_kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "with a live %s created, an uncreated %s is not found", + kind -> test_kind_name, other_kind -> test_kind_name); + test_expect(description, test_live_check(other_object), (ULONG) TX_FALSE); + } + + (void) snprintf(description, sizeof(description), + "and the live %s is", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* Liveness is the kernel's record, not the pool's. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* An object the application created lives outside the pool, and the manager + has no allocation record of it. The kernel created list is the only record + there is, and it is the record this consults. */ + test_object_create(&test_host_queue, TXM_QUEUE_OBJECT); + + test_expect("an application-owned queue outside the pool is live", + test_live_check(&test_host_queue), (ULONG) TX_TRUE); + + test_object_delete(&test_host_queue, TXM_QUEUE_OBJECT); + + test_expect("and is not once it has been deleted", + test_live_check(&test_host_queue), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* The bounds on the search. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* Three queues, and a created count that says one. A list whose links have + been damaged must not make the scan run past the count the kernel keeps + beside it. */ + object = test_allocate_and_create(&module_a, &test_object_kinds[4]); + other_object = test_allocate_and_create(&module_a, &test_object_kinds[4]); + raw_object = test_allocate_and_create(&module_a, &test_object_kinds[4]); + + test_expect("all three queues are on the list", _tx_queue_created_count, ((ULONG) 3)); + test_expect("the newest is found", test_live_check(raw_object), (ULONG) TX_TRUE); + test_expect("the oldest is found too", test_live_check(object), (ULONG) TX_TRUE); + + _tx_queue_created_count = ((ULONG) 1); + + test_expect("with the count saying one, the head is still found", + test_live_check(raw_object), (ULONG) TX_TRUE); + test_expect("...but the second member is not walked to", + test_live_check(other_object), (ULONG) TX_FALSE); + test_expect("...nor the third", + test_live_check(object), (ULONG) TX_FALSE); + + /* A count larger than the list. The walk has to stop at the end of the chain + as well as at the count. */ + _tx_queue_created_count = ((ULONG) 64); + ((TX_QUEUE *) raw_object) -> tx_queue_created_next = TX_NULL; + + test_expect("a count larger than the list does not run the scan off the end", + test_live_check(&test_host_queue), (ULONG) TX_FALSE); + + /* An empty list is the ordinary state of most types on most systems. */ + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + + test_expect("nothing is live once every list is empty", + test_live_check(raw_object), (ULONG) TX_FALSE); + + /* The same bound, for every type: a chain that ends before the count does. */ + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, kind); + test_object_orphan(object, kind -> test_kind_type); + + (void) snprintf(description, sizeof(description), + "a %s list that ends before its count does not run the scan off the end", + kind -> test_kind_name); + test_expect(description, test_live_check(&test_host_queue), (ULONG) TX_FALSE); + + (void) snprintf(description, sizeof(description), + "...and the %s at its head is still found", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* Allocations belonging to another module. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* Module B's live object. Module A is refused, and the refusal is the + ownership one: whether A may operate on B's objects at all is a separate + question, and this request never reaches the liveness one. */ + object = test_allocate_and_create(&module_b, &test_object_kinds[5]); + + test_expect("module A cannot give back module B's live allocation", + test_deallocate(object), (ULONG) TX_PTR_ERROR); + test_expect("...and B's allocation list is untouched", + module_b.txm_module_instance_object_list_count, ((ULONG) 1)); + test_expect("...with nothing released to the pool", test_releases, ((ULONG) 0)); + + /* And B's uncreated storage, which A is refused for the same reason. */ + raw_object = test_allocate(&module_b, (ULONG) sizeof(TX_QUEUE)); + + test_expect("module A cannot give back module B's uncreated allocation", + test_deallocate(raw_object), (ULONG) TX_PTR_ERROR); + test_expect("...and B's allocation list still holds both", + module_b.txm_module_instance_object_list_count, ((ULONG) 2)); + + /* B can give its own uncreated storage back, so the ownership test has not + been turned into a refusal of everything. */ + test_current_thread.tx_thread_module_instance_ptr = &module_b; + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("module B can give back its own uncreated allocation", + test_deallocate(raw_object), (ULONG) TX_SUCCESS); + test_expect("...but not its own live object", + test_deallocate(object), (ULONG) TX_DELETE_ERROR); + + test_current_thread.tx_thread_module_instance_ptr = &module_a; + + /**********************************************************************/ + /* An address that is not the start of one of this module's allocations.*/ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + /* An address inside an allocation names none of this module's allocations. + The search establishes that without reading the words in front of the + address, so an interior address is refused rather than taken for a header. */ + test_expect("an address inside an allocation is refused as naming no allocation", + test_deallocate((VOID *) (((UCHAR *) object) + sizeof(ULONG))), (ULONG) TX_PTR_ERROR); + + test_expect("...leaving the module's allocation list as it was", + module_a.txm_module_instance_object_list_count, ((ULONG) 1)); + + /**********************************************************************/ + /* Types the manager does not know. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, &test_object_kinds[4]); + + /* The per-type check is asked directly here, because the search over the + types the manager knows can never present it with one it does not. A + kernel stack allocation is the case that exists: the manager allocates it + from the same pool and gives it a type of its own, and there is no created + list for it. */ + test_expect("a kernel stack is not a type with a created list", + (ULONG) _txm_module_manager_created_object_type_check((ALIGN_TYPE) object, + (UINT) TXM_THREAD_KERNEL_STACK_OBJECT), + (ULONG) TX_FALSE); + + test_expect("nor is a type of zero", + (ULONG) _txm_module_manager_created_object_type_check((ALIGN_TYPE) object, 0U), + (ULONG) TX_FALSE); + + test_expect("and the live queue is still found by the search", + test_live_check(object), (ULONG) TX_TRUE); + + /**********************************************************************/ + /* Releasing one allocation out of several. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* Allocations are appended behind the head, so the first one made is the + head. Releasing it has to move the head on rather than leave it pointing + at memory that has gone back to the pool. */ + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + other_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("the first allocation is the list head", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), + (ULONG) TX_TRUE); + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("releasing the head allocation succeeds", + test_deallocate(object), (ULONG) TX_SUCCESS); + test_expect("...leaving one allocation on the list", + module_a.txm_module_instance_object_list_count, ((ULONG) 1)); + test_expect("...and the head moved on to it", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) other_object) - 1)), + (ULONG) TX_TRUE); + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("releasing the last allocation succeeds", + test_deallocate(other_object), (ULONG) TX_SUCCESS); + test_expect("...emptying the list", + module_a.txm_module_instance_object_list_count, ((ULONG) 0)); + test_expect("...and clearing its head", + (ULONG) (module_a.txm_module_instance_object_list_head == TX_NULL), (ULONG) TX_TRUE); + + /* Asking for the same address again. The header in front of it still names this + module, because nothing has overwritten it, so the empty allocation list is + what has to refuse the second release rather than the owner test. */ + test_expect("releasing the same address a second time is refused", + test_deallocate(other_object), (ULONG) TX_PTR_ERROR); + + /* An address with no room for a header in front of it anywhere in the address + space. The header pointer is null, and the address itself is never read. */ + test_expect("an address whose header would be at zero is refused", + test_deallocate((VOID *) ((ALIGN_TYPE) sizeof(TXM_MODULE_ALLOCATED_OBJECT))), + (ULONG) TX_PTR_ERROR); + + /**********************************************************************/ + /* An object pool that was never created. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + _txm_module_manager_object_pool_created = TX_FALSE; + + test_expect("and the deallocation reports the feature is not available", + test_deallocate((VOID *) test_pool_arena.test_pool_bytes), (ULONG) TX_NOT_AVAILABLE); + + _txm_module_manager_object_pool_created = TX_TRUE; + + /**********************************************************************/ + /* What the whole run has to have held. */ + /**********************************************************************/ + + test_expect("every case ran", (ULONG) (test_checks > ((ULONG) 100)), (ULONG) TX_TRUE); + + if (test_failures == 0U) + { + printf("SUCCESS! %lu expectations\n", (unsigned long) test_checks); + return(0); + } + + printf("ERROR: %u expectation(s) failed of %lu\n", test_failures, (unsigned long) test_checks); + return(1); +} diff --git a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c index ca583956..576ed532 100644 --- a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c +++ b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c @@ -854,26 +854,33 @@ char description[128]; test_expect("a live queue is accepted before anything is given back", test_authenticate(&module_a, object, TXM_QUEUE_OBJECT), (ULONG) TX_TRUE); - /* Give the memory back without deleting the object first. The manager stops - vouching for the control block at the moment it stops owning the memory, so - the address is refused even though the created list has not been told. */ + /* Memory holding a live object is not given back at all. The object stays + created, the allocation stays owned, and the address stays authentic, so + the state this once had to defend against -- an object on the created list + whose memory the manager no longer owns -- cannot be reached. */ _tx_thread_current_ptr = (TX_THREAD *) test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); _tx_thread_current_ptr -> tx_thread_module_instance_ptr = &module_a; + status = _txm_module_manager_object_deallocate(object); + test_expect("memory holding a live object is not given back", (ULONG) status, (ULONG) TX_DELETE_ERROR); + + test_expect("and the live object is still accepted afterwards", + test_authenticate(&module_a, object, TXM_QUEUE_OBJECT), (ULONG) TX_TRUE); + + /* Deleted first, the same memory is given back, and the address comes round + again as a fresh, raw allocation. It is once again an exact allocation start + of the right size, and the ID of the object that used to be there can be + written back into it by the module that now owns it, so the created list is + the only thing that refuses it. */ + test_object_delete(object, kind -> test_kind_type); test_release_size(kind -> test_kind_size); status = _txm_module_manager_object_deallocate(object); - test_expect("the object memory is given back", (ULONG) status, (ULONG) TX_SUCCESS); + test_expect("a deleted object's memory is given back", (ULONG) status, (ULONG) TX_SUCCESS); - test_expect("an address whose memory was given back without a delete is refused", - test_authenticate(&module_a, object, TXM_QUEUE_OBJECT), (ULONG) TX_FALSE); - - /* The same address now comes back as a fresh, raw allocation. It is once - again an exact allocation start of the right size, and it is still on the - created list, so nothing but the cleared ID stands between it and being - taken for the object that used to be there. */ raw_object = test_allocate(&module_a, kind -> test_kind_size); test_expect("the freed address is handed out again", (ULONG) (raw_object == object), (ULONG) TX_TRUE); + (VOID) test_plant(raw_object, ((ULONG) 0), kind -> test_kind_id); test_expect("and is not accepted as the object that used to be there", test_authenticate(&module_a, raw_object, TXM_QUEUE_OBJECT), (ULONG) TX_FALSE);