Skip to content

Commit

Permalink
testing/ostest: add test case for task priority change with locked sc…
Browse files Browse the repository at this point in the history
…heduler

Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
  • Loading branch information
pkarashchenko committed Apr 11, 2023
1 parent f2ba02c commit ce67d71
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 6 deletions.
14 changes: 8 additions & 6 deletions testing/ostest/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ endif
ifeq ($(CONFIG_SCHED_WORKQUEUE),y)
CSRCS += wqueue.c
endif

ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
CSRCS += prioinherit.c
endif

ifneq ($(CONFIG_ARCH_SIM),y)
CSRCS += schedlock.c
endif
endif # CONFIG_DISABLE_PTHREAD

ifneq ($(CONFIG_DISABLE_MQUEUE),y)
Expand All @@ -118,12 +126,6 @@ CSRCS += vfork.c
endif
endif

ifneq ($(CONFIG_DISABLE_PTHREAD),y)
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
CSRCS += prioinherit.c
endif # CONFIG_PRIORITY_INHERITANCE
endif # CONFIG_DISABLE_PTHREAD

ifeq ($(CONFIG_ARCH_SETJMP_H),y)
CSRCS += setjmp.c
endif
Expand Down
6 changes: 6 additions & 0 deletions testing/ostest/ostest.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,12 @@ void barrier_test(void);

void priority_inheritance(void);

/* schedlock.c ***************************************************************/

#ifndef CONFIG_ARCH_SIM
void sched_lock_test(void);
#endif

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

#if defined(CONFIG_ARCH_HAVE_VFORK) && 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 @@ -564,6 +564,12 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_PTHREAD */

#if !defined(CONFIG_ARCH_SIM) && !defined(CONFIG_DISABLE_PTHREAD)
printf("\nuser_main: priority test\n");
sched_lock_test();
check_test_memory_usage();
#endif /* !CONFIG_ARCH_SIM && !CONFIG_DISABLE_PTHREAD */

#if defined(CONFIG_ARCH_HAVE_VFORK) && defined(CONFIG_SCHED_WAITPID)
printf("\nuser_main: vfork() test\n");
vfork_test();
Expand Down
241 changes: 241 additions & 0 deletions testing/ostest/schedlock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
/****************************************************************************
* apps/testing/ostest/schedlock.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 <unistd.h>
#include <pthread.h>
#include <errno.h>
#include <sched.h>
#include <unistd.h>
#include <stdint.h>

#include "ostest.h"

#include <sys/wait.h>

static pthread_t g_lowpri;
static pthread_t g_highpri;
static volatile bool g_locked;
static volatile bool g_pass;

/****************************************************************************
* Private Functions
****************************************************************************/

/****************************************************************************
* Name: highpri_thread
****************************************************************************/

static FAR void *highpri_thread(FAR void *parameter)
{
struct sched_param param;
int policy;
bool self = (bool)(uintptr_t)parameter;
pthread_t thread = self ? 0 : g_lowpri;

usleep(100);

pthread_getschedparam(0, &policy, &param);
if (self)
{
param.sched_priority -= 2;
}
else
{
param.sched_priority += 2;
}

sched_lock();

g_locked = true;

nxsched_set_param(thread, &param);

/* Test pass if g_locked was not cleared by lowpri thread while scheduler
* is locked */

g_pass = g_locked;

sched_unlock();

return NULL;
}

/****************************************************************************
* Name: lowpri_thread
****************************************************************************/

static FAR void *lowpri_thread(FAR void *parameter)
{
/* Wait until highpri thread starts the scheduler lock test */

while (!g_locked)
{
}

g_locked = false;

return NULL;
}

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

/****************************************************************************
* Name: sched_lock_test
****************************************************************************/

void sched_lock_test(void)
{
int i;

for (i = 0; i < 2; i++)
{
pthread_attr_t attr;
struct sched_param sparam;
int status;
int highprio;
int lowprio;
#ifdef CONFIG_SMP
cpu_set_t cpu_mask;

CPU_ZERO(&cpu_mask);
CPU_SET(0, &cpu_mask);
#endif

status = sched_getparam(0, &sparam);
if (status != 0)
{
printf("priority: ERROR sched_getparam failed\n");
ASSERT(false);
sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY;
}

highprio = sparam.sched_priority - 2;
lowprio = highprio - 1;

/* Start the low priority thread */

printf("priority: Starting lowpri_thread at %d\n", lowprio);
status = pthread_attr_init(&attr);
if (status != 0)
{
printf("priority: ERROR pthread_attr_init failed, status=%d\n",
status);
ASSERT(false);
}

sparam.sched_priority = lowprio;
status = pthread_attr_setschedparam(&attr, &sparam);
if (status != OK)
{
printf("priority: "
"ERROR pthread_attr_setschedparam failed, status=%d\n",
status);
ASSERT(false);
}
else
{
printf("priority: Set lowpri_thread priority to %d\n",
sparam.sched_priority);
}

#ifdef CONFIG_SMP
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpu_mask);
#endif

FFLUSH();

status = pthread_create(&g_lowpri, &attr, lowpri_thread, NULL);
if (status != 0)
{
printf("priority: ERROR pthread_create failed, status=%d\n",
status);
ASSERT(false);
}

/* Start the high priority thread */

printf("priority: Starting highpri_thread at %d\n", highprio);
status = pthread_attr_init(&attr);
if (status != 0)
{
printf("priority: ERROR pthread_attr_init failed, status=%d\n",
status);
ASSERT(false);
}

sparam.sched_priority = highprio;
status = pthread_attr_setschedparam(&attr, &sparam);
if (status != OK)
{
printf("priority: "
"ERROR pthread_attr_setschedparam failed, status=%d\n",
status);
ASSERT(false);
}
else
{
printf("priority: Set highpri_thread priority to %d\n",
sparam.sched_priority);
}

#ifdef CONFIG_SMP
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpu_mask);
#endif

FFLUSH();

status = pthread_create(&g_highpri, &attr, highpri_thread,
(FAR void *)(uintptr_t)(i == 0));
if (status != 0)
{
printf("priority: ERROR pthread_create failed, status=%d\n",
status);
ASSERT(false);
}

printf("priority: Waiting...\n");
sleep(1);

waitpid(g_highpri, &status, 0);
waitpid(g_lowpri, &status, 0);

if (!g_pass)
{
printf("priority: ERROR: FAIL pre-emption occurred"
"while scheduler was locked.\n");
ASSERT(false);
}
else
{
printf("priority: PASSED No pre-emption occurred"
"while scheduler was locked.\n");
}
}

printf("priority: Finished\n");
FFLUSH();
}

0 comments on commit ce67d71

Please sign in to comment.