1f08c3bdfSopenharmony_ci/****************************************************************************** 2f08c3bdfSopenharmony_ci * 3f08c3bdfSopenharmony_ci * Copyright © International Business Machines Corp., 2005, 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 * pthread_cond_latency.c 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * DESCRIPTION 23f08c3bdfSopenharmony_ci * measure pthread_cond_t latencies 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 * Paul E. McKenney <paulmck@us.ibm.com> 30f08c3bdfSopenharmony_ci * 31f08c3bdfSopenharmony_ci * HISTORY 32f08c3bdfSopenharmony_ci * 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci *****************************************************************************/ 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci#include <stdio.h> 37f08c3bdfSopenharmony_ci#include <pthread.h> 38f08c3bdfSopenharmony_ci#include <sys/time.h> 39f08c3bdfSopenharmony_ci#include <sched.h> 40f08c3bdfSopenharmony_ci#include <sys/poll.h> 41f08c3bdfSopenharmony_ci#include <sys/types.h> 42f08c3bdfSopenharmony_ci#include <unistd.h> 43f08c3bdfSopenharmony_ci#include <stdlib.h> 44f08c3bdfSopenharmony_ci#include <librttest.h> 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_cipthread_mutex_t child_mutex = PTHREAD_MUTEX_INITIALIZER; 47f08c3bdfSopenharmony_civolatile int child_waiting = 0; 48f08c3bdfSopenharmony_cidouble endtime; 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_civoid usage(void) 51f08c3bdfSopenharmony_ci{ 52f08c3bdfSopenharmony_ci rt_help(); 53f08c3bdfSopenharmony_ci printf("testpi-1 specific options:\n"); 54f08c3bdfSopenharmony_ci} 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ciint parse_args(int c, char *v) 57f08c3bdfSopenharmony_ci{ 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci int handled = 1; 60f08c3bdfSopenharmony_ci switch (c) { 61f08c3bdfSopenharmony_ci case 'h': 62f08c3bdfSopenharmony_ci usage(); 63f08c3bdfSopenharmony_ci exit(0); 64f08c3bdfSopenharmony_ci default: 65f08c3bdfSopenharmony_ci handled = 0; 66f08c3bdfSopenharmony_ci break; 67f08c3bdfSopenharmony_ci } 68f08c3bdfSopenharmony_ci return handled; 69f08c3bdfSopenharmony_ci} 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci/* 72f08c3bdfSopenharmony_ci * Return time as a floating-point number rather than struct timeval. 73f08c3bdfSopenharmony_ci */ 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_cidouble d_gettimeofday(void) 76f08c3bdfSopenharmony_ci{ 77f08c3bdfSopenharmony_ci int retval; 78f08c3bdfSopenharmony_ci struct timeval tv; 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci retval = gettimeofday(&tv, NULL); 81f08c3bdfSopenharmony_ci if (retval != 0) { 82f08c3bdfSopenharmony_ci perror("gettimeofday"); 83f08c3bdfSopenharmony_ci exit(-1); 84f08c3bdfSopenharmony_ci } 85f08c3bdfSopenharmony_ci return (tv.tv_sec + ((double)tv.tv_usec) / 1000000.); 86f08c3bdfSopenharmony_ci} 87f08c3bdfSopenharmony_ci 88f08c3bdfSopenharmony_civoid *childfunc(void *arg) 89f08c3bdfSopenharmony_ci{ 90f08c3bdfSopenharmony_ci pthread_cond_t *cp = (pthread_cond_t *) arg; 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci while (child_waiting == 0) { 93f08c3bdfSopenharmony_ci pthread_mutex_lock(&child_mutex); 94f08c3bdfSopenharmony_ci child_waiting = 1; 95f08c3bdfSopenharmony_ci if (pthread_cond_wait(cp, &child_mutex) != 0) { 96f08c3bdfSopenharmony_ci perror("pthread_cond_wait"); 97f08c3bdfSopenharmony_ci exit(-1); 98f08c3bdfSopenharmony_ci } 99f08c3bdfSopenharmony_ci endtime = d_gettimeofday(); 100f08c3bdfSopenharmony_ci child_waiting = 2; 101f08c3bdfSopenharmony_ci pthread_mutex_unlock(&child_mutex); 102f08c3bdfSopenharmony_ci while (child_waiting == 2) { 103f08c3bdfSopenharmony_ci poll(NULL, 0, 10); 104f08c3bdfSopenharmony_ci } 105f08c3bdfSopenharmony_ci } 106f08c3bdfSopenharmony_ci pthread_exit(NULL); 107f08c3bdfSopenharmony_ci} 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_civoid test_signal(int broadcast_flag, int iter) 110f08c3bdfSopenharmony_ci{ 111f08c3bdfSopenharmony_ci pthread_attr_t attr; 112f08c3bdfSopenharmony_ci pthread_t childid; 113f08c3bdfSopenharmony_ci pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 114f08c3bdfSopenharmony_ci int i; 115f08c3bdfSopenharmony_ci int prio; 116f08c3bdfSopenharmony_ci struct sched_param schparm; 117f08c3bdfSopenharmony_ci double starttime; 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci prio = sched_get_priority_max(SCHED_FIFO); 120f08c3bdfSopenharmony_ci if (prio == -1) { 121f08c3bdfSopenharmony_ci perror("sched_get_priority_max"); 122f08c3bdfSopenharmony_ci exit(-1); 123f08c3bdfSopenharmony_ci } 124f08c3bdfSopenharmony_ci schparm.sched_priority = prio; 125f08c3bdfSopenharmony_ci if (sched_setscheduler(getpid(), SCHED_FIFO, &schparm) != 0) { 126f08c3bdfSopenharmony_ci perror("sched_setscheduler"); 127f08c3bdfSopenharmony_ci exit(-1); 128f08c3bdfSopenharmony_ci } 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci if (pthread_attr_init(&attr) != 0) { 131f08c3bdfSopenharmony_ci perror("pthread_attr_init"); 132f08c3bdfSopenharmony_ci exit(-1); 133f08c3bdfSopenharmony_ci } 134f08c3bdfSopenharmony_ci if (pthread_attr_setschedpolicy(&attr, SCHED_FIFO) != 0) { 135f08c3bdfSopenharmony_ci perror("pthread_attr_setschedpolicy"); 136f08c3bdfSopenharmony_ci exit(-1); 137f08c3bdfSopenharmony_ci } 138f08c3bdfSopenharmony_ci if (pthread_attr_setschedparam(&attr, &schparm) != 0) { 139f08c3bdfSopenharmony_ci perror("pthread_attr_setschedparam"); 140f08c3bdfSopenharmony_ci exit(-1); 141f08c3bdfSopenharmony_ci } 142f08c3bdfSopenharmony_ci if (pthread_create(&childid, &attr, childfunc, (void *)&cond) != 0) { 143f08c3bdfSopenharmony_ci perror("pthread_create"); 144f08c3bdfSopenharmony_ci exit(-1); 145f08c3bdfSopenharmony_ci } 146f08c3bdfSopenharmony_ci for (i = 0; i < iter; i++) { 147f08c3bdfSopenharmony_ci pthread_mutex_lock(&child_mutex); 148f08c3bdfSopenharmony_ci child_waiting = 0; 149f08c3bdfSopenharmony_ci while (child_waiting == 0) { 150f08c3bdfSopenharmony_ci pthread_mutex_unlock(&child_mutex); 151f08c3bdfSopenharmony_ci sched_yield(); 152f08c3bdfSopenharmony_ci pthread_mutex_lock(&child_mutex); 153f08c3bdfSopenharmony_ci } 154f08c3bdfSopenharmony_ci pthread_mutex_unlock(&child_mutex); 155f08c3bdfSopenharmony_ci if (broadcast_flag) { 156f08c3bdfSopenharmony_ci starttime = d_gettimeofday(); 157f08c3bdfSopenharmony_ci if (pthread_cond_broadcast(&cond) != 0) { 158f08c3bdfSopenharmony_ci perror("pthread_cond_broadcast"); 159f08c3bdfSopenharmony_ci exit(-1); 160f08c3bdfSopenharmony_ci } 161f08c3bdfSopenharmony_ci } else { 162f08c3bdfSopenharmony_ci starttime = d_gettimeofday(); 163f08c3bdfSopenharmony_ci if (pthread_cond_signal(&cond) != 0) { 164f08c3bdfSopenharmony_ci perror("pthread_cond_signal"); 165f08c3bdfSopenharmony_ci exit(-1); 166f08c3bdfSopenharmony_ci } 167f08c3bdfSopenharmony_ci } 168f08c3bdfSopenharmony_ci for (;;) { 169f08c3bdfSopenharmony_ci pthread_mutex_lock(&child_mutex); 170f08c3bdfSopenharmony_ci if (child_waiting == 2) { 171f08c3bdfSopenharmony_ci break; 172f08c3bdfSopenharmony_ci } 173f08c3bdfSopenharmony_ci pthread_mutex_unlock(&child_mutex); 174f08c3bdfSopenharmony_ci poll(NULL, 0, 10); 175f08c3bdfSopenharmony_ci } 176f08c3bdfSopenharmony_ci printf("%s() latency: %d microseconds\n", 177f08c3bdfSopenharmony_ci (broadcast_flag 178f08c3bdfSopenharmony_ci ? "pthread_cond_broadcast" 179f08c3bdfSopenharmony_ci : "pthread_cond_signal"), 180f08c3bdfSopenharmony_ci (int)((endtime - starttime) * 1000000.)); 181f08c3bdfSopenharmony_ci pthread_mutex_unlock(&child_mutex); 182f08c3bdfSopenharmony_ci } 183f08c3bdfSopenharmony_ci pthread_mutex_lock(&child_mutex); 184f08c3bdfSopenharmony_ci child_waiting = 3; 185f08c3bdfSopenharmony_ci pthread_mutex_unlock(&child_mutex); 186f08c3bdfSopenharmony_ci if (pthread_join(childid, NULL) != 0) { 187f08c3bdfSopenharmony_ci perror("pthread_join"); 188f08c3bdfSopenharmony_ci exit(-1); 189f08c3bdfSopenharmony_ci } 190f08c3bdfSopenharmony_ci} 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 193f08c3bdfSopenharmony_ci{ 194f08c3bdfSopenharmony_ci struct sched_param sp; 195f08c3bdfSopenharmony_ci long iter; 196f08c3bdfSopenharmony_ci setup(); 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci rt_init("h", parse_args, argc, argv); 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci sp.sched_priority = sched_get_priority_max(SCHED_FIFO); 201f08c3bdfSopenharmony_ci if (sp.sched_priority == -1) { 202f08c3bdfSopenharmony_ci perror("sched_get_priority_max"); 203f08c3bdfSopenharmony_ci exit(-1); 204f08c3bdfSopenharmony_ci } 205f08c3bdfSopenharmony_ci if (sched_setscheduler(0, SCHED_FIFO, &sp) != 0) { 206f08c3bdfSopenharmony_ci perror("sched_setscheduler"); 207f08c3bdfSopenharmony_ci exit(-1); 208f08c3bdfSopenharmony_ci } 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci if (argc == 1) { 211f08c3bdfSopenharmony_ci fprintf(stderr, "Usage: %s iterations [unicast]\n", argv[0]); 212f08c3bdfSopenharmony_ci exit(-1); 213f08c3bdfSopenharmony_ci } 214f08c3bdfSopenharmony_ci iter = strtol(argv[1], NULL, 0); 215f08c3bdfSopenharmony_ci test_signal(argc == 2, iter); 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci return 0; 218f08c3bdfSopenharmony_ci} 219