1 /* 2 * 3 * Copyright (c) Novell Inc. 2011 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms in version 2 of the GNU General Public License as published by 7 * the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12 * the GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 * 18 * Author: Peter W. Morreale <pmorreale AT novell DOT com> 19 * 20 * Date: 20/05/2011 21 */ 22 23 #include "affinity.h" 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <pthread.h> 28 #include <unistd.h> 29 #include <stdlib.h> 30 #include <errno.h> 31 #include <posixtest.h> 32 33 /* Priorities for the threads, must be unique, non-zero, and ordered */ 34 #define PRIO_HIGH 20 35 #define PRIO_MED 10 36 #define PRIO_LOW 5 37 #define PRIO_MAIN 1 38 39 static int priorities[3]; 40 41 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 42 static pthread_mutex_t c_mutex = PTHREAD_MUTEX_INITIALIZER; 43 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 44 45 static int thread_started; 46 47 #define FAIL_AND_EXIT(f, rc) { \ 48 printf("Failed: function: %s status: %s(%u)\n", f, strerror(rc), rc); \ 49 exit(PTS_UNRESOLVED); \ 50 } 51 52 static void *thread_func(void *data) 53 { 54 struct sched_param sp; 55 int policy; 56 int rc; 57 58 rc = pthread_getschedparam(pthread_self(), &policy, &sp); 59 if (rc) 60 FAIL_AND_EXIT("pthread_getschedparam()", rc); 61 62 rc = pthread_mutex_lock(&c_mutex); 63 if (rc) 64 FAIL_AND_EXIT("pthread_mutex_lock()", rc); 65 thread_started = 1; 66 rc = pthread_cond_signal(&cond); 67 if (rc) 68 FAIL_AND_EXIT("pthread_cond_signal()", rc); 69 rc = pthread_mutex_unlock(&c_mutex); 70 if (rc) 71 FAIL_AND_EXIT("pthread_mutex_unlock()", rc); 72 73 rc = pthread_mutex_lock(&mutex); 74 if (rc) 75 FAIL_AND_EXIT("pthread_mutex_lock()", rc); 76 77 /* Stuff the priority in execution order */ 78 if (!priorities[0]) 79 priorities[0] = sp.sched_priority; 80 else if (!priorities[1]) 81 priorities[1] = sp.sched_priority; 82 else 83 priorities[2] = sp.sched_priority; 84 85 rc = pthread_mutex_unlock(&mutex); 86 if (rc) 87 FAIL_AND_EXIT("pthread_mutex_unlock()", rc); 88 89 return (void *)(long)rc; 90 } 91 92 static int create_thread(int prio, pthread_t * tid) 93 { 94 int rc; 95 struct sched_param sp; 96 pthread_attr_t attr; 97 98 rc = pthread_attr_init(&attr); 99 if (rc != 0) 100 FAIL_AND_EXIT("pthread_attr_init()", rc); 101 102 rc = pthread_attr_setschedpolicy(&attr, SCHED_FIFO); 103 if (rc != 0) 104 FAIL_AND_EXIT("pthread_attr_setschedpolicy()", rc); 105 106 rc = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); 107 if (rc != 0) 108 FAIL_AND_EXIT("pthread_attr_setinheritsched()", rc); 109 110 sp.sched_priority = prio; 111 rc = pthread_attr_setschedparam(&attr, &sp); 112 if (rc != 0) 113 FAIL_AND_EXIT("pthread_attr_setschedparam()", rc); 114 115 thread_started = 0; 116 117 rc = pthread_create(tid, &attr, thread_func, NULL); 118 if (rc) 119 FAIL_AND_EXIT("pthread_create()", rc); 120 121 rc = pthread_mutex_lock(&c_mutex); 122 if (rc) 123 FAIL_AND_EXIT("pthread_mutex_lock()", rc); 124 while (!thread_started) { 125 rc = pthread_cond_wait(&cond, &c_mutex); 126 if (rc) 127 FAIL_AND_EXIT("pthread_cond_wait()", rc); 128 } 129 rc = pthread_mutex_unlock(&c_mutex); 130 if (rc) 131 FAIL_AND_EXIT("pthread_mutex_unlock()", rc); 132 133 pthread_attr_destroy(&attr); 134 135 return 0; 136 } 137 138 int main(void) 139 { 140 int status; 141 int rc; 142 void *r1; 143 void *r2; 144 void *r3; 145 pthread_t t1; 146 pthread_t t2; 147 pthread_t t3; 148 struct sched_param sp; 149 150 status = PTS_UNRESOLVED; 151 152 153 rc = set_affinity_single(); 154 if (rc) 155 FAIL_AND_EXIT("set_affinity_single", errno); 156 157 sp.sched_priority = PRIO_MAIN; 158 rc = pthread_setschedparam(pthread_self(), SCHED_FIFO, &sp); 159 if (rc) 160 FAIL_AND_EXIT("pthread_setschedparam()", rc); 161 162 rc = pthread_mutex_lock(&mutex); 163 if (rc) 164 FAIL_AND_EXIT("pthread_mutex_lock()", rc); 165 166 rc = create_thread(PRIO_LOW, &t3); 167 if (rc) 168 FAIL_AND_EXIT("create_thread LOW", rc); 169 170 rc = create_thread(PRIO_MED, &t2); 171 if (rc) 172 FAIL_AND_EXIT("create_thread MED", rc); 173 174 rc = create_thread(PRIO_HIGH, &t1); 175 if (rc) 176 FAIL_AND_EXIT("create_thread HIGH", rc); 177 178 rc = pthread_mutex_unlock(&mutex); 179 if (rc) 180 FAIL_AND_EXIT("pthread_mutex_unlock()", rc); 181 182 rc = pthread_join(t1, &r1); 183 if (rc) 184 FAIL_AND_EXIT("pthread_join(t1)", rc); 185 186 rc = pthread_join(t2, &r2); 187 if (rc) 188 FAIL_AND_EXIT("pthread_join(t2)", rc); 189 190 rc = pthread_join(t3, &r3); 191 if (rc) 192 FAIL_AND_EXIT("pthread_join(t3)", rc); 193 194 /* priorities must be high to low */ 195 status = PTS_FAIL; 196 if (priorities[0] != PRIO_HIGH) 197 printf("Failed: first is prio: %u, should be: %u\n", 198 priorities[0], PRIO_HIGH); 199 else if (priorities[1] != PRIO_MED) 200 printf("Failed: second is prio: %u, should be: %u\n", 201 priorities[1], PRIO_MED); 202 else if (priorities[2] != PRIO_LOW) 203 printf("Failed: third is prio: %u, should be: %u\n", 204 priorities[2], PRIO_LOW); 205 else 206 status = PTS_PASS; 207 208 if (status == PTS_PASS) 209 printf("Test PASSED\n"); 210 211 return status; 212 } 213