Skip to content

Commit f05b9e3

Browse files
committed
testing/ostest: add test case for task priority change with locked scheduler
Signed-off-by: Petro Karashchenko <[email protected]>
1 parent 5d4c9eb commit f05b9e3

File tree

4 files changed

+261
-6
lines changed

4 files changed

+261
-6
lines changed

testing/ostest/Makefile

+8-6
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,14 @@ endif
105105
ifeq ($(CONFIG_SCHED_WORKQUEUE),y)
106106
CSRCS += wqueue.c
107107
endif
108+
109+
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
110+
CSRCS += prioinherit.c
111+
endif
112+
113+
ifneq ($(CONFIG_ARCH_SIM),y)
114+
CSRCS += schedlock.c
115+
endif
108116
endif # CONFIG_DISABLE_PTHREAD
109117

110118
ifneq ($(CONFIG_DISABLE_MQUEUE),y)
@@ -126,12 +134,6 @@ CSRCS += vfork.c
126134
endif
127135
endif
128136

129-
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
130-
ifeq ($(CONFIG_PRIORITY_INHERITANCE),y)
131-
CSRCS += prioinherit.c
132-
endif # CONFIG_PRIORITY_INHERITANCE
133-
endif # CONFIG_DISABLE_PTHREAD
134-
135137
ifeq ($(CONFIG_ARCH_SETJMP_H),y)
136138
CSRCS += setjmp.c
137139
endif

testing/ostest/ostest.h

+6
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,12 @@ void barrier_test(void);
250250

251251
void priority_inheritance(void);
252252

253+
/* schedlock.c ***************************************************************/
254+
255+
#ifndef CONFIG_ARCH_SIM
256+
void sched_lock_test(void);
257+
#endif
258+
253259
/* vfork.c ******************************************************************/
254260

255261
#if defined(CONFIG_ARCH_HAVE_VFORK) && defined(CONFIG_SCHED_WAITPID)

testing/ostest/ostest_main.c

+6
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,12 @@ static int user_main(int argc, char *argv[])
574574
check_test_memory_usage();
575575
#endif /* CONFIG_PRIORITY_INHERITANCE && !CONFIG_DISABLE_PTHREAD */
576576

577+
#if !defined(CONFIG_ARCH_SIM) && !defined(CONFIG_DISABLE_PTHREAD)
578+
printf("\nuser_main: priority test\n");
579+
sched_lock_test();
580+
check_test_memory_usage();
581+
#endif /* !CONFIG_ARCH_SIM && !CONFIG_DISABLE_PTHREAD */
582+
577583
#if defined(CONFIG_ARCH_HAVE_VFORK) && defined(CONFIG_SCHED_WAITPID)
578584
printf("\nuser_main: vfork() test\n");
579585
vfork_test();

testing/ostest/schedlock.c

+241
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
/****************************************************************************
2+
* apps/testing/ostest/schedlock.c
3+
*
4+
* Licensed to the Apache Software Foundation (ASF) under one or more
5+
* contributor license agreements. See the NOTICE file distributed with
6+
* this work for additional information regarding copyright ownership. The
7+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
8+
* "License"); you may not use this file except in compliance with the
9+
* License. You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16+
* License for the specific language governing permissions and limitations
17+
* under the License.
18+
*
19+
****************************************************************************/
20+
21+
/****************************************************************************
22+
* Included Files
23+
****************************************************************************/
24+
25+
#include <stdio.h>
26+
#include <unistd.h>
27+
#include <pthread.h>
28+
#include <errno.h>
29+
#include <sched.h>
30+
#include <unistd.h>
31+
#include <stdint.h>
32+
33+
#include "ostest.h"
34+
35+
#include <sys/wait.h>
36+
37+
static pthread_t g_lowpri;
38+
static pthread_t g_highpri;
39+
static volatile bool g_locked;
40+
static volatile bool g_pass;
41+
42+
/****************************************************************************
43+
* Private Functions
44+
****************************************************************************/
45+
46+
/****************************************************************************
47+
* Name: highpri_thread
48+
****************************************************************************/
49+
50+
static FAR void *highpri_thread(FAR void *parameter)
51+
{
52+
struct sched_param param;
53+
int policy;
54+
bool self = (bool)(uintptr_t)parameter;
55+
pthread_t thread = self ? 0 : g_lowpri;
56+
57+
usleep(100);
58+
59+
pthread_getschedparam(0, &policy, &param);
60+
if (self)
61+
{
62+
param.sched_priority -= 2;
63+
}
64+
else
65+
{
66+
param.sched_priority += 2;
67+
}
68+
69+
sched_lock();
70+
71+
g_locked = true;
72+
73+
nxsched_set_param(thread, &param);
74+
75+
/* Test pass if g_locked was not cleared by lowpri thread while scheduler
76+
* is locked */
77+
78+
g_pass = g_locked;
79+
80+
sched_unlock();
81+
82+
return NULL;
83+
}
84+
85+
/****************************************************************************
86+
* Name: lowpri_thread
87+
****************************************************************************/
88+
89+
static FAR void *lowpri_thread(FAR void *parameter)
90+
{
91+
/* Wait until highpri thread starts the scheduler lock test */
92+
93+
while (!g_locked)
94+
{
95+
}
96+
97+
g_locked = false;
98+
99+
return NULL;
100+
}
101+
102+
/****************************************************************************
103+
* Public Functions
104+
****************************************************************************/
105+
106+
/****************************************************************************
107+
* Name: sched_lock_test
108+
****************************************************************************/
109+
110+
void sched_lock_test(void)
111+
{
112+
int i;
113+
114+
for (i = 0; i < 2; i++)
115+
{
116+
pthread_attr_t attr;
117+
struct sched_param sparam;
118+
int status;
119+
int highprio;
120+
int lowprio;
121+
#ifdef CONFIG_SMP
122+
cpu_set_t cpu_mask;
123+
124+
CPU_ZERO(&cpu_mask);
125+
CPU_SET(0, &cpu_mask);
126+
#endif
127+
128+
status = sched_getparam(0, &sparam);
129+
if (status != 0)
130+
{
131+
printf("priority: ERROR sched_getparam failed\n");
132+
ASSERT(false);
133+
sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY;
134+
}
135+
136+
highprio = sparam.sched_priority - 2;
137+
lowprio = highprio - 1;
138+
139+
/* Start the low priority thread */
140+
141+
printf("priority: Starting lowpri_thread at %d\n", lowprio);
142+
status = pthread_attr_init(&attr);
143+
if (status != 0)
144+
{
145+
printf("priority: ERROR pthread_attr_init failed, status=%d\n",
146+
status);
147+
ASSERT(false);
148+
}
149+
150+
sparam.sched_priority = lowprio;
151+
status = pthread_attr_setschedparam(&attr, &sparam);
152+
if (status != OK)
153+
{
154+
printf("priority: "
155+
"ERROR pthread_attr_setschedparam failed, status=%d\n",
156+
status);
157+
ASSERT(false);
158+
}
159+
else
160+
{
161+
printf("priority: Set lowpri_thread priority to %d\n",
162+
sparam.sched_priority);
163+
}
164+
165+
#ifdef CONFIG_SMP
166+
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpu_mask);
167+
#endif
168+
169+
FFLUSH();
170+
171+
status = pthread_create(&g_lowpri, &attr, lowpri_thread, NULL);
172+
if (status != 0)
173+
{
174+
printf("priority: ERROR pthread_create failed, status=%d\n",
175+
status);
176+
ASSERT(false);
177+
}
178+
179+
/* Start the high priority thread */
180+
181+
printf("priority: Starting highpri_thread at %d\n", highprio);
182+
status = pthread_attr_init(&attr);
183+
if (status != 0)
184+
{
185+
printf("priority: ERROR pthread_attr_init failed, status=%d\n",
186+
status);
187+
ASSERT(false);
188+
}
189+
190+
sparam.sched_priority = highprio;
191+
status = pthread_attr_setschedparam(&attr, &sparam);
192+
if (status != OK)
193+
{
194+
printf("priority: "
195+
"ERROR pthread_attr_setschedparam failed, status=%d\n",
196+
status);
197+
ASSERT(false);
198+
}
199+
else
200+
{
201+
printf("priority: Set highpri_thread priority to %d\n",
202+
sparam.sched_priority);
203+
}
204+
205+
#ifdef CONFIG_SMP
206+
pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpu_mask);
207+
#endif
208+
209+
FFLUSH();
210+
211+
status = pthread_create(&g_highpri, &attr, highpri_thread,
212+
(FAR void *)(uintptr_t)(i == 0));
213+
if (status != 0)
214+
{
215+
printf("priority: ERROR pthread_create failed, status=%d\n",
216+
status);
217+
ASSERT(false);
218+
}
219+
220+
printf("priority: Waiting...\n");
221+
sleep(1);
222+
223+
waitpid(g_highpri, &status, 0);
224+
waitpid(g_lowpri, &status, 0);
225+
226+
if (!g_pass)
227+
{
228+
printf("priority: ERROR: FAIL pre-emption occurred"
229+
"while scheduler was locked.\n");
230+
ASSERT(false);
231+
}
232+
else
233+
{
234+
printf("priority: PASSED No pre-emption occurred"
235+
"while scheduler was locked.\n");
236+
}
237+
}
238+
239+
printf("priority: Finished\n");
240+
FFLUSH();
241+
}

0 commit comments

Comments
 (0)