1 /* 2 * Copyright (c) Bull S.A. 2007 All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * History: 24 * Created by: Cyril Lacabanne (Cyril.Lacabanne (at) bull.net) 25 * 26 */ 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <pthread.h> 31 #include <time.h> 32 #include <errno.h> 33 #include "lapi/rpc.h" 34 35 //Standard define 36 #define PROCNUM 1 37 #define VERSNUM 1 38 39 static double *thread_time_result; 40 static int maxThd = 1; 41 int run_mode; 42 int progNum; 43 int callNb; 44 char *nettype = "visible"; 45 char *hostname; 46 47 void *my_thread_process(void *arg) 48 { 49 int i; 50 CLIENT *clnt = NULL; 51 int sndVar = 0; 52 int recVar = -1; 53 struct timeval total_timeout; 54 55 if (run_mode == 1) { 56 fprintf(stderr, "Thread %ld\n", (long)arg); 57 } 58 //Initialisation 59 total_timeout.tv_sec = 1; 60 total_timeout.tv_usec = 1; 61 /**/ 62 //First of all, create client using top level API 63 clnt = clnt_create(hostname, progNum, VERSNUM, nettype); 64 65 if (clnt == NULL) { 66 printf("5\n"); 67 exit(5); 68 } 69 70 for (i = 0; i < callNb; i++) { 71 clnt_call((CLIENT *) clnt, PROCNUM, (xdrproc_t) xdr_int, (char *)&sndVar, // xdr_in 72 (xdrproc_t) xdr_int, (char *)&recVar, // xdr_out 73 total_timeout); 74 /**/} 75 76 clnt_destroy(clnt); 77 78 pthread_exit(0); 79 } 80 81 int main(int argn, char *argc[]) 82 { 83 //Program parameters : argc[1] : HostName or Host IP 84 // argc[2] : Server Program Number 85 // argc[3] : Maximal number of threads 86 // argc[4] : Number of calls per thread 87 // other arguments depend on test case 88 89 //run_mode can switch into stand alone program or program launch by shell script 90 //1 : stand alone, debug mode, more screen information 91 //0 : launch by shell script as test case, only one printf -> result status 92 run_mode = 0; 93 int test_status = 1; //Default test result set to FAILED 94 int i; 95 long j; 96 int threadNb = atoi((char *)argc[3]); 97 int curThd = 1; 98 99 //Thread declarations 100 pthread_t *pThreadArray; 101 void *ret = NULL; 102 pthread_attr_t thread_attr; 103 int ssz = 0; 104 105 //Time measurement declarations 106 struct timeval tv1, tv2; 107 struct timezone tz; 108 long long diff; 109 double rslt; 110 111 //Program initialization 112 progNum = atoi((char *)argc[2]); 113 callNb = atoi((char *)argc[4]); 114 hostname = (char *)argc[1]; 115 116 //Initialization 117 maxThd = maxThd << (threadNb - 1); //Set the maximum threads number 118 119 pthread_attr_init(&thread_attr); 120 121 if (run_mode == 1) { 122 pthread_attr_getstacksize(&thread_attr, (size_t *) & ssz); //For debug purpose, get default thread stack size 123 fprintf(stderr, "Server #%d\n", progNum); 124 fprintf(stderr, "Calls per thread : %d\n", callNb); 125 fprintf(stderr, "Instances : %d\n", threadNb); 126 fprintf(stderr, "Max threads to create : %d\n", maxThd); 127 fprintf(stderr, "Standard thread stack size in bytes %d\n", 128 ssz); 129 } 130 131 pthread_attr_setstacksize(&thread_attr, 40000); //Set thread stack size to 40 KB 132 133 //Init results table 134 thread_time_result = malloc((threadNb) * sizeof(double)); 135 memset(&thread_time_result[0], (double)0, (threadNb) * sizeof(double)); 136 137 //Create all threads 138 //Run all threads 139 pThreadArray = malloc(maxThd * sizeof(pthread_t)); 140 141 for (i = 0; i < threadNb; i++) { 142 if (run_mode) 143 fprintf(stderr, "Threads for pass %d : %d\n", i, 144 curThd); 145 146 gettimeofday(&tv1, &tz); 147 148 for (j = 0; j < curThd; j++) { 149 //Create thread using defined parameters (stack size = 40 KB) 150 if (pthread_create 151 (&pThreadArray[j], &thread_attr, my_thread_process, 152 (void *)j) != 0) { 153 fprintf(stderr, 154 "pthread_create error for thread %ld\n", 155 j); 156 printf("1\n"); 157 exit(1); 158 } 159 } 160 161 //Clean threads 162 for (j = 0; j < curThd; j++) { 163 if ((pthread_t *) pThreadArray[j] != NULL) { 164 (void)pthread_join(pThreadArray[j], &ret); 165 } else { 166 fprintf(stderr, "pThread Join Err : %ld\n", j); 167 } 168 } 169 170 gettimeofday(&tv2, &tz); 171 172 //Calculate and store delay to table results 173 diff = 174 (tv2.tv_sec - tv1.tv_sec) * 1000000L + (tv2.tv_usec - 175 tv1.tv_usec); 176 rslt = (double)diff / 1000; 177 thread_time_result[i] = rslt; 178 179 curThd = curThd * 2; 180 } 181 182 //Check if all threads results are ok 183 test_status = 0; 184 for (i = 0; i < threadNb; i++) { 185 if (thread_time_result[i] == 0) { 186 test_status = 1; 187 break; 188 } 189 } 190 191 //This last printf gives the result status to the tests suite 192 //normally should be 0: test has passed or 1: test has failed 193 printf("%d\n", test_status); 194 195 //Print scalability results 196 curThd = 1; 197 for (i = 0; i < threadNb; i++) { 198 printf("%d %lf\n", curThd, thread_time_result[i]); 199 curThd = curThd * 2; 200 } 201 202 return test_status; 203 } 204