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