static int timeout = DEF_TIMEOUT;
static int odirect = DEF_ODIRECT;
static int global_bs = DEF_BS;
+static int rate_quit = 1;
static int thread_number;
static char *ini_file;
DDIR_WRITE,
};
+/*
+ * thread life cycle
+ */
+enum {
+ TD_NOT_CREATED = 0,
+ TD_CREATED,
+ TD_STARTED,
+ TD_EXITED,
+ TD_REAPED,
+};
+
struct thread_data {
char file_name[256];
int thread_number;
int stat_fd;
pid_t pid;
volatile int terminate;
- volatile int started;
+ volatile int runstate;
unsigned int ddir;
unsigned int ioprio;
unsigned int sequential;
static sem_t startup_sem;
+static volatile int do_quit;
+
static void sig_handler(int sig)
{
int i;
}
}
+static void terminate_threads(void)
+{
+ do_quit = 1;
+ sig_handler(0);
+}
+
static int init_random_state(struct thread_data *td)
{
unsigned long seed = 123;
rate = ((td->io_blocks - td->rate_blocks) * td->bs) / spent;
if (rate < td->ratemin) {
printf("Client%d: min rate %d not met, got %ldKiB/sec\n", td->thread_number, td->ratemin, rate);
+ if (rate_quit)
+ terminate_threads();
return 1;
}
}
close(td->fd);
if (ret)
sem_post(&startup_sem);
+
+ td->runstate = TD_EXITED;
shmdt(data);
return NULL;
}
parm++;
repeatable = !!atoi(parm);
break;
+ case 'R':
+ parm++;
+ rate_quit = !!atoi(parm);
+ break;
case 'o':
parm++;
odirect = !!atoi(parm);
return i;
}
+static int reap_threads(void)
+{
+ int i, reaped = 0;
+
+ for (i = 0; i < thread_number; i++) {
+ struct thread_data *td = &threads[i];
+
+ if (td->runstate == TD_EXITED) {
+ td->runstate = TD_REAPED;
+ waitpid(td->pid, NULL, 0);
+ reaped++;
+ }
+ }
+
+ return reaped;
+}
+
static void run_threads(char *argv[])
{
struct timeval genesis, now;
struct thread_data *td;
unsigned long spent;
- int i, todo;
+ int i, todo, nr_running;
gettimeofday(&genesis, NULL);
}
todo = thread_number;
+ nr_running = 0;
- while (todo) {
+ while (todo && !do_quit) {
for (i = 0; i < thread_number; i++) {
td = &threads[i];
- if (td->started)
+ if (td->runstate != TD_NOT_CREATED)
continue;
if (td->start_delay) {
continue;
}
- td->started = 1;
+ td->runstate = TD_CREATED;
sem_init(&startup_sem, 1, 1);
todo--;
for (i = 0; i < thread_number; i++) {
struct thread_data *td = &threads[i];
- if (td->started == 1) {
- td->started++;
+ if (td->runstate == TD_CREATED) {
+ td->runstate = TD_STARTED;
+ nr_running++;
sem_post(&td->mutex);
+ printf("%d threads now running\n", nr_running);
}
}
+ nr_running -= reap_threads();
+
if (todo)
usleep(100000);
}
+
+ while (nr_running) {
+ nr_running -= reap_threads();
+ usleep(10000);
+ }
}
int main(int argc, char *argv[])
run_threads(argv);
- for (i = 0; i < thread_number; i++) {
- struct thread_data *td = &threads[i];
-
- waitpid(td->pid, NULL, 0);
- }
-
min_bw[0] = min_run[0] = ~0UL;
min_bw[1] = min_run[1] = ~0UL;
minl[0] = minl[1] = ~0UL;