12c28215423293e443469a07ae7011135d058b671Garrett Cooper/* 22c28215423293e443469a07ae7011135d058b671Garrett Cooper * Copyright (c) 2004, Bull S.A.. All rights reserved. 32c28215423293e443469a07ae7011135d058b671Garrett Cooper * Created by: Sebastien Decugis 42c28215423293e443469a07ae7011135d058b671Garrett Cooper 52c28215423293e443469a07ae7011135d058b671Garrett Cooper * This program is free software; you can redistribute it and/or modify it 62c28215423293e443469a07ae7011135d058b671Garrett Cooper * under the terms of version 2 of the GNU General Public License as 72c28215423293e443469a07ae7011135d058b671Garrett Cooper * published by the Free Software Foundation. 82c28215423293e443469a07ae7011135d058b671Garrett Cooper * 92c28215423293e443469a07ae7011135d058b671Garrett Cooper * This program is distributed in the hope that it would be useful, but 102c28215423293e443469a07ae7011135d058b671Garrett Cooper * WITHOUT ANY WARRANTY; without even the implied warranty of 112c28215423293e443469a07ae7011135d058b671Garrett Cooper * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 122c28215423293e443469a07ae7011135d058b671Garrett Cooper * 132c28215423293e443469a07ae7011135d058b671Garrett Cooper * You should have received a copy of the GNU General Public License along 14fed9641096e27f79a0f2d9adfe9839dd8d11dc0fWanlong Gao * with this program; if not, write the Free Software Foundation, Inc., 15fed9641096e27f79a0f2d9adfe9839dd8d11dc0fWanlong Gao * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 162c28215423293e443469a07ae7011135d058b671Garrett Cooper * 172c28215423293e443469a07ae7011135d058b671Garrett Cooper 182c28215423293e443469a07ae7011135d058b671Garrett Cooper * This file is a scalability test for the pthread_cond_timedwait function. 192c28215423293e443469a07ae7011135d058b671Garrett Cooper * 202c28215423293e443469a07ae7011135d058b671Garrett Cooper * It aims to measure the time between end of timeout and actual wakeup 212c28215423293e443469a07ae7011135d058b671Garrett Cooper * with different factors. 222c28215423293e443469a07ae7011135d058b671Garrett Cooper 232c28215423293e443469a07ae7011135d058b671Garrett Cooper * The steps are: 242c28215423293e443469a07ae7011135d058b671Garrett Cooper * -*- Number of threads waiting on the conditionnal variable 252c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> for an increaing number of threads, 262c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> create the other threads which will do a pthread_cond_wait on the same cond/mutex 272c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> When the threads are waiting, create one thread which will measure the time 282c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> once the timeout has expired and the measure is done, broadcast the condition. 292c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> do each measure 10 times (with different attributes i.e.) 302c28215423293e443469a07ae7011135d058b671Garrett Cooper * 312c28215423293e443469a07ae7011135d058b671Garrett Cooper * -*- other possible influencial parameters 322c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> To be defined. 332c28215423293e443469a07ae7011135d058b671Garrett Cooper */ 342c28215423293e443469a07ae7011135d058b671Garrett Cooper 352c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ 36354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define _POSIX_C_SOURCE 200112L 372c28215423293e443469a07ae7011135d058b671Garrett Cooper 38354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifndef WITHOUT_XOPEN 39354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define _XOPEN_SOURCE 600 40354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 412c28215423293e443469a07ae7011135d058b671Garrett Cooper 422c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/ 432c28215423293e443469a07ae7011135d058b671Garrett Cooper/****************************** standard includes *****************************************/ 442c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/ 45354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <pthread.h> 46354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdarg.h> 47354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdio.h> 48354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <stdlib.h> 49354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <unistd.h> 502c28215423293e443469a07ae7011135d058b671Garrett Cooper 51354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <time.h> 52354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <errno.h> 53354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include <math.h> 542c28215423293e443469a07ae7011135d058b671Garrett Cooper 552c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/ 562c28215423293e443469a07ae7011135d058b671Garrett Cooper/****************************** Test framework *****************************************/ 572c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/ 58354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include "testfrmw.h" 59354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#include "testfrmw.c" 602c28215423293e443469a07ae7011135d058b671Garrett Cooper /* This header is responsible for defining the following macros: 612c28215423293e443469a07ae7011135d058b671Garrett Cooper * UNRESOLVED(ret, descr); 622c28215423293e443469a07ae7011135d058b671Garrett Cooper * where descr is a description of the error and ret is an int (error code for example) 632c28215423293e443469a07ae7011135d058b671Garrett Cooper * FAILED(descr); 642c28215423293e443469a07ae7011135d058b671Garrett Cooper * where descr is a short text saying why the test has failed. 652c28215423293e443469a07ae7011135d058b671Garrett Cooper * PASSED(); 662c28215423293e443469a07ae7011135d058b671Garrett Cooper * No parameter. 672c28215423293e443469a07ae7011135d058b671Garrett Cooper * 682c28215423293e443469a07ae7011135d058b671Garrett Cooper * Both three macros shall terminate the calling process. 692c28215423293e443469a07ae7011135d058b671Garrett Cooper * The testcase shall not terminate in any other maneer. 702c28215423293e443469a07ae7011135d058b671Garrett Cooper * 712c28215423293e443469a07ae7011135d058b671Garrett Cooper * The other file defines the functions 722c28215423293e443469a07ae7011135d058b671Garrett Cooper * void output_init() 732c28215423293e443469a07ae7011135d058b671Garrett Cooper * void output(char * string, ...) 742c28215423293e443469a07ae7011135d058b671Garrett Cooper * 752c28215423293e443469a07ae7011135d058b671Garrett Cooper * Those may be used to output information. 762c28215423293e443469a07ae7011135d058b671Garrett Cooper */ 772c28215423293e443469a07ae7011135d058b671Garrett Cooper 782c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/ 792c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************** Configuration ******************************************/ 802c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/ 812c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef SCALABILITY_FACTOR 822c28215423293e443469a07ae7011135d058b671Garrett Cooper#define SCALABILITY_FACTOR 1 832c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 842c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef VERBOSE 852c28215423293e443469a07ae7011135d058b671Garrett Cooper#define VERBOSE 1 862c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 872c28215423293e443469a07ae7011135d058b671Garrett Cooper 882c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef WITHOUT_ALTCLK 89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define USE_ALTCLK /* make tests with MONOTONIC CLOCK if supported */ 902c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 912c28215423293e443469a07ae7011135d058b671Garrett Cooper 92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#define MES_TIMEOUT (1000000) /* ns, offset for the pthread_cond_timedwait call */ 932c28215423293e443469a07ae7011135d058b671Garrett Cooper 942c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifdef PLOT_OUTPUT 952c28215423293e443469a07ae7011135d058b671Garrett Cooper#undef VERBOSE 962c28215423293e443469a07ae7011135d058b671Garrett Cooper#define VERBOSE 0 972c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 982c28215423293e443469a07ae7011135d058b671Garrett Cooper 992c28215423293e443469a07ae7011135d058b671Garrett Cooper// #define USE_CANCEL /* Will cancel the threads instead of signaling the cond */#define 1002c28215423293e443469a07ae7011135d058b671Garrett Cooper 1012c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/ 1022c28215423293e443469a07ae7011135d058b671Garrett Cooper/*********************************** Test case *****************************************/ 1032c28215423293e443469a07ae7011135d058b671Garrett Cooper/********************************************************************************************/ 1042c28215423293e443469a07ae7011135d058b671Garrett Cooper 1052c28215423293e443469a07ae7011135d058b671Garrett Cooperlong altclk_ok, pshared_ok; 1062c28215423293e443469a07ae7011135d058b671Garrett Cooper 107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaotypedef struct { 1082c28215423293e443469a07ae7011135d058b671Garrett Cooper pthread_cond_t *cnd; 1092c28215423293e443469a07ae7011135d058b671Garrett Cooper pthread_mutex_t *mtx; 110354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int *predicate; 111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int *tnum; 1122c28215423293e443469a07ae7011135d058b671Garrett Cooper} test_t; 1132c28215423293e443469a07ae7011135d058b671Garrett Cooper 1142c28215423293e443469a07ae7011135d058b671Garrett Cooperstruct { 1152c28215423293e443469a07ae7011135d058b671Garrett Cooper int mutex_type; 1162c28215423293e443469a07ae7011135d058b671Garrett Cooper int pshared; 1172c28215423293e443469a07ae7011135d058b671Garrett Cooper clockid_t cid; 118354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *desc; 1192c28215423293e443469a07ae7011135d058b671Garrett Cooper} test_scenar[] = { 120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao { 121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_DEFAULT, PTHREAD_PROCESS_PRIVATE, CLOCK_REALTIME, 122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Default"} 123354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 124354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_DEFAULT, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME, 125354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "PShared"} 1262c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef WITHOUT_XOPEN 127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 128354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_NORMAL, PTHREAD_PROCESS_PRIVATE, CLOCK_REALTIME, 129354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Normal"} 130354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 131354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_NORMAL, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME, 132354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Normal+PShared"} 133354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 134354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_ERRORCHECK, PTHREAD_PROCESS_PRIVATE, 135354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao CLOCK_REALTIME, "Errorcheck"} 136354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 137354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_ERRORCHECK, PTHREAD_PROCESS_SHARED, 138354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao CLOCK_REALTIME, "Errorcheck+PShared"} 139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_RECURSIVE, PTHREAD_PROCESS_PRIVATE, 141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao CLOCK_REALTIME, "Recursive"} 142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 143354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_RECURSIVE, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME, 144354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Recursive+PShared"} 1452c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 1462c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifdef USE_ALTCLK 147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_DEFAULT, PTHREAD_PROCESS_PRIVATE, CLOCK_MONOTONIC, 149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Monotonic"} 150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 151354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_DEFAULT, PTHREAD_PROCESS_SHARED, CLOCK_MONOTONIC, 152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "PShared+Monotonic"} 1532c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifndef WITHOUT_XOPEN 154354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_NORMAL, PTHREAD_PROCESS_PRIVATE, CLOCK_MONOTONIC, 156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Normal+Monotonic"} 157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_NORMAL, PTHREAD_PROCESS_SHARED, CLOCK_MONOTONIC, 159354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Normal+PShared+Monotonic"} 160354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 161354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_ERRORCHECK, PTHREAD_PROCESS_PRIVATE, 162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao CLOCK_MONOTONIC, "Errorcheck+Monotonic"} 163354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 164354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_ERRORCHECK, PTHREAD_PROCESS_SHARED, 165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao CLOCK_MONOTONIC, "Errorcheck+PShared+Monotonic"} 166354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 167354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_RECURSIVE, PTHREAD_PROCESS_PRIVATE, 168354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao CLOCK_MONOTONIC, "Recursive+Monotonic"} 169354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao , { 170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao PTHREAD_MUTEX_RECURSIVE, PTHREAD_PROCESS_SHARED, 171354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao CLOCK_MONOTONIC, "Recursive+PShared+Monotonic"} 1722c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 1732c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 1742c28215423293e443469a07ae7011135d058b671Garrett Cooper}; 1752c28215423293e443469a07ae7011135d058b671Garrett Cooper 1762c28215423293e443469a07ae7011135d058b671Garrett Cooper#define NSCENAR (sizeof(test_scenar) / sizeof(test_scenar[0])) 1772c28215423293e443469a07ae7011135d058b671Garrett Cooper 178354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaopthread_attr_t ta; 1792c28215423293e443469a07ae7011135d058b671Garrett Cooper 1802c28215423293e443469a07ae7011135d058b671Garrett Cooper/* The next structure is used to save the tests measures */ 181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaotypedef struct __mes_t { 182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int nthreads; 183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao long _data[NSCENAR]; /* As we store µsec values, a long type should be amply enough. */ 1842c28215423293e443469a07ae7011135d058b671Garrett Cooper struct __mes_t *next; 1852c28215423293e443469a07ae7011135d058b671Garrett Cooper} mes_t; 1862c28215423293e443469a07ae7011135d058b671Garrett Cooper 1872c28215423293e443469a07ae7011135d058b671Garrett Cooper/**** do_measure 1882c28215423293e443469a07ae7011135d058b671Garrett Cooper * This function will do a timedwait on the cond cnd after locking mtx. 1892c28215423293e443469a07ae7011135d058b671Garrett Cooper * Once the timedwait times out, it will read the clock cid then 1902c28215423293e443469a07ae7011135d058b671Garrett Cooper * compute the difference and put it into ts. 1912c28215423293e443469a07ae7011135d058b671Garrett Cooper * This function must be called once test is ready, as the timeout will be very short. */ 192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid do_measure(pthread_mutex_t * mtx, pthread_cond_t * cnd, clockid_t cid, 193354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct timespec *ts) 1942c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 1952c28215423293e443469a07ae7011135d058b671Garrett Cooper int ret, rc; 1962c28215423293e443469a07ae7011135d058b671Garrett Cooper 1972c28215423293e443469a07ae7011135d058b671Garrett Cooper struct timespec ts_cnd, ts_clk; 1982c28215423293e443469a07ae7011135d058b671Garrett Cooper 1992c28215423293e443469a07ae7011135d058b671Garrett Cooper /* lock the mutex */ 2002c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_lock(mtx); 201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 202354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to lock mutex"); 203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2042c28215423293e443469a07ae7011135d058b671Garrett Cooper 2052c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Prepare the timeout parameter */ 2062c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = clock_gettime(cid, &ts_cnd); 207354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 208354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(errno, "Unable to read clock"); 209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2102c28215423293e443469a07ae7011135d058b671Garrett Cooper 2112c28215423293e443469a07ae7011135d058b671Garrett Cooper ts_cnd.tv_nsec += MES_TIMEOUT; 212354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while (ts_cnd.tv_nsec >= 1000000000) { 2132c28215423293e443469a07ae7011135d058b671Garrett Cooper ts_cnd.tv_nsec -= 1000000000; 2142c28215423293e443469a07ae7011135d058b671Garrett Cooper ts_cnd.tv_sec++; 2152c28215423293e443469a07ae7011135d058b671Garrett Cooper } 2162c28215423293e443469a07ae7011135d058b671Garrett Cooper 2172c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Do the timedwait */ 2182c28215423293e443469a07ae7011135d058b671Garrett Cooper do { 2192c28215423293e443469a07ae7011135d058b671Garrett Cooper rc = pthread_cond_timedwait(cnd, mtx, &ts_cnd); 2202c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Re-read the clock as soon as possible */ 2212c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = clock_gettime(cid, &ts_clk); 222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 223354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(errno, "Unable to read clock"); 224354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2252c28215423293e443469a07ae7011135d058b671Garrett Cooper } 2262c28215423293e443469a07ae7011135d058b671Garrett Cooper while (rc == 0); 227354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (rc != ETIMEDOUT) { 228354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(rc, 229354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Timedwait returned an unexpected error (expected ETIMEDOUT)"); 230354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2312c28215423293e443469a07ae7011135d058b671Garrett Cooper 2322c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Compute the difference time */ 2332c28215423293e443469a07ae7011135d058b671Garrett Cooper ts->tv_sec = ts_clk.tv_sec - ts_cnd.tv_sec; 2342c28215423293e443469a07ae7011135d058b671Garrett Cooper ts->tv_nsec = ts_clk.tv_nsec - ts_cnd.tv_nsec; 235354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ts->tv_nsec < 0) { 2362c28215423293e443469a07ae7011135d058b671Garrett Cooper ts->tv_nsec += 1000000000; 2372c28215423293e443469a07ae7011135d058b671Garrett Cooper ts->tv_sec -= 1; 2382c28215423293e443469a07ae7011135d058b671Garrett Cooper } 2392c28215423293e443469a07ae7011135d058b671Garrett Cooper 240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ts->tv_sec < 0) { 241354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao FAILED 242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("The function returned from wait with a timeout before the time has passed\n"); 2432c28215423293e443469a07ae7011135d058b671Garrett Cooper } 2442c28215423293e443469a07ae7011135d058b671Garrett Cooper 2452c28215423293e443469a07ae7011135d058b671Garrett Cooper /* unlock the mutex */ 2462c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_unlock(mtx); 247354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to unlock mutex"); 249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2502c28215423293e443469a07ae7011135d058b671Garrett Cooper 2512c28215423293e443469a07ae7011135d058b671Garrett Cooper return; 2522c28215423293e443469a07ae7011135d058b671Garrett Cooper} 2532c28215423293e443469a07ae7011135d058b671Garrett Cooper 254354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid *waiter(void *arg) 2552c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 256354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao test_t *dt = (test_t *) arg; 2572c28215423293e443469a07ae7011135d058b671Garrett Cooper 2582c28215423293e443469a07ae7011135d058b671Garrett Cooper int ret; 2592c28215423293e443469a07ae7011135d058b671Garrett Cooper 2602c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_lock(dt->mtx); 261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 262354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Mutex lock failed in waiter"); 263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2642c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifdef USE_CANCEL 2652c28215423293e443469a07ae7011135d058b671Garrett Cooper pthread_cleanup_push((void *)pthread_mutex_unlock, (void *)(dt->mtx)); 2662c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 2672c28215423293e443469a07ae7011135d058b671Garrett Cooper 2682c28215423293e443469a07ae7011135d058b671Garrett Cooper /* This thread is ready to wait */ 2692c28215423293e443469a07ae7011135d058b671Garrett Cooper *(dt->tnum) += 1; 2702c28215423293e443469a07ae7011135d058b671Garrett Cooper 271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao do { 272354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ret = pthread_cond_wait(dt->cnd, dt->mtx); 273354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2742c28215423293e443469a07ae7011135d058b671Garrett Cooper while ((ret == 0) && (*(dt->predicate) == 0)); 275354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "pthread_cond_wait failed in waiter"); 277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2782c28215423293e443469a07ae7011135d058b671Garrett Cooper#ifdef USE_CANCEL 279354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pthread_cleanup_pop(0); /* We could put 1 and avoid the next line, but we would miss the return code */ 2802c28215423293e443469a07ae7011135d058b671Garrett Cooper#endif 2812c28215423293e443469a07ae7011135d058b671Garrett Cooper 2822c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_unlock(dt->mtx); 283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 284354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Mutex unlock failed in waiter"); 285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2862c28215423293e443469a07ae7011135d058b671Garrett Cooper 2872c28215423293e443469a07ae7011135d058b671Garrett Cooper return NULL; 2882c28215423293e443469a07ae7011135d058b671Garrett Cooper} 2892c28215423293e443469a07ae7011135d058b671Garrett Cooper 2902c28215423293e443469a07ae7011135d058b671Garrett Cooper/**** do_threads_test 2912c28215423293e443469a07ae7011135d058b671Garrett Cooper * This function is responsible for all the testing with a given # of threads 2922c28215423293e443469a07ae7011135d058b671Garrett Cooper * nthreads is the amount of threads to create. 2932c28215423293e443469a07ae7011135d058b671Garrett Cooper * the return value is: 2942c28215423293e443469a07ae7011135d058b671Garrett Cooper * < 0 if function was not able to create enough threads. 2952c28215423293e443469a07ae7011135d058b671Garrett Cooper * cumulated # of nanoseconds otherwise. 2962c28215423293e443469a07ae7011135d058b671Garrett Cooper */ 2972c28215423293e443469a07ae7011135d058b671Garrett Cooperlong do_threads_test(int nthreads, mes_t * measure) 2982c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 2992c28215423293e443469a07ae7011135d058b671Garrett Cooper int ret; 3002c28215423293e443469a07ae7011135d058b671Garrett Cooper 3012c28215423293e443469a07ae7011135d058b671Garrett Cooper int scal, i, j; 3022c28215423293e443469a07ae7011135d058b671Garrett Cooper 3032c28215423293e443469a07ae7011135d058b671Garrett Cooper pthread_t *th; 3042c28215423293e443469a07ae7011135d058b671Garrett Cooper 3052c28215423293e443469a07ae7011135d058b671Garrett Cooper int s; 3062c28215423293e443469a07ae7011135d058b671Garrett Cooper pthread_mutexattr_t ma; 3072c28215423293e443469a07ae7011135d058b671Garrett Cooper pthread_condattr_t ca; 3082c28215423293e443469a07ae7011135d058b671Garrett Cooper 3092c28215423293e443469a07ae7011135d058b671Garrett Cooper pthread_cond_t cnd; 3102c28215423293e443469a07ae7011135d058b671Garrett Cooper pthread_mutex_t mtx; 3112c28215423293e443469a07ae7011135d058b671Garrett Cooper int predicate; 3122c28215423293e443469a07ae7011135d058b671Garrett Cooper int tnum; 3132c28215423293e443469a07ae7011135d058b671Garrett Cooper 3142c28215423293e443469a07ae7011135d058b671Garrett Cooper test_t td; 3152c28215423293e443469a07ae7011135d058b671Garrett Cooper 3162c28215423293e443469a07ae7011135d058b671Garrett Cooper struct timespec ts, ts_cumul; 3172c28215423293e443469a07ae7011135d058b671Garrett Cooper 3182c28215423293e443469a07ae7011135d058b671Garrett Cooper td.mtx = &mtx; 3192c28215423293e443469a07ae7011135d058b671Garrett Cooper td.cnd = &cnd; 3202c28215423293e443469a07ae7011135d058b671Garrett Cooper td.predicate = &predicate; 3212c28215423293e443469a07ae7011135d058b671Garrett Cooper td.tnum = &tnum; 3222c28215423293e443469a07ae7011135d058b671Garrett Cooper 3232c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Allocate space for the threads structures */ 324354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao th = (pthread_t *) calloc(nthreads, sizeof(pthread_t)); 325354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (th == NULL) { 326354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(errno, "Not enough memory for thread storage"); 327354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifdef PLOT_OUTPUT 3292c28215423293e443469a07ae7011135d058b671Garrett Cooper output("%d", nthreads); 330354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 3312c28215423293e443469a07ae7011135d058b671Garrett Cooper /* For each test scenario (mutex and cond attributes) */ 332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (s = 0; s < NSCENAR; s++) { 3332c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Initialize the attributes */ 3342c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutexattr_init(&ma); 335354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 336354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to initialize mutex attribute object"); 338354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3392c28215423293e443469a07ae7011135d058b671Garrett Cooper 3402c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_condattr_init(&ca); 341354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 342354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 343354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to initialize cond attribute object"); 344354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3452c28215423293e443469a07ae7011135d058b671Garrett Cooper 3462c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Set the attributes according to the scenar and the impl capabilities */ 3472c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutexattr_settype(&ma, test_scenar[s].mutex_type); 348354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 349354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to set mutex type"); 350354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3512c28215423293e443469a07ae7011135d058b671Garrett Cooper 352354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (pshared_ok > 0) { 353354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ret = 354354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pthread_mutexattr_setpshared(&ma, 355354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao test_scenar[s]. 356354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pshared); 357354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 358354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 359354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to set mutex process-shared"); 360354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3612c28215423293e443469a07ae7011135d058b671Garrett Cooper 362354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ret = 363354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pthread_condattr_setpshared(&ca, 364354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao test_scenar[s].pshared); 365354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 366354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 367354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to set cond process-shared"); 368354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3692c28215423293e443469a07ae7011135d058b671Garrett Cooper } 370354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifdef USE_ALTCLK 371354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (altclk_ok > 0) { 372354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ret = 373354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pthread_condattr_setclock(&ca, test_scenar[s].cid); 374354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 375354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to set clock for cond"); 376354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3772c28215423293e443469a07ae7011135d058b671Garrett Cooper } 378354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 3792c28215423293e443469a07ae7011135d058b671Garrett Cooper 380354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ts_cumul.tv_sec = 0; 381354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ts_cumul.tv_nsec = 0; 3822c28215423293e443469a07ae7011135d058b671Garrett Cooper 383354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 3842c28215423293e443469a07ae7011135d058b671Garrett Cooper output("Starting case %s\n", test_scenar[s].desc); 385354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 3862c28215423293e443469a07ae7011135d058b671Garrett Cooper 387354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (scal = 0; scal < 5 * SCALABILITY_FACTOR; scal++) { 3882c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Initialize the mutex, the cond, and other data */ 3892c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_init(&mtx, &ma); 390354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 391354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Mutex init failed"); 392354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3932c28215423293e443469a07ae7011135d058b671Garrett Cooper 3942c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_cond_init(&cnd, &ca); 395354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 396354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Cond init failed"); 397354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3982c28215423293e443469a07ae7011135d058b671Garrett Cooper 3992c28215423293e443469a07ae7011135d058b671Garrett Cooper predicate = 0; 4002c28215423293e443469a07ae7011135d058b671Garrett Cooper tnum = 0; 4012c28215423293e443469a07ae7011135d058b671Garrett Cooper 4022c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Create the waiter threads */ 403354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < nthreads; i++) { 404354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ret = 405354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pthread_create(&th[i], &ta, waiter, 406354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (void *)&td); 407354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { /* We reached the limits */ 408354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 409354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output 410354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Limit reached with %i threads\n", 411354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao i); 412354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 413354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifdef USE_CANCEL 414354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (j = i - 1; j >= 0; j--) { 4152c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_cancel(th[j]); 416354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 417354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 418354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to cancel a thread"); 419354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 4202c28215423293e443469a07ae7011135d058b671Garrett Cooper } 421354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#else 4222c28215423293e443469a07ae7011135d058b671Garrett Cooper predicate = 1; 4232c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_cond_broadcast(&cnd); 424354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 425354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 426354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to broadcast the condition"); 427354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 428354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 429354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (j = i - 1; j >= 0; j--) { 4302c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_join(th[j], NULL); 431354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 432354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 433354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to join a canceled thread"); 434354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 4352c28215423293e443469a07ae7011135d058b671Garrett Cooper } 4362c28215423293e443469a07ae7011135d058b671Garrett Cooper free(th); 4372c28215423293e443469a07ae7011135d058b671Garrett Cooper return -1; 4382c28215423293e443469a07ae7011135d058b671Garrett Cooper } 4392c28215423293e443469a07ae7011135d058b671Garrett Cooper } 4402c28215423293e443469a07ae7011135d058b671Garrett Cooper /* All waiter threads are created now */ 441354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 5 4422c28215423293e443469a07ae7011135d058b671Garrett Cooper output("%i waiter threads created successfully\n", i); 443354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 4442c28215423293e443469a07ae7011135d058b671Garrett Cooper 4452c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_lock(&mtx); 446354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 447354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to lock mutex"); 448354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 4492c28215423293e443469a07ae7011135d058b671Garrett Cooper 4502c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Wait for all threads be waiting */ 451354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while (tnum < nthreads) { 4522c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_unlock(&mtx); 453354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 454354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Mutex unlock failed"); 455354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 4562c28215423293e443469a07ae7011135d058b671Garrett Cooper 4572c28215423293e443469a07ae7011135d058b671Garrett Cooper sched_yield(); 4582c28215423293e443469a07ae7011135d058b671Garrett Cooper 4592c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_lock(&mtx); 460354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 461354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Mutex lock failed"); 462354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 4632c28215423293e443469a07ae7011135d058b671Garrett Cooper } 4642c28215423293e443469a07ae7011135d058b671Garrett Cooper 4652c28215423293e443469a07ae7011135d058b671Garrett Cooper /* All threads are now waiting - we do the measure */ 4662c28215423293e443469a07ae7011135d058b671Garrett Cooper 4672c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_unlock(&mtx); 468354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 469354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Mutex unlock failed"); 470354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 471354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 5 472354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output("%i waiter threads are waiting; start measure\n", 473354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao tnum); 474354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 4752c28215423293e443469a07ae7011135d058b671Garrett Cooper 4762c28215423293e443469a07ae7011135d058b671Garrett Cooper do_measure(&mtx, &cnd, test_scenar[s].cid, &ts); 4772c28215423293e443469a07ae7011135d058b671Garrett Cooper 478354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 5 479354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output("Measure for %s returned %d.%09d\n", 480354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao test_scenar[s].desc, ts.tv_sec, ts.tv_nsec); 481354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 4822c28215423293e443469a07ae7011135d058b671Garrett Cooper 4832c28215423293e443469a07ae7011135d058b671Garrett Cooper ts_cumul.tv_sec += ts.tv_sec; 4842c28215423293e443469a07ae7011135d058b671Garrett Cooper ts_cumul.tv_nsec += ts.tv_nsec; 485354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ts_cumul.tv_nsec >= 1000000000) { 4862c28215423293e443469a07ae7011135d058b671Garrett Cooper ts_cumul.tv_nsec -= 1000000000; 4872c28215423293e443469a07ae7011135d058b671Garrett Cooper ts_cumul.tv_sec += 1; 4882c28215423293e443469a07ae7011135d058b671Garrett Cooper } 4892c28215423293e443469a07ae7011135d058b671Garrett Cooper 4902c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We can release the threads */ 4912c28215423293e443469a07ae7011135d058b671Garrett Cooper predicate = 1; 4922c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_cond_broadcast(&cnd); 493354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 494354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 495354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to broadcast the condition"); 496354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 497354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 5 4982c28215423293e443469a07ae7011135d058b671Garrett Cooper output("Joining the waiters...\n"); 499354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 5002c28215423293e443469a07ae7011135d058b671Garrett Cooper 5012c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We will join every threads */ 502354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < nthreads; i++) { 5032c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_join(th[i], NULL); 504354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 505354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, 506354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to join a thread"); 507354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 5082c28215423293e443469a07ae7011135d058b671Garrett Cooper 5092c28215423293e443469a07ae7011135d058b671Garrett Cooper } 5102c28215423293e443469a07ae7011135d058b671Garrett Cooper 5112c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Destroy everything */ 5122c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutex_destroy(&mtx); 513354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 514354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to destroy mutex"); 515354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 5162c28215423293e443469a07ae7011135d058b671Garrett Cooper 5172c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_cond_destroy(&cnd); 518354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 519354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to destroy cond"); 520354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 5212c28215423293e443469a07ae7011135d058b671Garrett Cooper } 5222c28215423293e443469a07ae7011135d058b671Garrett Cooper 523354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifdef PLOT_OUTPUT 5242c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" %d.%09d", ts_cumul.tv_sec, ts_cumul.tv_nsec); 525354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 5262c28215423293e443469a07ae7011135d058b671Garrett Cooper 527354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao measure->_data[s] = ts_cumul.tv_sec * 1000000 + (ts_cumul.tv_nsec / 1000); /* We reduce precision */ 5282c28215423293e443469a07ae7011135d058b671Garrett Cooper 5292c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Destroy the mutex attributes */ 5302c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_mutexattr_destroy(&ma); 531354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 532354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to destroy mutex attribute"); 533354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 5342c28215423293e443469a07ae7011135d058b671Garrett Cooper 5352c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_condattr_destroy(&ca); 536354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 537354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to destroy cond attribute"); 538354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 5392c28215423293e443469a07ae7011135d058b671Garrett Cooper } 5402c28215423293e443469a07ae7011135d058b671Garrett Cooper 5412c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Free the memory */ 5422c28215423293e443469a07ae7011135d058b671Garrett Cooper free(th); 5432c28215423293e443469a07ae7011135d058b671Garrett Cooper 544354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 2 545354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output("%5d threads; %d.%09d s (%i loops)\n", nthreads, ts_cumul.tv_sec, 546354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ts_cumul.tv_nsec, scal); 547354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 5482c28215423293e443469a07ae7011135d058b671Garrett Cooper 549354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifdef PLOT_OUTPUT 5502c28215423293e443469a07ae7011135d058b671Garrett Cooper output("\n"); 551354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 5522c28215423293e443469a07ae7011135d058b671Garrett Cooper 5532c28215423293e443469a07ae7011135d058b671Garrett Cooper return ts_cumul.tv_sec * 1000000000 + ts_cumul.tv_nsec; 5542c28215423293e443469a07ae7011135d058b671Garrett Cooper} 5552c28215423293e443469a07ae7011135d058b671Garrett Cooper 5562c28215423293e443469a07ae7011135d058b671Garrett Cooper/* Forward declaration */ 5572c28215423293e443469a07ae7011135d058b671Garrett Cooperint parse_measure(mes_t * measures); 5582c28215423293e443469a07ae7011135d058b671Garrett Cooper 5592c28215423293e443469a07ae7011135d058b671Garrett Cooper/* Main 5602c28215423293e443469a07ae7011135d058b671Garrett Cooper */ 561354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint main(int argc, char *argv[]) 5622c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 5632c28215423293e443469a07ae7011135d058b671Garrett Cooper int ret, nth; 5642c28215423293e443469a07ae7011135d058b671Garrett Cooper long dur; 5652c28215423293e443469a07ae7011135d058b671Garrett Cooper 5662c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Initialize the measure list */ 5672c28215423293e443469a07ae7011135d058b671Garrett Cooper mes_t sentinel; 5682c28215423293e443469a07ae7011135d058b671Garrett Cooper mes_t *m_cur, *m_tmp; 5692c28215423293e443469a07ae7011135d058b671Garrett Cooper m_cur = &sentinel; 5702c28215423293e443469a07ae7011135d058b671Garrett Cooper m_cur->next = NULL; 5712c28215423293e443469a07ae7011135d058b671Garrett Cooper 5722c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Initialize the output */ 5732c28215423293e443469a07ae7011135d058b671Garrett Cooper output_init(); 5742c28215423293e443469a07ae7011135d058b671Garrett Cooper 5752c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Test machine capabilities */ 5762c28215423293e443469a07ae7011135d058b671Garrett Cooper /* -> clockid_t; pshared; ... */ 5772c28215423293e443469a07ae7011135d058b671Garrett Cooper altclk_ok = sysconf(_SC_CLOCK_SELECTION); 5782c28215423293e443469a07ae7011135d058b671Garrett Cooper if (altclk_ok > 0) 5792c28215423293e443469a07ae7011135d058b671Garrett Cooper altclk_ok = sysconf(_SC_MONOTONIC_CLOCK); 580354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifndef USE_ALTCLK 5812c28215423293e443469a07ae7011135d058b671Garrett Cooper if (altclk_ok > 0) 582354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output 583354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("Implementation supports the MONOTONIC CLOCK but option is disabled in test.\n"); 584354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 5852c28215423293e443469a07ae7011135d058b671Garrett Cooper 5862c28215423293e443469a07ae7011135d058b671Garrett Cooper pshared_ok = sysconf(_SC_THREAD_PROCESS_SHARED); 5872c28215423293e443469a07ae7011135d058b671Garrett Cooper 588354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 0 5892c28215423293e443469a07ae7011135d058b671Garrett Cooper output("Test starting\n"); 590354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output(" Process-shared primitive %s be tested\n", 591354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (pshared_ok > 0) ? "will" : "won't"); 592354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output(" Alternative clock for cond %s be tested\n", 593354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (altclk_ok > 0) ? "will" : "won't"); 594354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 5952c28215423293e443469a07ae7011135d058b671Garrett Cooper 5962c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Prepare thread attribute */ 5972c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_attr_init(&ta); 598354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 599354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to initialize thread attributes"); 600354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 6012c28215423293e443469a07ae7011135d058b671Garrett Cooper 6022c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = pthread_attr_setstacksize(&ta, sysconf(_SC_THREAD_STACK_MIN)); 603354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 604354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(ret, "Unable to set stack size to minimum value"); 605354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 606354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#ifdef PLOT_OUTPUT 6072c28215423293e443469a07ae7011135d058b671Garrett Cooper output("# COLUMNS %d #threads", NSCENAR + 1); 608354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (nth = 0; nth < NSCENAR; nth++) 6092c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" %s", test_scenar[nth].desc); 6102c28215423293e443469a07ae7011135d058b671Garrett Cooper output("\n"); 611354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 6122c28215423293e443469a07ae7011135d058b671Garrett Cooper 6132c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Do the testing */ 6142c28215423293e443469a07ae7011135d058b671Garrett Cooper nth = 0; 615354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao do { 6162c28215423293e443469a07ae7011135d058b671Garrett Cooper nth += 100 * SCALABILITY_FACTOR; 6172c28215423293e443469a07ae7011135d058b671Garrett Cooper 6182c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Create a new measure item */ 619d218f348c12b42a78fa0306d9a033bfa4f67238bCyril Hrubis m_tmp = malloc(sizeof(mes_t)); 620354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (m_tmp == NULL) { 621354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(errno, 622354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Unable to alloc memory for measure saving"); 623354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 6242c28215423293e443469a07ae7011135d058b671Garrett Cooper m_tmp->nthreads = nth; 6252c28215423293e443469a07ae7011135d058b671Garrett Cooper m_tmp->next = NULL; 6262c28215423293e443469a07ae7011135d058b671Garrett Cooper 6272c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Run the test */ 6282c28215423293e443469a07ae7011135d058b671Garrett Cooper dur = do_threads_test(nth, m_tmp); 6292c28215423293e443469a07ae7011135d058b671Garrett Cooper 6302c28215423293e443469a07ae7011135d058b671Garrett Cooper /* If test was success, add this measure to the list. Otherwise, free the mem */ 631354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (dur >= 0) { 6322c28215423293e443469a07ae7011135d058b671Garrett Cooper m_cur->next = m_tmp; 6332c28215423293e443469a07ae7011135d058b671Garrett Cooper m_cur = m_tmp; 634354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 6352c28215423293e443469a07ae7011135d058b671Garrett Cooper free(m_tmp); 6362c28215423293e443469a07ae7011135d058b671Garrett Cooper } 6372c28215423293e443469a07ae7011135d058b671Garrett Cooper } 6382c28215423293e443469a07ae7011135d058b671Garrett Cooper while (dur >= 0); 6392c28215423293e443469a07ae7011135d058b671Garrett Cooper 6402c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We will now parse the results to determine if the measure is ~ constant or is growing. */ 6412c28215423293e443469a07ae7011135d058b671Garrett Cooper 6422c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = parse_measure(&sentinel); 6432c28215423293e443469a07ae7011135d058b671Garrett Cooper 6442c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Free the memory from the list */ 6452c28215423293e443469a07ae7011135d058b671Garrett Cooper m_cur = sentinel.next; 646354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while (m_cur != NULL) { 6472c28215423293e443469a07ae7011135d058b671Garrett Cooper m_tmp = m_cur; 6482c28215423293e443469a07ae7011135d058b671Garrett Cooper m_cur = m_tmp->next; 6492c28215423293e443469a07ae7011135d058b671Garrett Cooper free(m_tmp); 6502c28215423293e443469a07ae7011135d058b671Garrett Cooper } 6512c28215423293e443469a07ae7011135d058b671Garrett Cooper 652354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret != 0) { 6532c28215423293e443469a07ae7011135d058b671Garrett Cooper FAILED("This function is not scalable"); 6542c28215423293e443469a07ae7011135d058b671Garrett Cooper } 655354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 0 6562c28215423293e443469a07ae7011135d058b671Garrett Cooper output("The function is scalable\n"); 657354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 6582c28215423293e443469a07ae7011135d058b671Garrett Cooper 6592c28215423293e443469a07ae7011135d058b671Garrett Cooper PASSED; 6602c28215423293e443469a07ae7011135d058b671Garrett Cooper} 6612c28215423293e443469a07ae7011135d058b671Garrett Cooper 6622c28215423293e443469a07ae7011135d058b671Garrett Cooper/*** 6632c28215423293e443469a07ae7011135d058b671Garrett Cooper * The next function will seek for the better model for each series of measurements. 6642c28215423293e443469a07ae7011135d058b671Garrett Cooper * 6652c28215423293e443469a07ae7011135d058b671Garrett Cooper * The tested models are: -- X = # threads; Y = latency 6662c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> Y = a; -- Error is r1 = avg((Y - Yavg)²); 6672c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> Y = aX + b; -- Error is r2 = avg((Y -aX -b)²); 6682c28215423293e443469a07ae7011135d058b671Garrett Cooper * -- where a = avg ((X - Xavg)(Y - Yavg)) / avg((X - Xavg)²) 6692c28215423293e443469a07ae7011135d058b671Garrett Cooper * -- Note: We will call _q = sum((X - Xavg) * (Y - Yavg)); 6702c28215423293e443469a07ae7011135d058b671Garrett Cooper * -- and _d = sum((X - Xavg)²); 6712c28215423293e443469a07ae7011135d058b671Garrett Cooper * -- and b = Yavg - a * Xavg 6722c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> Y = c * X^a;-- Same as previous, but with log(Y) = a log(X) + b; and b = log(c). Error is r3 6732c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> Y = exp(aX + b); -- log(Y) = aX + b. Error is r4 6742c28215423293e443469a07ae7011135d058b671Garrett Cooper * 6752c28215423293e443469a07ae7011135d058b671Garrett Cooper * We compute each error factor (r1, r2, r3, r4) then search which is the smallest (with ponderation). 6762c28215423293e443469a07ae7011135d058b671Garrett Cooper * The function returns 0 when r1 is the best for all cases (latency is constant) and !0 otherwise. 6772c28215423293e443469a07ae7011135d058b671Garrett Cooper */ 6782c28215423293e443469a07ae7011135d058b671Garrett Cooper 679354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostruct row { 680354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao long X; /* the X values -- copied from function argument */ 681354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao long Y[NSCENAR]; /* the Y values -- copied from function argument */ 682354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao long _x; /* Value X - Xavg */ 683354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao long _y[NSCENAR]; /* Value Y - Yavg */ 684354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao double LnX; /* Natural logarithm of X values */ 685354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao double LnY[NSCENAR]; /* Natural logarithm of Y values */ 686354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao double _lnx; /* Value LnX - LnXavg */ 687354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao double _lny[NSCENAR]; /* Value LnY - LnYavg */ 6882c28215423293e443469a07ae7011135d058b671Garrett Cooper}; 6892c28215423293e443469a07ae7011135d058b671Garrett Cooper 6902c28215423293e443469a07ae7011135d058b671Garrett Cooperint parse_measure(mes_t * measures) 6912c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 6922c28215423293e443469a07ae7011135d058b671Garrett Cooper int ret, i, r; 6932c28215423293e443469a07ae7011135d058b671Garrett Cooper 6942c28215423293e443469a07ae7011135d058b671Garrett Cooper mes_t *cur; 6952c28215423293e443469a07ae7011135d058b671Garrett Cooper 6962c28215423293e443469a07ae7011135d058b671Garrett Cooper double Xavg, Yavg[NSCENAR]; 6972c28215423293e443469a07ae7011135d058b671Garrett Cooper double LnXavg, LnYavg[NSCENAR]; 6982c28215423293e443469a07ae7011135d058b671Garrett Cooper 6992c28215423293e443469a07ae7011135d058b671Garrett Cooper int N; 7002c28215423293e443469a07ae7011135d058b671Garrett Cooper 7012c28215423293e443469a07ae7011135d058b671Garrett Cooper double r1[NSCENAR], r2[NSCENAR], r3[NSCENAR], r4[NSCENAR]; 7022c28215423293e443469a07ae7011135d058b671Garrett Cooper 7032c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Some more intermediate vars */ 7042c28215423293e443469a07ae7011135d058b671Garrett Cooper long double _q[3][NSCENAR]; 7052c28215423293e443469a07ae7011135d058b671Garrett Cooper long double _d[3][NSCENAR]; 7062c28215423293e443469a07ae7011135d058b671Garrett Cooper 707354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao long double t; /* temp value */ 7082c28215423293e443469a07ae7011135d058b671Garrett Cooper 7092c28215423293e443469a07ae7011135d058b671Garrett Cooper struct row *Table = NULL; 7102c28215423293e443469a07ae7011135d058b671Garrett Cooper 7112c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Initialize the datas */ 7122c28215423293e443469a07ae7011135d058b671Garrett Cooper Xavg = 0.0; 7132c28215423293e443469a07ae7011135d058b671Garrett Cooper LnXavg = 0.0; 714354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < NSCENAR; i++) { 7152c28215423293e443469a07ae7011135d058b671Garrett Cooper Yavg[i] = 0.0; 7162c28215423293e443469a07ae7011135d058b671Garrett Cooper LnYavg[i] = 0.0; 7172c28215423293e443469a07ae7011135d058b671Garrett Cooper r1[i] = 0.0; 7182c28215423293e443469a07ae7011135d058b671Garrett Cooper r2[i] = 0.0; 7192c28215423293e443469a07ae7011135d058b671Garrett Cooper r3[i] = 0.0; 7202c28215423293e443469a07ae7011135d058b671Garrett Cooper r4[i] = 0.0; 721354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao _q[0][i] = 0.0; 722354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao _q[1][i] = 0.0; 723354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao _q[2][i] = 0.0; 724354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao _d[0][i] = 0.0; 725354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao _d[1][i] = 0.0; 726354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao _d[2][i] = 0.0; 7272c28215423293e443469a07ae7011135d058b671Garrett Cooper } 728354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao N = 0; 7292c28215423293e443469a07ae7011135d058b671Garrett Cooper cur = measures; 7302c28215423293e443469a07ae7011135d058b671Garrett Cooper 731354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 7322c28215423293e443469a07ae7011135d058b671Garrett Cooper output("Data analysis starting\n"); 733354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 7342c28215423293e443469a07ae7011135d058b671Garrett Cooper 7352c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We start with reading the list to find: 7362c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> number of elements, to assign an array 7372c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> average values 7382c28215423293e443469a07ae7011135d058b671Garrett Cooper */ 739354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while (cur->next != NULL) { 7402c28215423293e443469a07ae7011135d058b671Garrett Cooper cur = cur->next; 7412c28215423293e443469a07ae7011135d058b671Garrett Cooper 7422c28215423293e443469a07ae7011135d058b671Garrett Cooper N++; 7432c28215423293e443469a07ae7011135d058b671Garrett Cooper 744354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao Xavg += (double)cur->nthreads; 745354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao LnXavg += log((double)cur->nthreads); 7462c28215423293e443469a07ae7011135d058b671Garrett Cooper 747354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < NSCENAR; i++) { 748354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao Yavg[i] += (double)cur->_data[i]; 749354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao LnYavg[i] += log((double)cur->_data[i]); 7502c28215423293e443469a07ae7011135d058b671Garrett Cooper } 7512c28215423293e443469a07ae7011135d058b671Garrett Cooper } 7522c28215423293e443469a07ae7011135d058b671Garrett Cooper 7532c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We have the sum; we can divide to obtain the average values */ 7542c28215423293e443469a07ae7011135d058b671Garrett Cooper Xavg /= N; 7552c28215423293e443469a07ae7011135d058b671Garrett Cooper LnXavg /= N; 7562c28215423293e443469a07ae7011135d058b671Garrett Cooper 757354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < NSCENAR; i++) { 7582c28215423293e443469a07ae7011135d058b671Garrett Cooper Yavg[i] /= N; 7592c28215423293e443469a07ae7011135d058b671Garrett Cooper LnYavg[i] /= N; 7602c28215423293e443469a07ae7011135d058b671Garrett Cooper } 7612c28215423293e443469a07ae7011135d058b671Garrett Cooper 762354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 7632c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Found %d rows and %d columns\n", N, NSCENAR); 764354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 7652c28215423293e443469a07ae7011135d058b671Garrett Cooper 7662c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We will now alloc the array ... */ 7672c28215423293e443469a07ae7011135d058b671Garrett Cooper Table = calloc(N, sizeof(struct row)); 768354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (Table == NULL) { 769354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao UNRESOLVED(errno, "Unable to alloc space for results parsing"); 770354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 7712c28215423293e443469a07ae7011135d058b671Garrett Cooper 7722c28215423293e443469a07ae7011135d058b671Garrett Cooper /* ... and fill it */ 7732c28215423293e443469a07ae7011135d058b671Garrett Cooper N = 0; 7742c28215423293e443469a07ae7011135d058b671Garrett Cooper cur = measures; 7752c28215423293e443469a07ae7011135d058b671Garrett Cooper 776354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while (cur->next != NULL) { 7772c28215423293e443469a07ae7011135d058b671Garrett Cooper cur = cur->next; 7782c28215423293e443469a07ae7011135d058b671Garrett Cooper 779354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao Table[N].X = (long)cur->nthreads; 780354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao Table[N]._x = Table[N].X - Xavg; 781354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao Table[N].LnX = log((double)cur->nthreads); 7822c28215423293e443469a07ae7011135d058b671Garrett Cooper Table[N]._lnx = Table[N].LnX - LnXavg; 783354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < NSCENAR; i++) { 7842c28215423293e443469a07ae7011135d058b671Garrett Cooper Table[N].Y[i] = cur->_data[i]; 785354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao Table[N]._y[i] = Table[N].Y[i] - Yavg[i]; 786354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao Table[N].LnY[i] = log((double)cur->_data[i]); 7872c28215423293e443469a07ae7011135d058b671Garrett Cooper Table[N]._lny[i] = Table[N].LnY[i] - LnYavg[i]; 7882c28215423293e443469a07ae7011135d058b671Garrett Cooper } 7892c28215423293e443469a07ae7011135d058b671Garrett Cooper 7902c28215423293e443469a07ae7011135d058b671Garrett Cooper N++; 7912c28215423293e443469a07ae7011135d058b671Garrett Cooper } 7922c28215423293e443469a07ae7011135d058b671Garrett Cooper 7932c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We won't need the list anymore -- we'll work with the array which should be faster. */ 794354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 7952c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Data was stored in an array.\n"); 796354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 7972c28215423293e443469a07ae7011135d058b671Garrett Cooper 7982c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We need to read the full array at least twice to compute all the error factors */ 7992c28215423293e443469a07ae7011135d058b671Garrett Cooper 8002c28215423293e443469a07ae7011135d058b671Garrett Cooper /* In the first pass, we'll compute: 8012c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> r1 for each scenar. 8022c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> "a" factor for linear (0), power (1) and exponential (2) approximations -- with using the _d and _q vars. 8032c28215423293e443469a07ae7011135d058b671Garrett Cooper */ 804354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 8052c28215423293e443469a07ae7011135d058b671Garrett Cooper output("Starting first pass...\n"); 806354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 807354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (r = 0; r < N; r++) { 808354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < NSCENAR; i++) { 809354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao r1[i] += 810354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ((double)Table[r]._y[i] / N) * 811354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (double)Table[r]._y[i]; 8122c28215423293e443469a07ae7011135d058b671Garrett Cooper 8132c28215423293e443469a07ae7011135d058b671Garrett Cooper _q[0][i] += Table[r]._y[i] * Table[r]._x; 8142c28215423293e443469a07ae7011135d058b671Garrett Cooper _d[0][i] += Table[r]._x * Table[r]._x; 8152c28215423293e443469a07ae7011135d058b671Garrett Cooper 8162c28215423293e443469a07ae7011135d058b671Garrett Cooper _q[1][i] += Table[r]._lny[i] * Table[r]._lnx; 8172c28215423293e443469a07ae7011135d058b671Garrett Cooper _d[1][i] += Table[r]._lnx * Table[r]._lnx; 8182c28215423293e443469a07ae7011135d058b671Garrett Cooper 8192c28215423293e443469a07ae7011135d058b671Garrett Cooper _q[2][i] += Table[r]._lny[i] * Table[r]._x; 8202c28215423293e443469a07ae7011135d058b671Garrett Cooper _d[2][i] += Table[r]._x * Table[r]._x; 8212c28215423293e443469a07ae7011135d058b671Garrett Cooper } 8222c28215423293e443469a07ae7011135d058b671Garrett Cooper } 8232c28215423293e443469a07ae7011135d058b671Garrett Cooper 8242c28215423293e443469a07ae7011135d058b671Garrett Cooper /* First pass is terminated; a2 = _q[0]/_d[0]; a3 = _q[1]/_d[1]; a4 = _q[2]/_d[2] */ 8252c28215423293e443469a07ae7011135d058b671Garrett Cooper 8262c28215423293e443469a07ae7011135d058b671Garrett Cooper /* In the first pass, we'll compute: 8272c28215423293e443469a07ae7011135d058b671Garrett Cooper * -> r2, r3, r4 for each scenar. 8282c28215423293e443469a07ae7011135d058b671Garrett Cooper */ 8292c28215423293e443469a07ae7011135d058b671Garrett Cooper 830354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 8312c28215423293e443469a07ae7011135d058b671Garrett Cooper output("Starting second pass...\n"); 832354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 833354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (r = 0; r < N; r++) { 834354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < NSCENAR; i++) { 8352c28215423293e443469a07ae7011135d058b671Garrett Cooper /* r2 = avg((y - ax -b)²); t = (y - ax - b) = (y - yavg) - a (x - xavg); */ 836354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao t = (Table[r]._y[i] - 837354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ((_q[0][i] * Table[r]._x) / _d[0][i])); 838354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao r2[i] += t * t / N; 8392c28215423293e443469a07ae7011135d058b671Garrett Cooper 8402c28215423293e443469a07ae7011135d058b671Garrett Cooper /* r3 = avg((y - c.x^a) ²); 841354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao t = y - c * x ^ a 842354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao = y - log (LnYavg - (_q[1]/_d[1]) * LnXavg) * x ^ (_q[1]/_d[1]) 843354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao */ 844354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao t = (Table[r].Y[i] 845354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao - (logl(LnYavg[i] - (_q[1][i] / _d[1][i]) * LnXavg) 846354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * powl(Table[r].X, (_q[1][i] / _d[1][i])) 847354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao )); 848354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao r3[i] += t * t / N; 8492c28215423293e443469a07ae7011135d058b671Garrett Cooper 8502c28215423293e443469a07ae7011135d058b671Garrett Cooper /* r4 = avg((y - exp(ax+b))²); 851354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao t = y - exp(ax+b) 852354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao = y - exp(_q[2]/_d[2] * x + (LnYavg - (_q[2]/_d[2] * Xavg))); 853354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao = y - exp(_q[2]/_d[2] * (x - Xavg) + LnYavg); 854354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao */ 855354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao t = (Table[r].Y[i] 856354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao - expl((_q[2][i] / _d[2][i]) * Table[r]._x + 857354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao LnYavg[i])); 858354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao r4[i] += t * t / N; 8592c28215423293e443469a07ae7011135d058b671Garrett Cooper 8602c28215423293e443469a07ae7011135d058b671Garrett Cooper } 8612c28215423293e443469a07ae7011135d058b671Garrett Cooper } 8622c28215423293e443469a07ae7011135d058b671Garrett Cooper 863354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 8642c28215423293e443469a07ae7011135d058b671Garrett Cooper output("All computing terminated.\n"); 865354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 8662c28215423293e443469a07ae7011135d058b671Garrett Cooper ret = 0; 867354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (i = 0; i < NSCENAR; i++) { 868354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 8692c28215423293e443469a07ae7011135d058b671Garrett Cooper output("\nScenario: %s\n", test_scenar[i].desc); 8702c28215423293e443469a07ae7011135d058b671Garrett Cooper 8712c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Model: Y = k\n"); 8722c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" k = %g\n", Yavg[i]); 8732c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Divergence %g\n", r1[i]); 8742c28215423293e443469a07ae7011135d058b671Garrett Cooper 8752c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Model: Y = a * X + b\n"); 8762c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" a = %Lg\n", _q[0][i] / _d[0][i]); 877354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output(" b = %Lg\n", 878354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao Yavg[i] - ((_q[0][i] / _d[0][i]) * Xavg)); 8792c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Divergence %g\n", r2[i]); 8802c28215423293e443469a07ae7011135d058b671Garrett Cooper 8812c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Model: Y = c * X ^ a\n"); 8822c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" a = %Lg\n", _q[1][i] / _d[1][i]); 883354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output(" c = %Lg\n", 884354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao logl(LnYavg[i] - (_q[1][i] / _d[1][i]) * LnXavg)); 8852c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Divergence %g\n", r2[i]); 8862c28215423293e443469a07ae7011135d058b671Garrett Cooper 8872c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Model: Y = exp(a * X + b)\n"); 8882c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" a = %Lg\n", _q[2][i] / _d[2][i]); 889354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao output(" b = %Lg\n", 890354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao LnYavg[i] - ((_q[2][i] / _d[2][i]) * Xavg)); 8912c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Divergence %g\n", r2[i]); 892354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 8932c28215423293e443469a07ae7011135d058b671Garrett Cooper /* Compare r1 to other values, with some ponderations */ 894354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((r1[i] > 1.1 * r2[i]) || (r1[i] > 1.2 * r3[i]) 895354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao || (r1[i] > 1.3 * r4[i])) 8962c28215423293e443469a07ae7011135d058b671Garrett Cooper ret++; 897354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#if VERBOSE > 1 8982c28215423293e443469a07ae7011135d058b671Garrett Cooper else 8992c28215423293e443469a07ae7011135d058b671Garrett Cooper output(" Sanction: OK\n"); 900354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao#endif 9012c28215423293e443469a07ae7011135d058b671Garrett Cooper } 9022c28215423293e443469a07ae7011135d058b671Garrett Cooper 9032c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We need to free the array */ 9042c28215423293e443469a07ae7011135d058b671Garrett Cooper free(Table); 9052c28215423293e443469a07ae7011135d058b671Garrett Cooper 9062c28215423293e443469a07ae7011135d058b671Garrett Cooper /* We're done */ 9072c28215423293e443469a07ae7011135d058b671Garrett Cooper return ret; 908ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman} 909