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