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 * async_handler.c 21f08c3bdfSopenharmony_ci * 22f08c3bdfSopenharmony_ci * DESCRIPTION 23f08c3bdfSopenharmony_ci * Measure the latency involved in asynchronous event handlers. 24f08c3bdfSopenharmony_ci * Specifically it measures the latency of the pthread_cond_signal 25f08c3bdfSopenharmony_ci * call until the signalled thread is scheduled. 26f08c3bdfSopenharmony_ci * 27f08c3bdfSopenharmony_ci * USAGE: 28f08c3bdfSopenharmony_ci * Use run_auto.sh script in current directory to build and run test. 29f08c3bdfSopenharmony_ci * 30f08c3bdfSopenharmony_ci * AUTHOR 31f08c3bdfSopenharmony_ci * Darren Hart <dvhltc@us.ibm.com> 32f08c3bdfSopenharmony_ci * 33f08c3bdfSopenharmony_ci * HISTORY 34f08c3bdfSopenharmony_ci * 2006-Oct-20: Initial version by Darren Hart <dvhltc@us.ibm.com> 35f08c3bdfSopenharmony_ci * 36f08c3bdfSopenharmony_ci * This line has to be added to avoid a stupid CVS problem 37f08c3bdfSopenharmony_ci *****************************************************************************/ 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci#include <stdio.h> 40f08c3bdfSopenharmony_ci#include <stdlib.h> 41f08c3bdfSopenharmony_ci#include <math.h> 42f08c3bdfSopenharmony_ci#include <librttest.h> 43f08c3bdfSopenharmony_ci#include <libstats.h> 44f08c3bdfSopenharmony_ci#include <getopt.h> 45f08c3bdfSopenharmony_ci 46f08c3bdfSopenharmony_ci#define SIGNAL_PRIO 89 47f08c3bdfSopenharmony_ci#define HANDLER_PRIO 89 48f08c3bdfSopenharmony_ci#define DEFAULT_ITERATIONS 1000000 /* about 1 minute @ 2GHz */ 49f08c3bdfSopenharmony_ci#define HIST_BUCKETS 100 50f08c3bdfSopenharmony_ci#define PASS_US 100 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_cistatic nsec_t start; 53f08c3bdfSopenharmony_cistatic nsec_t end; 54f08c3bdfSopenharmony_cistatic int iterations = 0; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci#define CHILD_START 0 57f08c3bdfSopenharmony_ci#define CHILD_WAIT 1 58f08c3bdfSopenharmony_ci#define CHILD_HANDLED 2 59f08c3bdfSopenharmony_ci#define CHILD_QUIT 3 60f08c3bdfSopenharmony_ciatomic_t step; 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_cipthread_cond_t cond = PTHREAD_COND_INITIALIZER; 63f08c3bdfSopenharmony_cipthread_mutex_t mutex; 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_cistatic int ret = 0; 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_civoid usage(void) 68f08c3bdfSopenharmony_ci{ 69f08c3bdfSopenharmony_ci rt_help(); 70f08c3bdfSopenharmony_ci printf("async_handler specific options:\n"); 71f08c3bdfSopenharmony_ci printf 72f08c3bdfSopenharmony_ci (" -iITERATIONS number of iterations to calculate the average over\n"); 73f08c3bdfSopenharmony_ci} 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ciint parse_args(int c, char *v) 76f08c3bdfSopenharmony_ci{ 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci int handled = 1; 79f08c3bdfSopenharmony_ci switch (c) { 80f08c3bdfSopenharmony_ci case 'h': 81f08c3bdfSopenharmony_ci usage(); 82f08c3bdfSopenharmony_ci exit(0); 83f08c3bdfSopenharmony_ci case 'i': 84f08c3bdfSopenharmony_ci iterations = atoi(v); 85f08c3bdfSopenharmony_ci break; 86f08c3bdfSopenharmony_ci default: 87f08c3bdfSopenharmony_ci handled = 0; 88f08c3bdfSopenharmony_ci break; 89f08c3bdfSopenharmony_ci } 90f08c3bdfSopenharmony_ci return handled; 91f08c3bdfSopenharmony_ci} 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_civoid *handler_thread(void *arg) 94f08c3bdfSopenharmony_ci{ 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci while (atomic_get(&step) != CHILD_QUIT) { 97f08c3bdfSopenharmony_ci pthread_mutex_lock(&mutex); 98f08c3bdfSopenharmony_ci atomic_set(CHILD_WAIT, &step); 99f08c3bdfSopenharmony_ci if (pthread_cond_wait(&cond, &mutex) != 0) { 100f08c3bdfSopenharmony_ci perror("pthead_cond_wait"); 101f08c3bdfSopenharmony_ci break; 102f08c3bdfSopenharmony_ci } 103f08c3bdfSopenharmony_ci end = rt_gettime(); 104f08c3bdfSopenharmony_ci atomic_set(CHILD_HANDLED, &step); 105f08c3bdfSopenharmony_ci pthread_mutex_unlock(&mutex); 106f08c3bdfSopenharmony_ci while (atomic_get(&step) == CHILD_HANDLED) 107f08c3bdfSopenharmony_ci usleep(10); 108f08c3bdfSopenharmony_ci } 109f08c3bdfSopenharmony_ci printf("handler thread exiting\n"); 110f08c3bdfSopenharmony_ci return 0; 111f08c3bdfSopenharmony_ci} 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_civoid *signal_thread(void *arg) 114f08c3bdfSopenharmony_ci{ 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci int i; 117f08c3bdfSopenharmony_ci long delta, max, min; 118f08c3bdfSopenharmony_ci stats_container_t dat; 119f08c3bdfSopenharmony_ci stats_container_t hist; 120f08c3bdfSopenharmony_ci stats_record_t rec; 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_ci stats_container_init(&dat, iterations); 123f08c3bdfSopenharmony_ci stats_container_init(&hist, HIST_BUCKETS); 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_ci min = max = 0; 126f08c3bdfSopenharmony_ci for (i = 0; i < iterations; i++) { 127f08c3bdfSopenharmony_ci /* wait for child to wait on cond, then signal the event */ 128f08c3bdfSopenharmony_ci while (atomic_get(&step) != CHILD_WAIT) 129f08c3bdfSopenharmony_ci usleep(10); 130f08c3bdfSopenharmony_ci pthread_mutex_lock(&mutex); 131f08c3bdfSopenharmony_ci start = rt_gettime(); 132f08c3bdfSopenharmony_ci if (pthread_cond_signal(&cond) != 0) { 133f08c3bdfSopenharmony_ci perror("pthread_cond_signal"); 134f08c3bdfSopenharmony_ci atomic_set(CHILD_QUIT, &step); 135f08c3bdfSopenharmony_ci break; 136f08c3bdfSopenharmony_ci } 137f08c3bdfSopenharmony_ci pthread_mutex_unlock(&mutex); 138f08c3bdfSopenharmony_ci 139f08c3bdfSopenharmony_ci /* wait for the event handler to schedule */ 140f08c3bdfSopenharmony_ci while (atomic_get(&step) != CHILD_HANDLED) 141f08c3bdfSopenharmony_ci usleep(10); 142f08c3bdfSopenharmony_ci delta = (long)((end - start) / NS_PER_US); 143f08c3bdfSopenharmony_ci if (delta > pass_criteria) 144f08c3bdfSopenharmony_ci ret = 1; 145f08c3bdfSopenharmony_ci rec.x = i; 146f08c3bdfSopenharmony_ci rec.y = delta; 147f08c3bdfSopenharmony_ci stats_container_append(&dat, rec); 148f08c3bdfSopenharmony_ci if (i == 0) 149f08c3bdfSopenharmony_ci min = max = delta; 150f08c3bdfSopenharmony_ci else { 151f08c3bdfSopenharmony_ci min = MIN(min, delta); 152f08c3bdfSopenharmony_ci max = MAX(max, delta); 153f08c3bdfSopenharmony_ci } 154f08c3bdfSopenharmony_ci atomic_set((i == iterations - 1) ? CHILD_QUIT : CHILD_START, 155f08c3bdfSopenharmony_ci &step); 156f08c3bdfSopenharmony_ci } 157f08c3bdfSopenharmony_ci printf("recording statistics...\n"); 158f08c3bdfSopenharmony_ci printf("Min: %ld us\n", min); 159f08c3bdfSopenharmony_ci printf("Max: %ld us\n", max); 160f08c3bdfSopenharmony_ci printf("Avg: %.4f us\n", stats_avg(&dat)); 161f08c3bdfSopenharmony_ci printf("StdDev: %.4f us\n", stats_stddev(&dat)); 162f08c3bdfSopenharmony_ci stats_hist(&hist, &dat); 163f08c3bdfSopenharmony_ci stats_container_save("samples", 164f08c3bdfSopenharmony_ci "Asynchronous Event Handling Latency Scatter Plot", 165f08c3bdfSopenharmony_ci "Iteration", "Latency (us)", &dat, "points"); 166f08c3bdfSopenharmony_ci stats_container_save("hist", 167f08c3bdfSopenharmony_ci "Asynchronous Event Handling Latency Histogram", 168f08c3bdfSopenharmony_ci "Latency (us)", "Samples", &hist, "steps"); 169f08c3bdfSopenharmony_ci printf("signal thread exiting\n"); 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci return NULL; 172f08c3bdfSopenharmony_ci} 173f08c3bdfSopenharmony_ci 174f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 175f08c3bdfSopenharmony_ci{ 176f08c3bdfSopenharmony_ci int signal_id, handler_id; 177f08c3bdfSopenharmony_ci setup(); 178f08c3bdfSopenharmony_ci 179f08c3bdfSopenharmony_ci printf("\n-----------------------------------\n"); 180f08c3bdfSopenharmony_ci printf("Asynchronous Event Handling Latency\n"); 181f08c3bdfSopenharmony_ci printf("-----------------------------------\n\n"); 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_ci pass_criteria = PASS_US; 184f08c3bdfSopenharmony_ci rt_init("i:h", parse_args, argc, argv); 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci init_pi_mutex(&mutex); 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_ci atomic_set(CHILD_START, &step); 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci if (iterations == 0) 191f08c3bdfSopenharmony_ci iterations = DEFAULT_ITERATIONS; 192f08c3bdfSopenharmony_ci printf("Running %d iterations\n", iterations); 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci handler_id = 195f08c3bdfSopenharmony_ci create_fifo_thread(handler_thread, NULL, HANDLER_PRIO); 196f08c3bdfSopenharmony_ci signal_id = create_fifo_thread(signal_thread, NULL, SIGNAL_PRIO); 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci join_threads(); 199f08c3bdfSopenharmony_ci 200f08c3bdfSopenharmony_ci printf("\nCriteria: latencies < %d\n", (int)pass_criteria); 201f08c3bdfSopenharmony_ci printf("Result: %s\n", ret ? "FAIL" : "PASS"); 202f08c3bdfSopenharmony_ci 203f08c3bdfSopenharmony_ci return ret; 204f08c3bdfSopenharmony_ci} 205