/*************************************************************************** * 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 Component */ /** */ /** FreeRTOS compatibility layer, synchronisation object accounting */ /** */ /**************************************************************************/ /* Semaphores, mutexes, event groups and timers each take a single descriptor allocation and then create one kernel object. Every one of them must give the descriptor back when that kernel object cannot be created. */ #include "txfr_test_harness.h" #include "semphr.h" #include "event_groups.h" #include "timers.h" static void test_timer_callback(TimerHandle_t timer) { (void)timer; } void txfr_test_body(void) { SemaphoreHandle_t semaphore; EventGroupHandle_t event_group; TimerHandle_t timer; TXFR_COUNTERS counters; /* Counting semaphore. */ txfr_test_account_start(TXFR_INJECT_NONE, 0); semaphore = xSemaphoreCreateCounting(4u, 0u); txfr_test_account_stop(&counters); txfr_test_check("xSemaphoreCreateCounting returns a handle", semaphore != NULL); txfr_test_check_counts("xSemaphoreCreateCounting accounting", &counters, 1, 0, 1, 0); if(semaphore != NULL) { vSemaphoreDelete(semaphore); } txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 1); semaphore = xSemaphoreCreateCounting(4u, 0u); txfr_test_account_stop(&counters); txfr_test_check("xSemaphoreCreateCounting returns NULL on failure", semaphore == NULL); txfr_test_check_counts("counting semaphore failure releases descriptor", &counters, 1, 1, 1, 0); /* Binary semaphore, which shares the same descriptor path. */ txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 1); semaphore = xSemaphoreCreateBinary(); txfr_test_account_stop(&counters); txfr_test_check("xSemaphoreCreateBinary returns NULL on failure", semaphore == NULL); txfr_test_check_counts("binary semaphore failure releases descriptor", &counters, 1, 1, 1, 0); /* Mutex. */ txfr_test_account_start(TXFR_INJECT_NONE, 0); semaphore = xSemaphoreCreateMutex(); txfr_test_account_stop(&counters); txfr_test_check("xSemaphoreCreateMutex returns a handle", semaphore != NULL); txfr_test_check_counts("xSemaphoreCreateMutex accounting", &counters, 1, 0, 1, 0); if(semaphore != NULL) { vSemaphoreDelete(semaphore); } txfr_test_account_start(TXFR_INJECT_MUTEX_CREATE, 1); semaphore = xSemaphoreCreateMutex(); txfr_test_account_stop(&counters); txfr_test_check("xSemaphoreCreateMutex returns NULL on failure", semaphore == NULL); txfr_test_check_counts("mutex failure releases descriptor", &counters, 1, 1, 1, 0); /* Recursive mutex, which differs only in the inheritance argument. */ txfr_test_account_start(TXFR_INJECT_MUTEX_CREATE, 1); semaphore = xSemaphoreCreateRecursiveMutex(); txfr_test_account_stop(&counters); txfr_test_check("xSemaphoreCreateRecursiveMutex returns NULL on failure", semaphore == NULL); txfr_test_check_counts("recursive mutex failure releases descriptor", &counters, 1, 1, 1, 0); /* Event group. */ txfr_test_account_start(TXFR_INJECT_NONE, 0); event_group = xEventGroupCreate(); txfr_test_account_stop(&counters); txfr_test_check("xEventGroupCreate returns a handle", event_group != NULL); txfr_test_check_counts("xEventGroupCreate accounting", &counters, 1, 0, 1, 0); if(event_group != NULL) { vEventGroupDelete(event_group); } txfr_test_account_start(TXFR_INJECT_EVENT_FLAGS_CREATE, 1); event_group = xEventGroupCreate(); txfr_test_account_stop(&counters); txfr_test_check("xEventGroupCreate returns NULL on failure", event_group == NULL); txfr_test_check_counts("event group failure releases descriptor", &counters, 1, 1, 1, 0); /* Timer. */ txfr_test_account_start(TXFR_INJECT_NONE, 0); timer = xTimerCreate("t", 10u, pdFALSE, NULL, test_timer_callback); txfr_test_account_stop(&counters); txfr_test_check("xTimerCreate returns a handle", timer != NULL); txfr_test_check_counts("xTimerCreate accounting", &counters, 1, 0, 1, 0); if(timer != NULL) { (void)xTimerDelete(timer, 0u); } txfr_test_account_start(TXFR_INJECT_TIMER_CREATE, 1); timer = xTimerCreate("t", 10u, pdFALSE, NULL, test_timer_callback); txfr_test_account_stop(&counters); txfr_test_check("xTimerCreate returns NULL on failure", timer == NULL); txfr_test_check_counts("timer failure releases descriptor", &counters, 1, 1, 1, 0); }