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-3.c
     21  *
     22  * DESCRIPTION
     23  *
     24  *
     25  * USAGE:
     26  *	Use run_auto.sh script in current directory to build and run test.
     27  *
     28  * AUTHOR
     29  *
     30  *
     31  * HISTORY
     32  *
     33  *
     34  *****************************************************************************/
     35 
     36 #include <stdio.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 #include <sched.h>
     40 #include <pthread.h>
     41 #include <sys/types.h>
     42 #include <sys/syscall.h>
     43 #include <unistd.h>
     44 #include <librttest.h>
     45 
     46 void usage(void)
     47 {
     48 	rt_help();
     49 	printf("testpi-3 specific options:\n");
     50 }
     51 
     52 int parse_args(int c, char *v)
     53 {
     54 
     55 	int handled = 1;
     56 	switch (c) {
     57 	case 'h':
     58 		usage();
     59 		exit(0);
     60 	default:
     61 		handled = 0;
     62 		break;
     63 	}
     64 	return handled;
     65 }
     66 
     67 int gettid(void)
     68 {
     69 	return syscall(__NR_gettid);
     70 }
     71 
     72 typedef void *(*entrypoint_t) (void *);
     73 
     74 #define THREAD_STOP		1
     75 
     76 pthread_mutex_t glob_mutex;
     77 
     78 /*typedef struct thread {
     79 	int priority;
     80 	int policy;
     81 	entrypoint_t func;
     82 	pthread_attr_t attr;
     83 	pthread_t handle;
     84 	pthread_mutex_t mutex;
     85 	pthread_cond_t cond;
     86 	int flags;
     87 	int count;
     88 } Thread;*/
     89 
     90 typedef struct thread Thread;
     91 
     92 Thread arg1, arg2, arg3, arg4, arg5;
     93 
     94 int strartThread(Thread * thr);
     95 void stopThread(Thread * thr);
     96 void joinThread(Thread * thr);
     97 
     98 void *func_nonrt(void *arg)
     99 {
    100 	Thread *pthr = (Thread *) arg;
    101 	int rc, i, j, policy, tid = gettid();
    102 	struct sched_param schedp;
    103 	cpu_set_t mask;
    104 	CPU_ZERO(&mask);
    105 	CPU_SET(0, &mask);
    106 
    107 	rc = sched_setaffinity(0, sizeof(mask), &mask);
    108 	if (rc < 0) {
    109 		printf("Thread %d: Can't set affinity: %d %s\n", tid, rc,
    110 		       strerror(rc));
    111 		exit(-1);
    112 	}
    113 	rc = sched_getaffinity(0, sizeof(mask), &mask);
    114 
    115 	printf("Thread started %d on CPU %ld\n", pthr->priority,
    116 	       (long)mask.__bits[0]);
    117 	pthread_getschedparam(pthr->pthread, &policy, &schedp);
    118 	printf("Thread running %d\n", pthr->priority);
    119 
    120 	while (1) {
    121 		pthread_mutex_lock(&glob_mutex);
    122 		printf
    123 		    ("Thread %d at start pthread pol %d pri %d - Got global lock\n",
    124 		     pthr->priority, policy, schedp.sched_priority);
    125 		sleep(2);
    126 		for (i = 0; i < 10000; i++) {
    127 			if ((i % 100) == 0) {
    128 				sched_getparam(tid, &schedp);
    129 				policy = sched_getscheduler(tid);
    130 				printf("Thread %d(%d) loop %d pthread pol %d "
    131 				       "pri %d\n", tid, pthr->priority, i,
    132 				       policy, schedp.sched_priority);
    133 				fflush(NULL);
    134 			}
    135 			pthr->id++;
    136 			for (j = 0; j < 5000; j++) {
    137 				pthread_mutex_lock(&(pthr->mutex));
    138 				pthread_mutex_unlock(&(pthr->mutex));
    139 			}
    140 		}
    141 		pthread_mutex_unlock(&glob_mutex);
    142 		pthread_yield();
    143 	}
    144 	return NULL;
    145 }
    146 
    147 void *func_rt(void *arg)
    148 {
    149 	Thread *pthr = (Thread *) arg;
    150 	int rc, i, j, policy, tid = gettid();
    151 	struct sched_param schedp;
    152 	cpu_set_t mask;
    153 	CPU_ZERO(&mask);
    154 	CPU_SET(0, &mask);
    155 
    156 	rc = sched_setaffinity(0, sizeof(mask), &mask);
    157 	if (rc < 0) {
    158 		printf("Thread %d: Can't set affinity: %d %s\n", tid, rc,
    159 		       strerror(rc));
    160 		exit(-1);
    161 	}
    162 	rc = sched_getaffinity(0, sizeof(mask), &mask);
    163 
    164 	printf("Thread started %d on CPU %ld\n", pthr->priority,
    165 	       (long)mask.__bits[0]);
    166 	pthread_getschedparam(pthr->pthread, &policy, &schedp);
    167 
    168 	while (1) {
    169 		sleep(2);
    170 		printf("Thread running %d\n", pthr->priority);
    171 		pthread_mutex_lock(&glob_mutex);
    172 		printf
    173 		    ("Thread %d at start pthread pol %d pri %d - Got global lock\n",
    174 		     pthr->priority, policy, schedp.sched_priority);
    175 
    176 		/* we just use the mutex as something to slow things down */
    177 		/* say who we are and then do nothing for a while.      The aim
    178 		 * of this is to show that high priority threads make more
    179 		 * progress than lower priority threads..
    180 		 */
    181 		for (i = 0; i < 1000; i++) {
    182 			if (i % 100 == 0) {
    183 				sched_getparam(tid, &schedp);
    184 				policy = sched_getscheduler(tid);
    185 				printf
    186 				    ("Thread %d(%d) loop %d pthread pol %d pri %d\n",
    187 				     tid, pthr->priority, i, policy,
    188 				     schedp.sched_priority);
    189 				fflush(NULL);
    190 			}
    191 			pthr->id++;
    192 			for (j = 0; j < 5000; j++) {
    193 				pthread_mutex_lock(&(pthr->mutex));
    194 				pthread_mutex_unlock(&(pthr->mutex));
    195 			}
    196 		}
    197 		pthread_mutex_unlock(&glob_mutex);
    198 		sleep(2);
    199 	}
    200 	return NULL;
    201 }
    202 
    203 void *func_noise(void *arg)
    204 {
    205 	Thread *pthr = (Thread *) arg;
    206 	int rc, i, j, policy, tid = gettid();
    207 	struct sched_param schedp;
    208 	cpu_set_t mask;
    209 	CPU_ZERO(&mask);
    210 	CPU_SET(0, &mask);
    211 
    212 	rc = sched_setaffinity(0, sizeof(mask), &mask);
    213 	if (rc < 0) {
    214 		printf("Thread %d: Can't set affinity: %d %s\n", tid, rc,
    215 		       strerror(rc));
    216 		exit(-1);
    217 	}
    218 	rc = sched_getaffinity(0, sizeof(mask), &mask);
    219 
    220 	printf("Noise Thread started %d on CPU %ld\n", pthr->priority,
    221 	       (long)mask.__bits[0]);
    222 	pthread_getschedparam(pthr->pthread, &policy, &schedp);
    223 
    224 	while (1) {
    225 		sleep(1);
    226 		printf("Noise Thread running %d\n", pthr->priority);
    227 
    228 		for (i = 0; i < 10000; i++) {
    229 			if ((i % 100) == 0) {
    230 				sched_getparam(tid, &schedp);
    231 				policy = sched_getscheduler(tid);
    232 				printf
    233 				    ("Noise Thread %d(%d) loop %d pthread pol %d pri %d\n",
    234 				     tid, pthr->priority, i, policy,
    235 				     schedp.sched_priority);
    236 				fflush(NULL);
    237 			}
    238 			pthr->id++;
    239 			for (j = 0; j < 5000; j++) {
    240 				pthread_mutex_lock(&(pthr->mutex));
    241 				pthread_mutex_unlock(&(pthr->mutex));
    242 			}
    243 		}
    244 		pthread_yield();
    245 	}
    246 	return NULL;
    247 }
    248 
    249 int startThread(Thread * thrd)
    250 {
    251 	struct sched_param schedp;
    252 	pthread_condattr_t condattr;
    253 	int retc, policy, inherit;
    254 
    255 	printf("Start thread priority %d\n", thrd->priority);
    256 	if (pthread_attr_init(&(thrd->attr)) != 0) {
    257 		printf("Attr init failed");
    258 		exit(2);
    259 	}
    260 	thrd->flags = 0;
    261 	memset(&schedp, 0, sizeof(schedp));
    262 	schedp.sched_priority = thrd->priority;
    263 	policy = thrd->policy;
    264 
    265 	if (pthread_attr_setschedpolicy(&(thrd->attr), policy) != 0) {
    266 		printf("Can't set policy %d\n", policy);
    267 	}
    268 	if (pthread_attr_getschedpolicy(&(thrd->attr), &policy) != 0) {
    269 		printf("Can't get policy\n");
    270 	} else {
    271 		printf("Policy in attribs is %d\n", policy);
    272 	}
    273 	if (pthread_attr_setschedparam(&(thrd->attr), &schedp) != 0) {
    274 		printf("Can't set params");
    275 	}
    276 	if (pthread_attr_getschedparam(&(thrd->attr), &schedp) != 0) {
    277 		printf("Can't get params");
    278 	} else {
    279 		printf("Priority in attribs is %d\n", schedp.sched_priority);
    280 	}
    281 	if (pthread_attr_setinheritsched(&(thrd->attr), PTHREAD_EXPLICIT_SCHED)
    282 	    != 0) {
    283 		printf("Can't set inheritsched\n");
    284 	}
    285 	if (pthread_attr_getinheritsched(&(thrd->attr), &inherit) != 0) {
    286 		printf("Can't get inheritsched\n");
    287 	} else {
    288 		printf("inherit sched in attribs is %d\n", inherit);
    289 	}
    290 	if ((retc = pthread_mutex_init(&(thrd->mutex), NULL)) != 0) {
    291 		printf("Failed to init mutex: %d\n", retc);
    292 	}
    293 	if (pthread_condattr_init(&condattr) != 0) {
    294 		printf("Failed to init condattr\n");
    295 	}
    296 	if (pthread_cond_init(&(thrd->cond), &condattr) != 0) {
    297 		printf("Failed to init cond\n");
    298 	}
    299 	retc =
    300 	    pthread_create(&(thrd->pthread), &(thrd->attr), thrd->func, thrd);
    301 	printf("Create returns %d\n\n", retc);
    302 	return retc;
    303 }
    304 
    305 void stopThread(Thread * thr)
    306 {
    307 	thr->flags += THREAD_STOP;
    308 	joinThread(thr);
    309 }
    310 
    311 void joinThread(Thread * thr)
    312 {
    313 	void *ret = NULL;
    314 	if (pthread_join(thr->pthread, &ret) != 0) {
    315 		printf("Join failed\n");
    316 	}
    317 	printf("Join gave %p\n", ret);
    318 }
    319 
    320 /*
    321  * Test pthread creation at different thread priorities.
    322  */
    323 int main(int argc, char *argv[])
    324 {
    325 	int i, retc, nopi = 0;
    326 	cpu_set_t mask;
    327 	CPU_ZERO(&mask);
    328 	CPU_SET(0, &mask);
    329 	setup();
    330 
    331 	rt_init("h", parse_args, argc, argv);
    332 
    333 	retc = sched_setaffinity(0, sizeof(mask), &mask);
    334 	if (retc < 0) {
    335 		printf("Main Thread: Can't set affinity: %d %s\n", retc,
    336 		       strerror(retc));
    337 		exit(1);
    338 	}
    339 	retc = sched_getaffinity(0, sizeof(mask), &mask);
    340 
    341 	/*
    342 	 * XXX: Have you ever heard of structures with c89/c99?
    343 	 * Inline assignment is a beautiful thing.
    344 	 */
    345 	arg1.policy = SCHED_OTHER;
    346 	arg1.priority = 0;
    347 	arg1.func = func_nonrt;
    348 	arg2.policy = SCHED_RR;
    349 	arg2.priority = 20;
    350 	arg2.func = func_rt;
    351 	arg3.policy = SCHED_RR;
    352 	arg3.priority = 30;
    353 	arg3.func = func_rt;
    354 	arg4.policy = SCHED_RR;
    355 	arg4.priority = 40;
    356 	arg4.func = func_rt;
    357 	arg5.policy = SCHED_RR;
    358 	arg5.priority = 40;
    359 	arg5.func = func_noise;
    360 
    361 	for (i = 0; i < argc; i++) {
    362 		if (strcmp(argv[i], "nopi") == 0)
    363 			nopi = 1;
    364 	}
    365 
    366 	printf("Start %s\n", argv[0]);
    367 
    368 #if HAS_PRIORITY_INHERIT
    369 	if (!nopi) {
    370 		pthread_mutexattr_t mutexattr;
    371 		int protocol;
    372 
    373 		if (pthread_mutexattr_init(&mutexattr) != 0) {
    374 			printf("Failed to init mutexattr\n");
    375 		};
    376 		if (pthread_mutexattr_setprotocol
    377 		    (&mutexattr, PTHREAD_PRIO_INHERIT) != 0) {
    378 			printf("Can't set protocol prio inherit\n");
    379 		}
    380 		if (pthread_mutexattr_getprotocol(&mutexattr, &protocol) != 0) {
    381 			printf("Can't get mutexattr protocol\n");
    382 		} else {
    383 			printf("protocol in mutexattr is %d\n", protocol);
    384 		}
    385 		if ((retc = pthread_mutex_init(&glob_mutex, &mutexattr)) != 0) {
    386 			printf("Failed to init mutex: %d\n", retc);
    387 		}
    388 	}
    389 #endif
    390 
    391 	startThread(&arg1);
    392 	startThread(&arg2);
    393 	startThread(&arg3);
    394 	startThread(&arg4);
    395 	startThread(&arg5);
    396 
    397 	sleep(10);
    398 
    399 	printf("Stopping threads\n");
    400 	stopThread(&arg1);
    401 	stopThread(&arg2);
    402 	stopThread(&arg3);
    403 	stopThread(&arg4);
    404 	stopThread(&arg5);
    405 
    406 	printf("Thread counts %d %d %d %d %d\n", arg1.id, arg2.id, arg3.id,
    407 	       arg4.id, arg5.id);
    408 	printf("Done\n");
    409 
    410 	return 0;
    411 }
    412