1/* 2 * Copyright (c) 2004, QUALCOMM Inc. All rights reserved. 3 * Created by: abisain REMOVE-THIS AT qualcomm DOT com 4 * This file is licensed under the GPL license. For the full content 5 * of this license, see the COPYING file at the top level of this 6 * source tree. 7 8 * Test that pthread_cond_signal() 9 * shall wakeup a high priority thread even when a low priority thread 10 * is running 11 12 * Steps: 13 * 1. Create a condition variable 14 * 2. Create a high priority thread and make it wait on the cond 15 * 3. Create a low priority thread and let it busy-loop 16 * 4. Signal the cond in a signal handler and check that high 17 * priority thread got woken up 18 * 19 */ 20 21#include <pthread.h> 22#include <stdio.h> 23#include <stdlib.h> 24#include <signal.h> 25#include <unistd.h> 26#include <time.h> 27#include "posixtest.h" 28 29#define TEST "5-1" 30#define AREA "scheduler" 31#define ERROR_PREFIX "unexpected error: " AREA " " TEST ": " 32 33#define HIGH_PRIORITY 10 34#define LOW_PRIORITY 5 35#define RUNTIME 5 36#define POLICY SCHED_RR 37 38/* mutex required by the cond variable */ 39pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 40/* condition variable that threads block on*/ 41pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 42 43/* Flags that the threads use to indicate events */ 44int woken_up = -1; 45int low_done = -1; 46 47/* Signal handler that handle the ALRM and wakes up 48 * the high priority thread 49 */ 50void signal_handler(int sig) 51{ 52 if(pthread_cond_signal(&cond) != 0) { 53 printf(ERROR_PREFIX "pthread_cond_signal\n"); 54 exit(PTS_UNRESOLVED); 55 } 56} 57 58/* Utility function to find difference between two time values */ 59float timediff(struct timespec t2, struct timespec t1) 60{ 61 float diff = t2.tv_sec - t1.tv_sec; 62 diff += (t2.tv_nsec - t1.tv_nsec)/1000000000.0; 63 return diff; 64} 65 66void *hi_priority_thread(void *tmp) 67{ 68 struct sched_param param; 69 int policy; 70 int rc = 0; 71 72 param.sched_priority = HIGH_PRIORITY; 73 74 rc = pthread_setschedparam(pthread_self(), POLICY, ¶m); 75 if(rc != 0) { 76 printf(ERROR_PREFIX "pthread_setschedparam\n"); 77 exit(PTS_UNRESOLVED); 78 } 79 rc = pthread_getschedparam(pthread_self(), &policy, ¶m); 80 if(rc != 0) { 81 printf(ERROR_PREFIX "pthread_getschedparam\n"); 82 exit(PTS_UNRESOLVED); 83 } 84 if((policy != POLICY) || (param.sched_priority != HIGH_PRIORITY)) { 85 printf("Error: the policy or priority not correct\n"); 86 exit(PTS_UNRESOLVED); 87 } 88 89 /* Install a signal handler for ALRM */ 90 if(signal(SIGALRM, signal_handler) != 0) { 91 perror(ERROR_PREFIX "signal:"); 92 exit(PTS_UNRESOLVED); 93 } 94 95 /* acquire the mutex */ 96 rc = pthread_mutex_lock(&mutex); 97 if(rc != 0) { 98 printf(ERROR_PREFIX "pthread_mutex_lock\n"); 99 exit(PTS_UNRESOLVED); 100 } 101 102 /* Setup an alarm to go off in 2 seconds */ 103 alarm(2); 104 105 /* Block, to be woken up by the signal handler */ 106 rc = pthread_cond_wait(&cond, &mutex); 107 if(rc != 0) { 108 printf(ERROR_PREFIX "pthread_cond_wait\n"); 109 exit(PTS_UNRESOLVED); 110 } 111 112 /* This variable is unprotected because the scheduling removes 113 * the contention 114 */ 115 if(low_done != 1) 116 woken_up = 1; 117 118 rc = pthread_mutex_unlock(&mutex); 119 if(rc != 0) { 120 printf(ERROR_PREFIX "pthread_mutex_unlock\n"); 121 exit(PTS_UNRESOLVED); 122 } 123 return NULL; 124} 125 126void *low_priority_thread(void *tmp) 127{ 128 struct timespec start_time, current_time; 129 struct sched_param param; 130 int policy; 131 int rc = 0; 132 133 param.sched_priority = LOW_PRIORITY; 134 135 rc = pthread_setschedparam(pthread_self(), POLICY, ¶m); 136 if(rc != 0) { 137 printf(ERROR_PREFIX "pthread_setschedparam\n"); 138 exit(PTS_UNRESOLVED); 139 } 140 rc = pthread_getschedparam(pthread_self(), &policy, ¶m); 141 if(rc != 0) { 142 printf(ERROR_PREFIX "pthread_getschedparam\n"); 143 exit(PTS_UNRESOLVED); 144 } 145 if((policy != POLICY) || (param.sched_priority != LOW_PRIORITY)) { 146 printf("Error: the policy or priority not correct\n"); 147 exit(PTS_UNRESOLVED); 148 } 149 150 /* grab the start time and busy loop for 5 seconds */ 151 clock_gettime(CLOCK_REALTIME, &start_time); 152 while(1) 153 { 154 clock_gettime(CLOCK_REALTIME, ¤t_time); 155 if(timediff(current_time, start_time) > RUNTIME) 156 break; 157 } 158 low_done = 1; 159 return NULL; 160} 161 162int main() 163{ 164 pthread_t high_id, low_id; 165 pthread_attr_t high_attr, low_attr; 166 struct sched_param param; 167 int rc = 0; 168 169 /* Create the higher priority thread */ 170 rc = pthread_attr_init(&high_attr); 171 if(rc != 0) { 172 printf(ERROR_PREFIX "pthread_attr_init\n"); 173 exit(PTS_UNRESOLVED); 174 } 175 176 rc = pthread_attr_setschedpolicy(&high_attr, POLICY); 177 if(rc != 0) { 178 printf(ERROR_PREFIX "pthread_attr_setschedpolicy\n"); 179 exit(PTS_UNRESOLVED); 180 } 181 param.sched_priority = HIGH_PRIORITY; 182 rc = pthread_attr_setschedparam(&high_attr, ¶m); 183 if(rc != 0) { 184 printf(ERROR_PREFIX "pthread_attr_setschedparam\n"); 185 exit(PTS_UNRESOLVED); 186 } 187 rc = pthread_create(&high_id, &high_attr, hi_priority_thread, NULL); 188 if(rc != 0) { 189 printf(ERROR_PREFIX "pthread_create\n"); 190 exit(PTS_UNRESOLVED); 191 } 192 193 /* Create the low priority thread */ 194 rc = pthread_attr_init(&low_attr); 195 if(rc != 0) { 196 printf(ERROR_PREFIX "pthread_attr_init\n"); 197 exit(PTS_UNRESOLVED); 198 } 199 rc = pthread_attr_setschedpolicy(&low_attr, POLICY); 200 if(rc != 0) { 201 printf(ERROR_PREFIX "pthread_attr_setschedpolicy\n"); 202 exit(PTS_UNRESOLVED); 203 } 204 param.sched_priority = LOW_PRIORITY; 205 rc = pthread_attr_setschedparam(&low_attr, ¶m); 206 if(rc != 0) { 207 printf(ERROR_PREFIX "pthread_attr_setschedparam\n"); 208 exit(PTS_UNRESOLVED); 209 } 210 rc = pthread_create(&low_id, &low_attr, low_priority_thread, NULL); 211 if(rc != 0) { 212 printf(ERROR_PREFIX "pthread_create\n"); 213 exit(PTS_UNRESOLVED); 214 } 215 216 /* Wait for the threads to exit */ 217 rc = pthread_join(high_id, NULL); 218 if(rc != 0) { 219 printf(ERROR_PREFIX "pthread_join\n"); 220 exit(PTS_UNRESOLVED); 221 } 222 223 rc = pthread_join(low_id, NULL); 224 if(rc != 0) { 225 printf(ERROR_PREFIX "pthread_join\n"); 226 exit(PTS_UNRESOLVED); 227 } 228 229 /* Check the result */ 230 if(woken_up == -1) { 231 printf("Test FAILED: high priority was not woken up\\n"); 232 exit(PTS_FAIL); 233 } 234 235 printf("Test PASS\n"); 236 exit(PTS_PASS); 237} 238