ostest: Implement mutex move test functionality

Add a new test for moving mutexes to verify behavior when a mutex is relocated.
* Introduced mutex_thread_args_t structure for thread arguments
* Created moved_mutex_thread_func to handle mutex operations in threads
* Updated mutex_test to include mutex_move_test for comprehensive testing

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
Huang Qi 2025-03-12 21:51:06 +08:00 committed by Xiang Xiao
parent a8c62307ec
commit 16a16a9543

View file

@ -35,72 +35,236 @@
****************************************************************************/
#define NLOOPS 32
#define NYIELDS 10
/****************************************************************************
* Private Data
* Private Types
****************************************************************************/
static pthread_mutex_t mut;
static volatile int my_mutex = 0;
static unsigned long nloops[2] =
{
0,
0
};
static unsigned long nerrors[2] =
{
0,
0
};
typedef struct
{
pthread_mutex_t *mutex_ptr;
volatile int *mutex_value;
int *nloops;
int *nerrors;
int thread_id;
} mutex_thread_args_t;
/****************************************************************************
* Private Functions
****************************************************************************/
static void *thread_func(FAR void *parameter)
static void *mutex_thread_func(FAR void *parameter)
{
int id = (int)((intptr_t)parameter);
FAR mutex_thread_args_t *args = (FAR mutex_thread_args_t *)parameter;
int id = args->thread_id;
int ndx = id - 1;
int i;
int local_loops = 0;
for (nloops[ndx] = 0; nloops[ndx] < NLOOPS; nloops[ndx]++)
for (local_loops = 0; local_loops < NLOOPS; local_loops++)
{
int status = pthread_mutex_lock(&mut);
int status = pthread_mutex_lock(args->mutex_ptr);
if (status != 0)
{
printf("ERROR thread %d: pthread_mutex_lock failed, status=%d\n",
id, status);
printf("ERROR thread %d: pthread_mutex_lock failed, "
"status=%d\n", id, status);
ASSERT(false);
}
if (my_mutex == 1)
if (*(args->mutex_value) == 1)
{
printf("ERROR thread=%d: "
"my_mutex should be zero, instead my_mutex=%d\n",
id, my_mutex);
"mutex value should be zero, "
"instead mutex value=%d\n",
id, *(args->mutex_value));
ASSERT(false);
nerrors[ndx]++;
args->nerrors[ndx]++;
}
my_mutex = 1;
for (i = 0; i < 10; i++)
*(args->mutex_value) = 1;
for (i = 0; i < NYIELDS; i++)
{
pthread_yield();
}
my_mutex = 0;
*(args->mutex_value) = 0;
status = pthread_mutex_unlock(&mut);
status = pthread_mutex_unlock(args->mutex_ptr);
if (status != 0)
{
printf("ERROR thread %d: pthread_mutex_unlock failed, status=%d\n",
id, status);
printf("ERROR thread %d: pthread_mutex_unlock failed, "
"status=%d\n", id, status);
ASSERT(false);
}
}
args->nloops[ndx] = local_loops;
pthread_exit(NULL);
return NULL; /* Non-reachable -- needed for some compilers */
return NULL;
}
/****************************************************************************
* Name: mutex_move_test
*
* Description:
* Test the mutex move functionality. This test creates a mutex, moves
* it to a new location, and then starts two threads that use the moved
* mutex.
* POSIX specification does not define the behavior of a mutex that is
* moved. This test is intended to verify that the mutex can be moved,
* which is useful for some cases, see the discussion in
* https://github.com/rust-lang/rust/pull/138400
*
****************************************************************************/
static void mutex_move_test(void)
{
pthread_t thread1;
pthread_t thread2;
int status;
pthread_mutex_t initial_mutex;
pthread_mutex_t moved_mutex;
volatile int moved_mutex_value = 0;
int moved_nloops[2] =
{
0,
0
};
int moved_nerrors[2] =
{
0,
0
};
printf("\nTesting moved mutex\n");
/* Allocate and initialize first mutex */
pthread_mutex_init(&initial_mutex, NULL);
/* Copy the mutex to new location */
memcpy(&moved_mutex, &initial_mutex, sizeof(pthread_mutex_t));
/* Destroy the original mutex */
pthread_mutex_destroy(&initial_mutex);
mutex_thread_args_t thread1_args;
mutex_thread_args_t thread2_args;
thread1_args.mutex_ptr = &moved_mutex;
thread1_args.mutex_value = &moved_mutex_value;
thread1_args.nloops = moved_nloops;
thread1_args.nerrors = moved_nerrors;
thread1_args.thread_id = 1;
thread2_args.mutex_ptr = &moved_mutex;
thread2_args.mutex_value = &moved_mutex_value;
thread2_args.nloops = moved_nloops;
thread2_args.nerrors = moved_nerrors;
thread2_args.thread_id = 2;
/* Start two threads using the moved mutex */
printf("Starting moved mutex thread 1\n");
status = pthread_create(&thread1, NULL, mutex_thread_func,
&thread1_args);
if (status != 0)
{
printf("ERROR in moved mutex thread#1 creation\n");
ASSERT(false);
}
printf("Starting moved mutex thread 2\n");
status = pthread_create(&thread2, NULL, mutex_thread_func,
&thread2_args);
if (status != 0)
{
printf("ERROR in moved mutex thread#2 creation\n");
ASSERT(false);
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_mutex_destroy(&moved_mutex);
printf("\t\tThread1\tThread2\n");
printf("\tMoved Loops\t%u\t%u\n", moved_nloops[0], moved_nloops[1]);
printf("\tMoved Errors\t%u\t%u\n", moved_nerrors[0], moved_nerrors[1]);
}
void mutex_simple_test(void)
{
pthread_t thread1;
pthread_t thread2;
int status;
mutex_thread_args_t thread1_args;
mutex_thread_args_t thread2_args;
pthread_mutex_t mut;
volatile int my_mutex = 0;
int nloops[2] =
{
0,
0
};
int nerrors[2] =
{
0,
0
};
/* Initialize the mutex */
printf("Initializing mutex\n");
pthread_mutex_init(&mut, NULL);
/* Set up thread arguments */
thread1_args.mutex_ptr = &mut;
thread1_args.mutex_value = &my_mutex;
thread1_args.nloops = nloops;
thread1_args.nerrors = nerrors;
thread1_args.thread_id = 1;
thread2_args.mutex_ptr = &mut;
thread2_args.mutex_value = &my_mutex;
thread2_args.nloops = nloops;
thread2_args.nerrors = nerrors;
thread2_args.thread_id = 2;
/* Start two thread instances */
printf("Starting thread 1\n");
status = pthread_create(&thread1, NULL, mutex_thread_func, &thread1_args);
if (status != 0)
{
printf("ERROR in thread#1 creation\n");
ASSERT(false);
}
printf("Starting thread 2\n");
status = pthread_create(&thread2, NULL, mutex_thread_func, &thread2_args);
if (status != 0)
{
printf("ERROR in thread#2 creation\n");
ASSERT(false);
}
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
pthread_mutex_destroy(&mut);
printf("\t\tThread1\tThread2\n");
printf("\tLoops\t%u\t%u\n", nloops[0], nloops[1]);
printf("\tErrors\t%u\t%u\n", nerrors[0], nerrors[1]);
}
/****************************************************************************
@ -109,58 +273,6 @@ static void *thread_func(FAR void *parameter)
void mutex_test(void)
{
pthread_t thread1;
pthread_t thread2;
#ifdef SDCC
pthread_addr_t result1;
pthread_addr_t result2;
pthread_attr_t attr;
#endif
int status;
/* Initialize the mutex */
printf("Initializing mutex\n");
pthread_mutex_init(&mut, NULL);
/* Start two thread instances */
printf("Starting thread 1\n");
#ifdef SDCC
pthread_attr_init(&attr);
status = pthread_create(&thread1, &attr, thread_func, (pthread_addr_t)1);
#else
status = pthread_create(&thread1, NULL, thread_func, (pthread_addr_t)1);
#endif
if (status != 0)
{
printf("ERROR in thread#1 creation\n");
ASSERT(false);
}
printf("Starting thread 2\n");
#ifdef SDCC
status = pthread_create(&thread2, &attr, thread_func, (pthread_addr_t)2);
#else
status = pthread_create(&thread2, NULL, thread_func, (pthread_addr_t)2);
#endif
if (status != 0)
{
printf("ERROR in thread#2 creation\n");
ASSERT(false);
}
#ifdef SDCC
pthread_join(thread1, &result1);
pthread_join(thread2, &result2);
#else
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
#endif
pthread_mutex_destroy(&mut);
printf("\t\tThread1\tThread2\n");
printf("\tLoops\t%lu\t%lu\n", nloops[0], nloops[1]);
printf("\tErrors\t%lu\t%lu\n", nerrors[0], nerrors[1]);
mutex_simple_test();
mutex_move_test();
}