1f08c3bdfSopenharmony_ci/******************************************************************************
2f08c3bdfSopenharmony_ci *
3f08c3bdfSopenharmony_ci *   Copyright © International Business Machines  Corp., 2005, 2008
4f08c3bdfSopenharmony_ci *
5f08c3bdfSopenharmony_ci *   This program is free software;  you can redistribute it and/or modify
6f08c3bdfSopenharmony_ci *   it under the terms of the GNU General Public License as published by
7f08c3bdfSopenharmony_ci *   the Free Software Foundation; either version 2 of the License, or
8f08c3bdfSopenharmony_ci *   (at your option) any later version.
9f08c3bdfSopenharmony_ci *
10f08c3bdfSopenharmony_ci *   This program is distributed in the hope that it will be useful,
11f08c3bdfSopenharmony_ci *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
12f08c3bdfSopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
13f08c3bdfSopenharmony_ci *   the GNU General Public License for more details.
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci *   You should have received a copy of the GNU General Public License
16f08c3bdfSopenharmony_ci *   along with this program;  if not, write to the Free Software
17f08c3bdfSopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18f08c3bdfSopenharmony_ci *
19f08c3bdfSopenharmony_ci * NAME
20f08c3bdfSopenharmony_ci *      testpi-2.c
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci * DESCRIPTION
23f08c3bdfSopenharmony_ci *      This testcase verifies if the low priority SCHED_RR thread can preempt
24f08c3bdfSopenharmony_ci *      the high priority SCHED_RR thread multiple times via priority
25f08c3bdfSopenharmony_ci *      inheritance.
26f08c3bdfSopenharmony_ci *
27f08c3bdfSopenharmony_ci * USAGE:
28f08c3bdfSopenharmony_ci *      Use run_auto.sh script in current directory to build and run test.
29f08c3bdfSopenharmony_ci *
30f08c3bdfSopenharmony_ci * AUTHOR
31f08c3bdfSopenharmony_ci *
32f08c3bdfSopenharmony_ci *
33f08c3bdfSopenharmony_ci * HISTORY
34f08c3bdfSopenharmony_ci *      2010-04-22 Code cleanup and thread synchronization changes by using
35f08c3bdfSopenharmony_ci *		 conditional variables,
36f08c3bdfSopenharmony_ci *		 by Gowrishankar(gowrishankar.m@in.ibm.com).
37f08c3bdfSopenharmony_ci *
38f08c3bdfSopenharmony_ci *****************************************************************************/
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_ci#include <stdio.h>
41f08c3bdfSopenharmony_ci#include <stdlib.h>
42f08c3bdfSopenharmony_ci#include <string.h>
43f08c3bdfSopenharmony_ci#include <sched.h>
44f08c3bdfSopenharmony_ci#include <pthread.h>
45f08c3bdfSopenharmony_ci#include <sys/types.h>
46f08c3bdfSopenharmony_ci#include <sys/syscall.h>
47f08c3bdfSopenharmony_ci#include <unistd.h>
48f08c3bdfSopenharmony_ci#include <librttest.h>
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_cipthread_barrier_t barrier;
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_civoid usage(void)
53f08c3bdfSopenharmony_ci{
54f08c3bdfSopenharmony_ci	rt_help();
55f08c3bdfSopenharmony_ci	printf("testpi-2 specific options:\n");
56f08c3bdfSopenharmony_ci}
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ciint parse_args(int c, char *v)
59f08c3bdfSopenharmony_ci{
60f08c3bdfSopenharmony_ci
61f08c3bdfSopenharmony_ci	int handled = 1;
62f08c3bdfSopenharmony_ci	switch (c) {
63f08c3bdfSopenharmony_ci	case 'h':
64f08c3bdfSopenharmony_ci		usage();
65f08c3bdfSopenharmony_ci		exit(0);
66f08c3bdfSopenharmony_ci	default:
67f08c3bdfSopenharmony_ci		handled = 0;
68f08c3bdfSopenharmony_ci		break;
69f08c3bdfSopenharmony_ci	}
70f08c3bdfSopenharmony_ci	return handled;
71f08c3bdfSopenharmony_ci}
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ciint gettid(void)
74f08c3bdfSopenharmony_ci{
75f08c3bdfSopenharmony_ci	return syscall(__NR_gettid);
76f08c3bdfSopenharmony_ci}
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_citypedef void *(*entrypoint_t) (void *);
79f08c3bdfSopenharmony_cipthread_mutex_t glob_mutex;
80f08c3bdfSopenharmony_cistatic pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
81f08c3bdfSopenharmony_cistatic pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_civoid *func_lowrt(void *arg)
84f08c3bdfSopenharmony_ci{
85f08c3bdfSopenharmony_ci	struct thread *pthr = (struct thread *)arg;
86f08c3bdfSopenharmony_ci	int i, tid = gettid();
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_ci	printf("Thread %d started running with priority %d\n", tid,
89f08c3bdfSopenharmony_ci	       pthr->priority);
90f08c3bdfSopenharmony_ci	pthread_mutex_lock(&glob_mutex);
91f08c3bdfSopenharmony_ci	printf("Thread %d at start pthread pol %d pri %d - Got global lock\n",
92f08c3bdfSopenharmony_ci	       tid, pthr->policy, pthr->priority);
93f08c3bdfSopenharmony_ci	/* Wait for other RT threads to start up */
94f08c3bdfSopenharmony_ci	pthread_barrier_wait(&barrier);
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	/* Wait for the high priority noise thread to start and signal us */
97f08c3bdfSopenharmony_ci	pthread_mutex_lock(&cond_mutex);
98f08c3bdfSopenharmony_ci	pthread_cond_wait(&cond_var, &cond_mutex);
99f08c3bdfSopenharmony_ci	pthread_mutex_unlock(&cond_mutex);
100f08c3bdfSopenharmony_ci
101f08c3bdfSopenharmony_ci	for (i = 0; i < 10000; i++) {
102f08c3bdfSopenharmony_ci		if (i % 100 == 0) {
103f08c3bdfSopenharmony_ci			printf("Thread %d loop %d pthread pol %d pri %d\n",
104f08c3bdfSopenharmony_ci			       tid, i, pthr->policy, pthr->priority);
105f08c3bdfSopenharmony_ci			fflush(NULL);
106f08c3bdfSopenharmony_ci		}
107f08c3bdfSopenharmony_ci		busy_work_ms(1);
108f08c3bdfSopenharmony_ci	}
109f08c3bdfSopenharmony_ci	pthread_mutex_unlock(&glob_mutex);
110f08c3bdfSopenharmony_ci	return NULL;
111f08c3bdfSopenharmony_ci}
112f08c3bdfSopenharmony_ci
113f08c3bdfSopenharmony_civoid *func_rt(void *arg)
114f08c3bdfSopenharmony_ci{
115f08c3bdfSopenharmony_ci	struct thread *pthr = (struct thread *)arg;
116f08c3bdfSopenharmony_ci	int i, tid = gettid();
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	printf("Thread %d started running with prio %d\n", tid, pthr->priority);
119f08c3bdfSopenharmony_ci	pthread_barrier_wait(&barrier);
120f08c3bdfSopenharmony_ci	pthread_mutex_lock(&glob_mutex);
121f08c3bdfSopenharmony_ci	printf("Thread %d at start pthread pol %d pri %d - Got global lock\n",
122f08c3bdfSopenharmony_ci	       tid, pthr->policy, pthr->priority);
123f08c3bdfSopenharmony_ci
124f08c3bdfSopenharmony_ci	/* We just use the mutex as something to slow things down,
125f08c3bdfSopenharmony_ci	 * say who we are and then do nothing for a while.  The aim
126f08c3bdfSopenharmony_ci	 * of this is to show that high priority threads make more
127f08c3bdfSopenharmony_ci	 * progress than lower priority threads..
128f08c3bdfSopenharmony_ci	 */
129f08c3bdfSopenharmony_ci	for (i = 0; i < 1000; i++) {
130f08c3bdfSopenharmony_ci		if (i % 100 == 0) {
131f08c3bdfSopenharmony_ci			printf("Thread %d loop %d pthread pol %d pri %d\n",
132f08c3bdfSopenharmony_ci			       tid, i, pthr->policy, pthr->priority);
133f08c3bdfSopenharmony_ci			fflush(NULL);
134f08c3bdfSopenharmony_ci		}
135f08c3bdfSopenharmony_ci		busy_work_ms(1);
136f08c3bdfSopenharmony_ci	}
137f08c3bdfSopenharmony_ci	pthread_mutex_unlock(&glob_mutex);
138f08c3bdfSopenharmony_ci	return NULL;
139f08c3bdfSopenharmony_ci}
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_civoid *func_noise(void *arg)
142f08c3bdfSopenharmony_ci{
143f08c3bdfSopenharmony_ci	struct thread *pthr = (struct thread *)arg;
144f08c3bdfSopenharmony_ci	int i, tid = gettid();
145f08c3bdfSopenharmony_ci
146f08c3bdfSopenharmony_ci	printf("Noise Thread %d started running with prio %d\n", tid,
147f08c3bdfSopenharmony_ci	       pthr->priority);
148f08c3bdfSopenharmony_ci	pthread_barrier_wait(&barrier);
149f08c3bdfSopenharmony_ci
150f08c3bdfSopenharmony_ci	/* Let others wait at conditional variable */
151f08c3bdfSopenharmony_ci	usleep(1000);
152f08c3bdfSopenharmony_ci
153f08c3bdfSopenharmony_ci	/* Noise thread begins the test */
154f08c3bdfSopenharmony_ci	pthread_mutex_lock(&cond_mutex);
155f08c3bdfSopenharmony_ci	pthread_cond_broadcast(&cond_var);
156f08c3bdfSopenharmony_ci	pthread_mutex_unlock(&cond_mutex);
157f08c3bdfSopenharmony_ci
158f08c3bdfSopenharmony_ci	for (i = 0; i < 10000; i++) {
159f08c3bdfSopenharmony_ci		if (i % 100 == 0) {
160f08c3bdfSopenharmony_ci			printf("Noise Thread %d loop %d pthread pol %d "
161f08c3bdfSopenharmony_ci			       "pri %d\n", tid, i, pthr->policy,
162f08c3bdfSopenharmony_ci			       pthr->priority);
163f08c3bdfSopenharmony_ci			fflush(NULL);
164f08c3bdfSopenharmony_ci		}
165f08c3bdfSopenharmony_ci		busy_work_ms(1);
166f08c3bdfSopenharmony_ci	}
167f08c3bdfSopenharmony_ci	return NULL;
168f08c3bdfSopenharmony_ci}
169f08c3bdfSopenharmony_ci
170f08c3bdfSopenharmony_ci/*
171f08c3bdfSopenharmony_ci * Test pthread creation at different thread priorities.
172f08c3bdfSopenharmony_ci */
173f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
174f08c3bdfSopenharmony_ci{
175f08c3bdfSopenharmony_ci	int i, retc, nopi = 0;
176f08c3bdfSopenharmony_ci	cpu_set_t mask;
177f08c3bdfSopenharmony_ci	CPU_ZERO(&mask);
178f08c3bdfSopenharmony_ci	CPU_SET(0, &mask);
179f08c3bdfSopenharmony_ci	setup();
180f08c3bdfSopenharmony_ci	rt_init("h", parse_args, argc, argv);
181f08c3bdfSopenharmony_ci
182f08c3bdfSopenharmony_ci	retc = pthread_barrier_init(&barrier, NULL, 5);
183f08c3bdfSopenharmony_ci	if (retc) {
184f08c3bdfSopenharmony_ci		printf("pthread_barrier_init failed: %s\n", strerror(retc));
185f08c3bdfSopenharmony_ci		exit(retc);
186f08c3bdfSopenharmony_ci	}
187f08c3bdfSopenharmony_ci
188f08c3bdfSopenharmony_ci	retc = sched_setaffinity(0, sizeof(mask), &mask);
189f08c3bdfSopenharmony_ci	if (retc < 0) {
190f08c3bdfSopenharmony_ci		printf("Main Thread: Can't set affinity: %d %s\n", retc,
191f08c3bdfSopenharmony_ci		       strerror(retc));
192f08c3bdfSopenharmony_ci		exit(-1);
193f08c3bdfSopenharmony_ci	}
194f08c3bdfSopenharmony_ci
195f08c3bdfSopenharmony_ci	for (i = 0; i < argc; i++) {
196f08c3bdfSopenharmony_ci		if (strcmp(argv[i], "nopi") == 0)
197f08c3bdfSopenharmony_ci			nopi = 1;
198f08c3bdfSopenharmony_ci	}
199f08c3bdfSopenharmony_ci
200f08c3bdfSopenharmony_ci	printf("Start %s\n", argv[0]);
201f08c3bdfSopenharmony_ci
202f08c3bdfSopenharmony_ci	if (!nopi)
203f08c3bdfSopenharmony_ci		init_pi_mutex(&glob_mutex);
204f08c3bdfSopenharmony_ci
205f08c3bdfSopenharmony_ci	create_rr_thread(func_lowrt, NULL, 10);
206f08c3bdfSopenharmony_ci	create_rr_thread(func_rt, NULL, 20);
207f08c3bdfSopenharmony_ci	create_fifo_thread(func_rt, NULL, 30);
208f08c3bdfSopenharmony_ci	create_fifo_thread(func_rt, NULL, 40);
209f08c3bdfSopenharmony_ci	create_rr_thread(func_noise, NULL, 40);
210f08c3bdfSopenharmony_ci
211f08c3bdfSopenharmony_ci	printf("Joining threads\n");
212f08c3bdfSopenharmony_ci	join_threads();
213f08c3bdfSopenharmony_ci	printf("Done\n");
214f08c3bdfSopenharmony_ci	printf("Criteria: Low Priority Thread and High Priority Thread "
215f08c3bdfSopenharmony_ci	       "should prempt each other multiple times\n");
216f08c3bdfSopenharmony_ci
217f08c3bdfSopenharmony_ci	pthread_mutex_destroy(&glob_mutex);
218f08c3bdfSopenharmony_ci	pthread_mutex_destroy(&cond_mutex);
219f08c3bdfSopenharmony_ci	pthread_cond_destroy(&cond_var);
220f08c3bdfSopenharmony_ci
221f08c3bdfSopenharmony_ci	return 0;
222f08c3bdfSopenharmony_ci}
223