Home | History | Annotate | Download | only in pi-tests
      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 (at) 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 
     52 void usage(void)
     53 {
     54 	rt_help();
     55 	printf("testpi-2 specific options:\n");
     56 }
     57 
     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 
     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 
     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 
    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 
    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  */
    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