mirror of
https://github.com/apache/nuttx-apps.git
synced 2025-07-04 11:04:13 +08:00

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>
279 lines
7.4 KiB
C
279 lines
7.4 KiB
C
/****************************************************************************
|
|
* apps/testing/ostest/mutex.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <assert.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
|
|
#include "ostest.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
#define NLOOPS 32
|
|
#define NYIELDS 10
|
|
|
|
/****************************************************************************
|
|
* Private Types
|
|
****************************************************************************/
|
|
|
|
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 *mutex_thread_func(FAR void *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 (local_loops = 0; local_loops < NLOOPS; local_loops++)
|
|
{
|
|
int status = pthread_mutex_lock(args->mutex_ptr);
|
|
if (status != 0)
|
|
{
|
|
printf("ERROR thread %d: pthread_mutex_lock failed, "
|
|
"status=%d\n", id, status);
|
|
ASSERT(false);
|
|
}
|
|
|
|
if (*(args->mutex_value) == 1)
|
|
{
|
|
printf("ERROR thread=%d: "
|
|
"mutex value should be zero, "
|
|
"instead mutex value=%d\n",
|
|
id, *(args->mutex_value));
|
|
ASSERT(false);
|
|
args->nerrors[ndx]++;
|
|
}
|
|
|
|
*(args->mutex_value) = 1;
|
|
for (i = 0; i < NYIELDS; i++)
|
|
{
|
|
pthread_yield();
|
|
}
|
|
|
|
*(args->mutex_value) = 0;
|
|
|
|
status = pthread_mutex_unlock(args->mutex_ptr);
|
|
if (status != 0)
|
|
{
|
|
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;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* 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]);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
void mutex_test(void)
|
|
{
|
|
mutex_simple_test();
|
|
mutex_move_test();
|
|
}
|