1 /*---------------------------------------------------------------
2 * Copyright (c) 1999,2000,2001,2002,2003
3 * The Board of Trustees of the University of Illinois
5 *---------------------------------------------------------------
6 * Permission is hereby granted, free of charge, to any person
7 * obtaining a copy of this software (Iperf) and associated
8 * documentation files (the "Software"), to deal in the Software
9 * without restriction, including without limitation the
10 * rights to use, copy, modify, merge, publish, distribute,
11 * sublicense, and/or sell copies of the Software, and to permit
12 * persons to whom the Software is furnished to do
13 * so, subject to the following conditions:
16 * Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and
18 * the following disclaimers.
21 * Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimers in the documentation and/or other materials
24 * provided with the distribution.
27 * Neither the names of the University of Illinois, NCSA,
28 * nor the names of its contributors may be used to endorse
29 * or promote products derived from this Software without
30 * specific prior written permission.
32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
34 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT
36 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
37 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
38 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE
39 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 * ________________________________________________________________
41 * National Laboratory for Applied Network Research
42 * National Center for Supercomputing Applications
43 * University of Illinois at Urbana-Champaign
44 * http://www.ncsa.uiuc.edu
45 * ________________________________________________________________
47 * by Mark Gates <mgates@nlanr.net>
48 * & Ajay Tirumala <tirumala@ncsa.uiuc.edu>
49 * -------------------------------------------------------------------
50 * main does initialization and creates the various objects that will
51 * actually run the iperf program, then waits in the Joinall().
52 * -------------------------------------------------------------------
59 * ------------------------------------------------------------------- */
65 #include "Settings.hpp"
66 #include "PerfSocket.hpp"
68 #include "Condition.h"
69 #include "Timestamp.hpp"
70 #include "Listener.hpp"
74 /* -------------------------------------------------------------------
76 * ------------------------------------------------------------------- */
77 // Function called at exit to clean up as much as possible
80 /* -------------------------------------------------------------------
82 * ------------------------------------------------------------------- */
84 // Global flag to signal a user interrupt
86 // Global ID that we increment to be used
87 // as identifier for SUM reports
89 // Mutex to protect access to the above ID
91 // Condition used to signify advances of the current
92 // records being accessed in a report and also to
93 // serialize modification of the report list
95 Condition ReportDoneCond;
98 // global variables only accessed within this file
100 // Thread that received the SIGTERM or SIGINT signal
101 // Used to ensure that if multiple threads receive the
102 // signal we do not prematurely exit
104 // The main thread uses this function to wait
105 // for all other threads to complete
106 void waitUntilQuit( void );
108 /* -------------------------------------------------------------------
110 * Entry point into Iperf
112 * sets up signal handlers
113 * initialize global locks and conditions
114 * parses settings from environment and command line
115 * starts up server or client thread
116 * waits for all threads to complete
117 * ------------------------------------------------------------------- */
118 int main( int argc, char **argv ) {
120 // Set SIGTERM and SIGINT to call our user interrupt function
121 my_signal( SIGTERM, Sig_Interupt );
122 my_signal( SIGINT, Sig_Interupt );
125 // Initialize global mutexes and conditions
126 Condition_Initialize ( &ReportCond );
127 Condition_Initialize ( &ReportDoneCond );
128 Mutex_Initialize( &groupCond );
129 Mutex_Initialize( &clients_mutex );
131 // Initialize the thread subsystem
134 // Initialize the interrupt handling thread to 0
135 sThread = thread_zeroid();
137 // perform any cleanup when quitting Iperf
140 // Allocate the "global" settings
141 thread_Settings* ext_gSettings = new thread_Settings;
143 // Initialize settings to defaults
144 Settings_Initialize( ext_gSettings );
145 // read settings from environment variables
146 Settings_ParseEnvironment( ext_gSettings );
147 // read settings from command-line parameters
148 Settings_ParseCommandLine( argc, argv, ext_gSettings );
150 // Check for either having specified client or server
151 if ( ext_gSettings->mThreadMode == kMode_Client
152 || ext_gSettings->mThreadMode == kMode_Listener ) {
153 // initialize client(s)
154 if ( ext_gSettings->mThreadMode == kMode_Client ) {
155 client_init( ext_gSettings );
159 // start up the reporter and client(s) or listener
161 thread_Settings *into = NULL;
162 // Create the settings structure for the reporter thread
163 Settings_Copy( ext_gSettings, &into );
164 into->mThreadMode = kMode_Reporter;
166 // Have the reporter launch the client or listener
167 into->runNow = ext_gSettings;
169 // Start all the threads that are ready to go
170 thread_start( into );
173 // No need to make a reporter thread because we don't have threads
174 thread_start( ext_gSettings );
177 // neither server nor client mode was specified
178 // print usage and exit
180 fprintf( stderr, usage_short, argv[0], argv[0] );
185 // wait for other (client, server) threads to complete
192 /* -------------------------------------------------------------------
193 * Signal handler sets the sInterupted flag, so the object can
194 * respond appropriately.. [static]
195 * ------------------------------------------------------------------- */
197 void Sig_Interupt( int inSigno ) {
199 // We try to not allow a single interrupt handled by multiple threads
200 // to completely kill the app so we save off the first thread ID
201 // then that is the only thread that can supply the next interrupt
202 if ( thread_equalid( sThread, thread_zeroid() ) ) {
203 sThread = thread_getid();
204 } else if ( thread_equalid( sThread, thread_getid() ) ) {
208 // global variable used by threads to see if they were interrupted
211 // with threads, stop waiting for non-terminating threads
212 // (ie Listener Thread)
213 thread_release_nonterm( 1 );
216 // without threads, just exit quietly, same as sig_exit()
221 /* -------------------------------------------------------------------
222 * Any necesary cleanup before Iperf quits. Called at program exit,
223 * either by exit() or terminating main().
224 * ------------------------------------------------------------------- */
226 void cleanup( void ) {
227 // clean up the list of clients
228 Iperf_destroy ( &clients );
230 // shutdown the thread subsystem