1f08c3bdfSopenharmony_ci/****************************************************************************** 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright © International Business Machines Corp., 2006, 2008 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 6f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 7f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 8f08c3bdfSopenharmony_ci * (at your option) any later version. 9f08c3bdfSopenharmony_ci * 10f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 11f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 12f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 14f08c3bdfSopenharmony_ci * 15f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 16f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 17f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * NAME 20f08c3bdfSopenharmony_ci * lookup_pi_state.c 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * DESCRIPTION 23f08c3bdfSopenharmony_ci * A test to reproduce a bug in lookup_pi_state() 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * USAGE: 26f08c3bdfSopenharmony_ci * Use run_auto.sh script in current directory to build and run test. 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * AUTHOR 29f08c3bdfSopenharmony_ci * Darren Hart <dvhltc@us.ibm.com> 30f08c3bdfSopenharmony_ci * 31f08c3bdfSopenharmony_ci * HISTORY 32f08c3bdfSopenharmony_ci * 2006-May-18: Initial version by Darren Hart <dvhltc@us.ibm.com> 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci *****************************************************************************/ 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci#include <stdio.h> 37f08c3bdfSopenharmony_ci#include <librttest.h> 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci#define NUM_SLAVES 20 40f08c3bdfSopenharmony_ci#define SLAVE_PRIO 89 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_cipthread_mutex_t MM; 43f08c3bdfSopenharmony_cipthread_mutex_t MS; 44f08c3bdfSopenharmony_cipthread_mutex_t MT; 45f08c3bdfSopenharmony_cipthread_cond_t CM; 46f08c3bdfSopenharmony_cipthread_cond_t CS; 47f08c3bdfSopenharmony_cipthread_cond_t CT; 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_ciatomic_t slave_order_a = { 0 }; 50f08c3bdfSopenharmony_ciatomic_t slave_order_b = { 0 }; 51f08c3bdfSopenharmony_ciatomic_t slave_order_c = { 0 }; 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_civoid usage(void) 54f08c3bdfSopenharmony_ci{ 55f08c3bdfSopenharmony_ci rt_help(); 56f08c3bdfSopenharmony_ci printf("lookup_pi_state specific options:\n"); 57f08c3bdfSopenharmony_ci} 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ciint parse_args(int c, char *v) 60f08c3bdfSopenharmony_ci{ 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci int handled = 1; 63f08c3bdfSopenharmony_ci switch (c) { 64f08c3bdfSopenharmony_ci case 'h': 65f08c3bdfSopenharmony_ci usage(); 66f08c3bdfSopenharmony_ci exit(0); 67f08c3bdfSopenharmony_ci default: 68f08c3bdfSopenharmony_ci handled = 0; 69f08c3bdfSopenharmony_ci break; 70f08c3bdfSopenharmony_ci } 71f08c3bdfSopenharmony_ci return handled; 72f08c3bdfSopenharmony_ci} 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_civoid *slave_thread(void *arg) 75f08c3bdfSopenharmony_ci{ 76f08c3bdfSopenharmony_ci struct thread *t = (struct thread *)arg; 77f08c3bdfSopenharmony_ci int id = (intptr_t) t->arg; 78f08c3bdfSopenharmony_ci// 3 79f08c3bdfSopenharmony_ci pthread_mutex_lock(&MS); 80f08c3bdfSopenharmony_ci// 4,5 81f08c3bdfSopenharmony_ci if (atomic_inc(&slave_order_a) == NUM_SLAVES) { 82f08c3bdfSopenharmony_ci printf("Slave thread %d notifying master\n", id); 83f08c3bdfSopenharmony_ci pthread_mutex_lock(&MM); // make sure the master thread is waiting 84f08c3bdfSopenharmony_ci pthread_cond_signal(&CM); 85f08c3bdfSopenharmony_ci pthread_mutex_unlock(&MM); 86f08c3bdfSopenharmony_ci } 87f08c3bdfSopenharmony_ci printf("Slave thread %d waiting on CS,MS\n", id); 88f08c3bdfSopenharmony_ci pthread_cond_wait(&CS, &MS); // docs are contradictory on if this 89f08c3bdfSopenharmony_ci // should be MS or MM 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci if (atomic_inc(&slave_order_b) <= 6) { 92f08c3bdfSopenharmony_ci// 10,11 93f08c3bdfSopenharmony_ci ; 94f08c3bdfSopenharmony_ci // do nothing, just terminate 95f08c3bdfSopenharmony_ci } else { 96f08c3bdfSopenharmony_ci// 12 97f08c3bdfSopenharmony_ci pthread_cond_wait(&CS, &MS); 98f08c3bdfSopenharmony_ci// 17 99f08c3bdfSopenharmony_ci } 100f08c3bdfSopenharmony_ci pthread_mutex_unlock(&MS); 101f08c3bdfSopenharmony_ci atomic_inc(&slave_order_c); 102f08c3bdfSopenharmony_ci printf("Slave thread %d terminating\n", id); 103f08c3bdfSopenharmony_ci return NULL; 104f08c3bdfSopenharmony_ci} 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_civoid *master_thread(void *arg) 107f08c3bdfSopenharmony_ci{ 108f08c3bdfSopenharmony_ci int i; 109f08c3bdfSopenharmony_ci struct timespec ts_abs_timeout; 110f08c3bdfSopenharmony_ci struct thread *t = (struct thread *)arg; 111f08c3bdfSopenharmony_ci// 1 112f08c3bdfSopenharmony_ci pthread_mutex_lock(&MM); 113f08c3bdfSopenharmony_ci for (i = 0; i < NUM_SLAVES; i++) { 114f08c3bdfSopenharmony_ci create_fifo_thread(slave_thread, (void *)(intptr_t) i, 115f08c3bdfSopenharmony_ci SLAVE_PRIO); 116f08c3bdfSopenharmony_ci } 117f08c3bdfSopenharmony_ci// 2 118f08c3bdfSopenharmony_ci printf("Master waiting till slaves wait()\n"); 119f08c3bdfSopenharmony_ci pthread_cond_wait(&CM, &MM); 120f08c3bdfSopenharmony_ci printf("Master awoken\n"); 121f08c3bdfSopenharmony_ci// 6 122f08c3bdfSopenharmony_ci pthread_mutex_lock(&MS); 123f08c3bdfSopenharmony_ci// 7 124f08c3bdfSopenharmony_ci printf("Master doing 3 signals\n"); 125f08c3bdfSopenharmony_ci pthread_cond_signal(&CS); 126f08c3bdfSopenharmony_ci pthread_cond_signal(&CS); 127f08c3bdfSopenharmony_ci pthread_cond_signal(&CS); 128f08c3bdfSopenharmony_ci// 8 129f08c3bdfSopenharmony_ci printf("Master doing 3 broadcasts\n"); 130f08c3bdfSopenharmony_ci pthread_cond_broadcast(&CS); 131f08c3bdfSopenharmony_ci pthread_cond_broadcast(&CS); 132f08c3bdfSopenharmony_ci pthread_cond_broadcast(&CS); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci /* if we should timedwait on MS, then we don't need to unlock it here */ 135f08c3bdfSopenharmony_ci pthread_mutex_unlock(&MS); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci printf("Master waiting 10 seconds\n"); 138f08c3bdfSopenharmony_ci clock_gettime(CLOCK_REALTIME, &ts_abs_timeout); 139f08c3bdfSopenharmony_ci ts_abs_timeout.tv_sec += 10; 140f08c3bdfSopenharmony_ci /* 141f08c3bdfSopenharmony_ci * docs say CS and MS, but that doesn't seem correct 142f08c3bdfSopenharmony_ci * 143f08c3bdfSopenharmony_ci * XXX (garrcoop): then that's a documentation or implementation bug. 144f08c3bdfSopenharmony_ci * Duh... FIX IT! 145f08c3bdfSopenharmony_ci */ 146f08c3bdfSopenharmony_ci pthread_cond_timedwait(&CM, &MM, &ts_abs_timeout); 147f08c3bdfSopenharmony_ci// 13 148f08c3bdfSopenharmony_ci pthread_mutex_unlock(&MM); 149f08c3bdfSopenharmony_ci// 14 150f08c3bdfSopenharmony_ci printf("Master doing notify of all remaining slaves\n"); 151f08c3bdfSopenharmony_ci pthread_mutex_lock(&MS); 152f08c3bdfSopenharmony_ci pthread_cond_broadcast(&CS); 153f08c3bdfSopenharmony_ci// 15 154f08c3bdfSopenharmony_ci /* 155f08c3bdfSopenharmony_ci * docs say MM, but that doesn't make sense.. 156f08c3bdfSopenharmony_ci * 157f08c3bdfSopenharmony_ci * XXX (garrcoop): comments above apply here too 158f08c3bdfSopenharmony_ci */ 159f08c3bdfSopenharmony_ci pthread_mutex_unlock(&MS); 160f08c3bdfSopenharmony_ci// 16 161f08c3bdfSopenharmony_ci pthread_mutex_lock(&MT); 162f08c3bdfSopenharmony_ci clock_gettime(CLOCK_REALTIME, &ts_abs_timeout); 163f08c3bdfSopenharmony_ci ts_abs_timeout.tv_sec += 2; 164f08c3bdfSopenharmony_ci pthread_cond_timedwait(&CT, &MT, &ts_abs_timeout); 165f08c3bdfSopenharmony_ci// 18 166f08c3bdfSopenharmony_ci while (!thread_quit(t)) 167f08c3bdfSopenharmony_ci usleep(10); 168f08c3bdfSopenharmony_ci 169f08c3bdfSopenharmony_ci printf("All slaves have terminated\n"); 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci return NULL; 172f08c3bdfSopenharmony_ci} 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 175f08c3bdfSopenharmony_ci{ 176f08c3bdfSopenharmony_ci init_pi_mutex(&MM); 177f08c3bdfSopenharmony_ci init_pi_mutex(&MS); 178f08c3bdfSopenharmony_ci init_pi_mutex(&MT); 179f08c3bdfSopenharmony_ci setup(); 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_ci pthread_cond_init(&CM, NULL); 182f08c3bdfSopenharmony_ci pthread_cond_init(&CS, NULL); 183f08c3bdfSopenharmony_ci pthread_cond_init(&CT, NULL); 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_ci rt_init("h", parse_args, argc, argv); 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci create_other_thread(master_thread, NULL); 188f08c3bdfSopenharmony_ci 189f08c3bdfSopenharmony_ci /* wait for the slaves to quit */ 190f08c3bdfSopenharmony_ci while (atomic_get(&slave_order_c) < NUM_SLAVES) 191f08c3bdfSopenharmony_ci usleep(10); 192f08c3bdfSopenharmony_ci 193f08c3bdfSopenharmony_ci join_threads(); 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_ci return 0; 196f08c3bdfSopenharmony_ci} 197