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 sched_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 sched_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