1 /* 2 * Copyright (c) 2005, Bull S.A.. All rights reserved. 3 * Created by: Sebastien Decugis 4 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 16 17 * This stress test aims to test the following assertion: 18 19 * pthread_getschedparam() always returns the scheduling parameters of 20 * the queried thread. 21 22 * The steps are: 23 * -> Create several threads with different scheduling parameters. 24 * -> create more threads which call continuously the routine, and check 25 * -> that the correct parameters are always returned. 26 27 */ 28 29 /********************************************************************************************/ 30 /****************************** standard includes *****************************************/ 31 /********************************************************************************************/ 32 #include <pthread.h> 33 #include <stdarg.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include <errno.h> 40 #include <signal.h> 41 #include <sched.h> 42 43 /********************************************************************************************/ 44 /****************************** Test framework *****************************************/ 45 /********************************************************************************************/ 46 #include "testfrmw.h" 47 #include "testfrmw.c" 48 /* This header is responsible for defining the following macros: 49 * UNRESOLVED(ret, descr); 50 * where descr is a description of the error and ret is an int (error code for example) 51 * FAILED(descr); 52 * where descr is a short text saying why the test has failed. 53 * PASSED(); 54 * No parameter. 55 * 56 * Both three macros shall terminate the calling process. 57 * The testcase shall not terminate in any other maneer. 58 * 59 * The other file defines the functions 60 * void output_init() 61 * void output(char * string, ...) 62 * 63 * Those may be used to output information. 64 */ 65 66 /********************************************************************************************/ 67 /********************************** Configuration ******************************************/ 68 /********************************************************************************************/ 69 #ifndef VERBOSE 70 #define VERBOSE 1 71 #endif 72 73 #define NTHREADS 30 74 75 /********************************************************************************************/ 76 /*********************************** Test cases *****************************************/ 77 /********************************************************************************************/ 78 79 char do_it = 1; 80 long long iterations = 0; 81 82 /* Handler for user request to terminate */ 83 void sighdl(int sig) 84 { 85 do { 86 do_it = 0; 87 } 88 while (do_it); 89 } 90 91 typedef struct _tdata { 92 int policy; 93 int prio; 94 pthread_t thread; 95 } testdata_t; 96 97 testdata_t td[4]; 98 99 /* Thread function */ 100 void *threaded(void *arg) 101 { 102 int ret = 0; 103 int i = 0; 104 int pol; 105 106 struct sched_param sp; 107 108 while (do_it) { 109 for (i = 0; i < 4; i++) { 110 ret = pthread_getschedparam(td[i].thread, &pol, &sp); 111 112 if (ret != 0) { 113 UNRESOLVED(ret, "Failed to get sched param"); 114 } 115 116 if (pol != td[i].policy) { 117 FAILED("Wrong scheduling policy read"); 118 } 119 120 if (sp.sched_priority != td[i].prio) { 121 FAILED("Wrong scheduling priority read"); 122 } 123 124 } 125 126 /* We don't really care about concurrent access for this data */ 127 iterations++; 128 } 129 130 return NULL; 131 } 132 133 /* alternative policy threads */ 134 void *rt_thread(void *arg) 135 { 136 int ret = 0; 137 138 /* This thread does almost nothing but wait... */ 139 ret = pthread_barrier_wait(arg); 140 141 if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { 142 UNRESOLVED(ret, "Failed to wait for barrier"); 143 } 144 145 return NULL; 146 } 147 148 /* Main function */ 149 int main(int argc, char *argv[]) 150 { 151 int ret = 0, i; 152 153 struct sigaction sa; 154 155 pthread_barrier_t bar; 156 157 pthread_attr_t ta[4]; 158 159 pthread_t th[NTHREADS]; 160 161 struct sched_param sp; 162 163 /* Initialize output routine */ 164 output_init(); 165 166 /* Initialize barrier */ 167 ret = pthread_barrier_init(&bar, NULL, 5); 168 169 if (ret != 0) { 170 UNRESOLVED(ret, "Failed to init barrier"); 171 } 172 173 /* Register the signal handler for SIGUSR1 */ 174 sigemptyset(&sa.sa_mask); 175 176 sa.sa_flags = 0; 177 178 sa.sa_handler = sighdl; 179 180 if ((ret = sigaction(SIGUSR1, &sa, NULL))) { 181 UNRESOLVED(ret, "Unable to register signal handler"); 182 } 183 184 if ((ret = sigaction(SIGALRM, &sa, NULL))) { 185 UNRESOLVED(ret, "Unable to register signal handler"); 186 } 187 #if VERBOSE > 1 188 output("[parent] Signal handler registered\n"); 189 190 #endif 191 192 td[0].policy = td[1].policy = SCHED_FIFO; 193 194 td[2].policy = td[3].policy = SCHED_RR; 195 196 td[0].prio = sched_get_priority_min(SCHED_FIFO); 197 198 if (td[0].prio == -1) { 199 UNRESOLVED(errno, "Failed to get scheduler range value"); 200 } 201 202 td[1].prio = sched_get_priority_max(SCHED_FIFO); 203 204 if (td[1].prio == -1) { 205 UNRESOLVED(errno, "Failed to get scheduler range value"); 206 } 207 208 td[2].prio = sched_get_priority_min(SCHED_RR); 209 210 if (td[2].prio == -1) { 211 UNRESOLVED(errno, "Failed to get scheduler range value"); 212 } 213 214 td[3].prio = sched_get_priority_max(SCHED_RR); 215 216 if (td[3].prio == -1) { 217 UNRESOLVED(errno, "Failed to get scheduler range value"); 218 } 219 220 /* Initialize the threads attributes and create the RT threads */ 221 for (i = 0; i < 4; i++) { 222 ret = pthread_attr_init(&ta[i]); 223 224 if (ret != 0) { 225 UNRESOLVED(ret, 226 "Failed to initialize thread attribute"); 227 } 228 229 ret = 230 pthread_attr_setinheritsched(&ta[i], 231 PTHREAD_EXPLICIT_SCHED); 232 233 if (ret != 0) { 234 UNRESOLVED(ret, 235 "Failed to set explicit scheduling attribute"); 236 } 237 238 sp.sched_priority = td[i].prio; 239 240 ret = pthread_attr_setschedparam(&ta[i], &sp); 241 242 if (ret != 0) { 243 UNRESOLVED(ret, 244 "failed to set thread attribute sched param"); 245 } 246 247 ret = pthread_attr_setschedpolicy(&ta[i], td[i].policy); 248 249 if (ret != 0) { 250 UNRESOLVED(ret, 251 "failed to set thread attribute sched prio"); 252 } 253 254 ret = pthread_create(&td[i].thread, &ta[i], rt_thread, &bar); 255 256 if (ret != 0) { 257 UNRESOLVED(ret, 258 "Failed to create a RT thread -- need more privilege?"); 259 } 260 261 } 262 263 /* Create the worker threads */ 264 for (i = 0; i < NTHREADS; i++) { 265 ret = pthread_create(&th[i], NULL, threaded, NULL); 266 267 if (ret != 0) { 268 UNRESOLVED(ret, "failed to create a worker thread"); 269 } 270 } 271 272 /* Wait for the worker threads to finish */ 273 for (i = 0; i < NTHREADS; i++) { 274 ret = pthread_join(th[i], NULL); 275 276 if (ret != 0) { 277 UNRESOLVED(ret, "failed to join a worker thread"); 278 } 279 } 280 281 /* Join the barrier to terminate the RT threads */ 282 ret = pthread_barrier_wait(&bar); 283 284 if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { 285 UNRESOLVED(ret, "Failed to wait for the barrier"); 286 } 287 288 /* Join the RT threads */ 289 for (i = 0; i < 4; i++) { 290 ret = pthread_join(td[i].thread, NULL); 291 292 if (ret != 0) { 293 UNRESOLVED(ret, "Failed to join a thread"); 294 } 295 } 296 297 /* Done! */ 298 output("pthread_getschedparam stress test PASSED -- %llu iterations\n", 299 iterations); 300 301 ret = pthread_barrier_destroy(&bar); 302 303 if (ret != 0) { 304 UNRESOLVED(ret, "Failed to destroy the barrier"); 305 } 306 307 PASSED; 308 } 309