Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Os spinlock test #2375

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions testing/ostest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ if(CONFIG_TESTING_OSTEST)
list(APPEND SRCS smp_call.c)
endif()

if(CONFIG_SPINLOCK)
list(APPEND SRCS spinlock.c)
endif()

target_sources(apps PRIVATE ${SRCS})

nuttx_add_application(NAME ostest SRCS ostest_main.c)
Expand Down
4 changes: 4 additions & 0 deletions testing/ostest/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,8 @@ ifeq ($(CONFIG_SMP_CALL),y)
CSRCS += smp_call.c
endif

ifeq ($(CONFIG_SPINLOCK),y)
CSRCS += spinlock.c
endif

include $(APPDIR)/Application.mk
6 changes: 6 additions & 0 deletions testing/ostest/ostest.h
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,12 @@ void priority_inheritance(void);

void sched_lock_test(void);

/* spinlock.c ***************************************************************/

#if defined(CONFIG_SPINLOCK)
void spinlock_test(void);
#endif

/* vfork.c ******************************************************************/

#if defined(CONFIG_ARCH_HAVE_FORK) && defined(CONFIG_SCHED_WAITPID)
Expand Down
6 changes: 6 additions & 0 deletions testing/ostest/ostest_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,12 @@ static int user_main(int argc, char *argv[])
smp_call_test();
#endif

#if defined(CONFIG_SPINLOCK)
printf("\nuser_main: spinlock test\n");
spinlock_test();
check_test_memory_usage();
#endif

/* Compare memory usage at time ostest_main started until
* user_main exits. These should not be identical, but should
* be similar enough that we can detect any serious OS memory
Expand Down
193 changes: 193 additions & 0 deletions testing/ostest/spinlock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/****************************************************************************
* apps/testing/ostest/spinlock.c
*
* 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 <stdio.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/spinlock.h>
#include <stdatomic.h>

#include "ostest.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/****************************************************************************
* Private Data
****************************************************************************/

static spinlock_t lock = SP_UNLOCKED;

static pthread_t g_thread1;
static pthread_t g_thread2;

#ifdef CONFIG_RW_SPINLOCK
static pthread_t g_thread3;
static rwlock_t rw_lock = RW_SP_UNLOCKED;
static atomic_int reader_counter = 0;
#endif

static int g_result = 0;

static FAR void *thread_native_spinlock(FAR FAR void *parameter)
{
int pid = *(FAR int *)parameter;

for (int i = 0; i < 10; i++)
{
printf("pid %d try to get lock g_result:%d\n", pid, g_result);
spin_lock(&lock);
g_result++;
spin_unlock(&lock);
printf("pid %d release lock g_result:%d\n", pid, g_result);
}

return NULL;
}

static FAR void test_native_spinlock(void)
{
int status;
g_result = 0;
lock = SP_UNLOCKED;
spin_initialize(&lock, SP_UNLOCKED);

status = pthread_create(&g_thread1, NULL,
thread_native_spinlock, &g_thread1);
if (status != 0)
{
printf("spinlock_test: ERROR pthread_create failed, status=%d\n",
status);
ASSERT(false);
}

status = pthread_create(&g_thread2, NULL,
thread_native_spinlock, &g_thread2);
if (status != 0)
{
printf("spinlock_test: ERROR pthread_create failed, status=%d\n",
status);
ASSERT(false);
}

pthread_join(g_thread1, NULL);
pthread_join(g_thread2, NULL);

assert(g_result == 20);
}

#if defined(CONFIG_RW_SPINLOCK)
static void FAR *thread_read_spinlock(FAR void *parameter)
{
int pid = *(FAR int *)parameter;
int test;

for (int i = 0; i < 10; ++i)
{
printf("pid %d try to get read lock g_result:%d\n", pid, g_result);
read_lock(&rw_lock);
atomic_fetch_add(&reader_counter, 1);
test = g_result + 1;
atomic_fetch_sub(&reader_counter, 1);
read_unlock(&rw_lock);
printf("pid %d release read lock g_result+1:%d\n", pid, test);
}

return NULL;
}

static void FAR *thread_wrt_spinlock(FAR void *parameter)
{
static int writer_counter = 0;
int pid = *(FAR int *)parameter;

for (int i = 0; i < 10; ++i)
{
printf("pid %d try to get write lock g_result:%d\n", pid, g_result);
write_lock(&rw_lock);
writer_counter += 1;
g_result++;
ASSERT(atomic_load(&reader_counter) == 0 && writer_counter == 1);
writer_counter -= 1;
write_unlock(&rw_lock);
printf("pid %d release write lock g_result:%d\n", pid, g_result);
}

return NULL;
}

static FAR void test_rw_spinlock(void)
{
int status;
g_result = 0;
rwlock_init(&rw_lock);

status = pthread_create(&g_thread1, NULL,
thread_read_spinlock, &g_thread1);
if (status != 0)
{
printf("spinlock_test: ERROR pthread_create failed, status=%d\n",
status);
ASSERT(false);
}

status = pthread_create(&g_thread2, NULL,
thread_read_spinlock, &g_thread2);
if (status != 0)
{
printf("spinlock_test: ERROR pthread_create failed, status=%d\n",
status);
ASSERT(false);
}

status = pthread_create(&g_thread3, NULL,
thread_wrt_spinlock, &g_thread3);
if (status != 0)
{
printf("spinlock_test: ERROR pthread_create failed, status=%d\n",
status);
ASSERT(false);
}

pthread_join(g_thread1, NULL);
pthread_join(g_thread2, NULL);
pthread_join(g_thread3, NULL);

assert(g_result == 10);
}
#endif

/****************************************************************************
* Public Functions
****************************************************************************/

void spinlock_test(void)
{
test_native_spinlock();

#if defined(CONFIG_RW_SPINLOCK)
test_rw_spinlock();
#endif
}
Loading