/***************************************************************************/ /* 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 */ /***************************************************************************/ /* This test covers basic pthread and synchronisation operation: a pthread runs and reports its own identity, a mutex serialises access to shared state, a semaphore signals between two pthreads, and a join collects the worker's exit value. */ #include #include "tx_api.h" /* The layer ships no semaphore.h; sem_t and the sem_* calls arrive through pthread.h, which pulls in tx_posix.h. */ #include "pthread.h" #define TEST_STACK_BYTES 4096 static ULONG posix_region[192 * 1024 / sizeof(ULONG)]; static pthread_t worker; static pthread_attr_t worker_attr; static pthread_t driver; static pthread_attr_t driver_attr; static pthread_mutex_t guard; static sem_t handoff; static volatile INT shared_counter; static pthread_t worker_self_id; static INT worker_result = 77; extern void test_control_return(UINT status); static VOID *worker_entry(VOID *input); static VOID *driver_entry(VOID *input); /* Define what the initial system looks like. */ #ifdef CTEST void test_application_define(void *first_unused_memory) #else void posix_pthread_basic_application_define(void *first_unused_memory) #endif { struct sched_param param; VOID *storage_ptr; (void) first_unused_memory; storage_ptr = posix_initialize(posix_region); if (pthread_mutex_init(&guard, NULL) != OK) { printf("Running POSIX Pthread Basic Test.................................. ERROR #1\n"); test_control_return(1); } if (sem_init(&handoff, 0, 0) != OK) { printf("Running POSIX Pthread Basic Test.................................. ERROR #2\n"); test_control_return(1); } /* The driver runs below the worker so that the worker reaches its first blocking point before the driver inspects anything. */ pthread_attr_init(&worker_attr); param.sched_priority = 15; pthread_attr_setschedparam(&worker_attr, ¶m); pthread_attr_setstackaddr(&worker_attr, storage_ptr); storage_ptr = (ULONG *) storage_ptr + (TEST_STACK_BYTES / sizeof(ULONG)); pthread_attr_init(&driver_attr); param.sched_priority = 10; pthread_attr_setschedparam(&driver_attr, ¶m); pthread_attr_setstackaddr(&driver_attr, storage_ptr); if (pthread_create(&worker, &worker_attr, worker_entry, NULL) != OK) { printf("Running POSIX Pthread Basic Test.................................. ERROR #3\n"); test_control_return(1); } if (pthread_create(&driver, &driver_attr, driver_entry, NULL) != OK) { printf("Running POSIX Pthread Basic Test.................................. ERROR #4\n"); test_control_return(1); } } static VOID *worker_entry(VOID *input) { INT i; (void) input; /* Record what this pthread believes its own ID to be, for the driver to compare against the ID pthread_create() handed back. */ worker_self_id = pthread_self(); for (i = 0; i < 100; i++) { pthread_mutex_lock(&guard); shared_counter++; pthread_mutex_unlock(&guard); } /* Hand control to the driver. */ sem_post(&handoff); return ((VOID *) &worker_result); } static VOID *driver_entry(VOID *input) { VOID *exit_value; (void) input; printf("Running POSIX Pthread Basic Test.................................. "); /* Wait for the worker to finish its counting. */ if (sem_wait(&handoff) != OK) { printf("ERROR #5\n"); test_control_return(1); } if (shared_counter != 100) { printf("ERROR #6\n"); test_control_return(1); } if (worker_self_id != worker) { printf("ERROR #7\n"); test_control_return(1); } exit_value = NULL; if (pthread_join(worker, &exit_value) != OK) { printf("ERROR #8\n"); test_control_return(1); } if (exit_value != (VOID *) &worker_result) { printf("ERROR #9\n"); test_control_return(1); } if (pthread_mutex_destroy(&guard) != OK) { printf("ERROR #10\n"); test_control_return(1); } printf("SUCCESS!\n"); test_control_return(0); return (NULL); }