1f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu#include <math.h>
2f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu#include "json.h"
3f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu#include "idletime.h"
4f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
5f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liustatic volatile struct idle_prof_common ipc;
6f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
7680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe/*
8680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe * Get time to complete an unit work on a particular cpu.
9f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu * The minimum number in CALIBRATE_RUNS runs is returned.
10f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu */
11f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liustatic double calibrate_unit(unsigned char *data)
12f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
13f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	unsigned long t, i, j, k;
14f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct timeval tps;
15f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	double tunit = 0.0;
16f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
17680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	for (i = 0; i < CALIBRATE_RUNS; i++) {
18f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
19f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		fio_gettime(&tps, NULL);
20f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		/* scale for less variance */
21680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		for (j = 0; j < CALIBRATE_SCALE; j++) {
22f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			/* unit of work */
23f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			for (k=0; k < page_size; k++) {
24680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe				data[(k + j) % page_size] = k % 256;
25680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe				/*
26680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe				 * we won't see STOP here. this is to match
27f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu				 * the same statement in the profiling loop.
28f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu				 */
29f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu				if (ipc.status == IDLE_PROF_STATUS_PROF_STOP)
30f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu					return 0.0;
31f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			}
32f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
33f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
34f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		t = utime_since_now(&tps);
35f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (!t)
36f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			continue;
37f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
38f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		/* get the minimum time to complete CALIBRATE_SCALE units */
39680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		if ((i == 0) || ((double)t < tunit))
40f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			tunit = (double)t;
41f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
42f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
43680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	return tunit / CALIBRATE_SCALE;
44f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
45f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
463c9c470a4b176c739ad58e335f92fedbe549177fJens Axboestatic void free_cpu_affinity(struct idle_prof_thread *ipt)
473c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe{
483c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe#if defined(FIO_HAVE_CPU_AFFINITY)
493c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe	fio_cpuset_exit(&ipt->cpu_mask);
503c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe#endif
513c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe}
523c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe
5359358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboestatic int set_cpu_affinity(struct idle_prof_thread *ipt)
5459358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe{
5559358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe#if defined(FIO_HAVE_CPU_AFFINITY)
563c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe	if (fio_cpuset_init(&ipt->cpu_mask)) {
573c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe		log_err("fio: cpuset init failed\n");
583c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe		return -1;
593c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe	}
6059358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe
613c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe	fio_cpu_set(&ipt->cpu_mask, ipt->cpu);
6259358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe
633c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe	if (fio_setaffinity(gettid(), ipt->cpu_mask)) {
6459358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe		log_err("fio: fio_setaffinity failed\n");
653c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe		fio_cpuset_exit(&ipt->cpu_mask);
6659358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe		return -1;
6759358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe	}
6859358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe
6959358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe	return 0;
7059358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe#else
7159358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe	log_err("fio: fio_setaffinity not supported\n");
7259358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe	return -1;
7359358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe#endif
7459358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe}
7559358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe
76f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liustatic void *idle_prof_thread_fn(void *data)
77f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
78f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	int retval;
79f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	unsigned long j, k;
80f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct idle_prof_thread *ipt = data;
81f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
82f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* wait for all threads are spawned */
83f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	pthread_mutex_lock(&ipt->init_lock);
84f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
85f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* exit if any other thread failed to start */
86d5b351d483aabb0d0a0acd2930640428aa8e6339Jens Axboe	if (ipc.status == IDLE_PROF_STATUS_ABORT) {
87d5b351d483aabb0d0a0acd2930640428aa8e6339Jens Axboe		pthread_mutex_unlock(&ipt->init_lock);
88f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return NULL;
89d5b351d483aabb0d0a0acd2930640428aa8e6339Jens Axboe	}
90f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
9159358c8ef39efea4a2ab141d85b2deebf5cf34fdJens Axboe	retval = set_cpu_affinity(ipt);
92f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (retval == -1) {
93f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt->state = TD_EXITED;
94f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_unlock(&ipt->init_lock);
95f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return NULL;
96f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu        }
97f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
98f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipt->cali_time = calibrate_unit(ipt->data);
99f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
100f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* delay to set IDLE class till now for better calibration accuracy */
1017e09a9f10bb301635b6f9206b3144878a2710b0aJens Axboe#if defined(CONFIG_SCHED_IDLE)
102f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if ((retval = fio_set_sched_idle()))
103f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		log_err("fio: fio_set_sched_idle failed\n");
104f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu#else
105f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	retval = -1;
106f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	log_err("fio: fio_set_sched_idle not supported\n");
107f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu#endif
108f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (retval == -1) {
109f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt->state = TD_EXITED;
110f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_unlock(&ipt->init_lock);
1113c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe		goto do_exit;
112f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
113f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
114f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipt->state = TD_INITIALIZED;
115f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
116f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* signal the main thread that calibration is done */
117f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	pthread_cond_signal(&ipt->cond);
118f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	pthread_mutex_unlock(&ipt->init_lock);
119f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
120f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* wait for other calibration to finish */
121f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	pthread_mutex_lock(&ipt->start_lock);
122f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
123f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* exit if other threads failed to initialize */
124735ed278a7ba6e3f1d5a0c08fc08149a2f435c37Jens Axboe	if (ipc.status == IDLE_PROF_STATUS_ABORT) {
125735ed278a7ba6e3f1d5a0c08fc08149a2f435c37Jens Axboe		pthread_mutex_unlock(&ipt->start_lock);
1263c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe		goto do_exit;
127735ed278a7ba6e3f1d5a0c08fc08149a2f435c37Jens Axboe	}
128f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
129f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* exit if we are doing calibration only */
130735ed278a7ba6e3f1d5a0c08fc08149a2f435c37Jens Axboe	if (ipc.status == IDLE_PROF_STATUS_CALI_STOP) {
131735ed278a7ba6e3f1d5a0c08fc08149a2f435c37Jens Axboe		pthread_mutex_unlock(&ipt->start_lock);
1323c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe		goto do_exit;
133735ed278a7ba6e3f1d5a0c08fc08149a2f435c37Jens Axboe	}
134f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
135f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	fio_gettime(&ipt->tps, NULL);
136f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipt->state = TD_RUNNING;
137f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
138f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	j = 0;
139f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	while (1) {
140680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		for (k = 0; k < page_size; k++) {
141680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe			ipt->data[(k + j) % page_size] = k % 256;
142f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			if (ipc.status == IDLE_PROF_STATUS_PROF_STOP) {
143f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu				fio_gettime(&ipt->tpe, NULL);
144f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu				goto idle_prof_done;
145f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			}
146f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
147f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		j++;
148f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
149f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
150f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liuidle_prof_done:
151f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
152680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	ipt->loops = j + (double) k / page_size;
153f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipt->state = TD_EXITED;
154f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	pthread_mutex_unlock(&ipt->start_lock);
155f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
1563c9c470a4b176c739ad58e335f92fedbe549177fJens Axboedo_exit:
1573c9c470a4b176c739ad58e335f92fedbe549177fJens Axboe	free_cpu_affinity(ipt);
158f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	return NULL;
159f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
160f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
161f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu/* calculate mean and standard deviation to complete an unit of work */
162f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liustatic void calibration_stats(void)
163f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
164f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	int i;
165680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	double sum = 0.0, var = 0.0;
166f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct idle_prof_thread *ipt;
167f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
168f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	for (i = 0; i < ipc.nr_cpus; i++) {
169f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt = &ipc.ipts[i];
170f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		sum += ipt->cali_time;
171f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
172f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
173f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipc.cali_mean = sum/ipc.nr_cpus;
174f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
175f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	for (i = 0; i < ipc.nr_cpus; i++) {
176f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt = &ipc.ipts[i];
177f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		var += pow(ipt->cali_time-ipc.cali_mean, 2);
178f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
179f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
180f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipc.cali_stddev = sqrt(var/(ipc.nr_cpus-1));
181f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
182f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
183f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liuvoid fio_idle_prof_init(void)
184f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
185f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	int i, ret;
186f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct timeval tp;
187f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct timespec ts;
188680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	pthread_attr_t tattr;
189f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct idle_prof_thread *ipt;
190f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
191f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipc.nr_cpus = cpus_online();
192f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipc.status = IDLE_PROF_STATUS_OK;
193f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
194f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.opt == IDLE_PROF_OPT_NONE)
195f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
196f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
197f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if ((ret = pthread_attr_init(&tattr))) {
198f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		log_err("fio: pthread_attr_init %s\n", strerror(ret));
199f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
200f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
201f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if ((ret = pthread_attr_setscope(&tattr, PTHREAD_SCOPE_SYSTEM))) {
202f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		log_err("fio: pthread_attr_setscope %s\n", strerror(ret));
203f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
204f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
205f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
206f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipc.ipts = malloc(ipc.nr_cpus * sizeof(struct idle_prof_thread));
207f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (!ipc.ipts) {
208f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		log_err("fio: malloc failed\n");
209f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
210f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
211f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
212f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipc.buf = malloc(ipc.nr_cpus * page_size);
213f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (!ipc.buf) {
214f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		log_err("fio: malloc failed\n");
215f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		free(ipc.ipts);
216f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
217f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
218f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
219680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	/*
220680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	 * profiling aborts on any single thread failure since the
221f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	 * result won't be accurate if any cpu is not used.
222f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	 */
223f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	for (i = 0; i < ipc.nr_cpus; i++) {
224f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt = &ipc.ipts[i];
225f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
226f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt->cpu = i;
227f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt->state = TD_NOT_CREATED;
228f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt->data = (unsigned char *)(ipc.buf + page_size * i);
229f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
230f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if ((ret = pthread_mutex_init(&ipt->init_lock, NULL))) {
231f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ipc.status = IDLE_PROF_STATUS_ABORT;
232f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_err("fio: pthread_mutex_init %s\n", strerror(ret));
233f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			break;
234f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
235f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
236f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if ((ret = pthread_mutex_init(&ipt->start_lock, NULL))) {
237f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ipc.status = IDLE_PROF_STATUS_ABORT;
238f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_err("fio: pthread_mutex_init %s\n", strerror(ret));
239f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			break;
240f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
241f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
242f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if ((ret = pthread_cond_init(&ipt->cond, NULL))) {
243f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ipc.status = IDLE_PROF_STATUS_ABORT;
244f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_err("fio: pthread_cond_init %s\n", strerror(ret));
245f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			break;
246f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
247f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
248f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		/* make sure all threads are spawned before they start */
249f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_lock(&ipt->init_lock);
250f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
251f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		/* make sure all threads finish init before profiling starts */
252f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_lock(&ipt->start_lock);
253f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
254f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if ((ret = pthread_create(&ipt->thread, &tattr, idle_prof_thread_fn, ipt))) {
255f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ipc.status = IDLE_PROF_STATUS_ABORT;
256f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_err("fio: pthread_create %s\n", strerror(ret));
257f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			break;
258680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		} else
259f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ipt->state = TD_CREATED;
260f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
261f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if ((ret = pthread_detach(ipt->thread))) {
262f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			/* log error and let the thread spin */
263f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_err("fio: pthread_detatch %s\n", strerror(ret));
264f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
265f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
266f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
267680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	/*
268680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	 * let good threads continue so that they can exit
269680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	 * if errors on other threads occurred previously.
270f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	 */
271f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	for (i = 0; i < ipc.nr_cpus; i++) {
272f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt = &ipc.ipts[i];
273f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_unlock(&ipt->init_lock);
274f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
275f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
276f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.status == IDLE_PROF_STATUS_ABORT)
277f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
278f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
279f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* wait for calibration to finish */
280f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	for (i = 0; i < ipc.nr_cpus; i++) {
281f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt = &ipc.ipts[i];
282f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_lock(&ipt->init_lock);
283680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		while ((ipt->state != TD_EXITED) &&
284680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		       (ipt->state!=TD_INITIALIZED)) {
285f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			fio_gettime(&tp, NULL);
286f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ts.tv_sec = tp.tv_sec + 1;
287f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ts.tv_nsec = tp.tv_usec * 1000;
288f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			pthread_cond_timedwait(&ipt->cond, &ipt->init_lock, &ts);
289f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
290f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_unlock(&ipt->init_lock);
291f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
292680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		/*
293680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		 * any thread failed to initialize would abort other threads
294f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		 * later after fio_idle_prof_start.
295f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		 */
296f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (ipt->state == TD_EXITED)
297f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ipc.status = IDLE_PROF_STATUS_ABORT;
298f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
299f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
300f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.status != IDLE_PROF_STATUS_ABORT)
301f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		calibration_stats();
302680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	else
303f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipc.cali_mean = ipc.cali_stddev = 0.0;
304f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
305f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.opt == IDLE_PROF_OPT_CALI)
306f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipc.status = IDLE_PROF_STATUS_CALI_STOP;
307f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
308f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
309f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liuvoid fio_idle_prof_start(void)
310f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
311f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	int i;
312f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct idle_prof_thread *ipt;
313f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
314f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.opt == IDLE_PROF_OPT_NONE)
315f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
316f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
317f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* unlock regardless abort is set or not */
318f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	for (i = 0; i < ipc.nr_cpus; i++) {
319f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt = &ipc.ipts[i];
320f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_unlock(&ipt->start_lock);
321f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
322f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
323f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
324f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liuvoid fio_idle_prof_stop(void)
325f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
326f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	int i;
327f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	uint64_t runt;
328f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct timeval tp;
329f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct timespec ts;
330f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct idle_prof_thread *ipt;
331f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
332f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.opt == IDLE_PROF_OPT_NONE)
333f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
334f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
335f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.opt == IDLE_PROF_OPT_CALI)
336f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
337f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
338f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipc.status = IDLE_PROF_STATUS_PROF_STOP;
339f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
340f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	/* wait for all threads to exit from profiling */
341f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	for (i = 0; i < ipc.nr_cpus; i++) {
342f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt = &ipc.ipts[i];
343f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_lock(&ipt->start_lock);
344680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		while ((ipt->state != TD_EXITED) &&
345680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		       (ipt->state!=TD_NOT_CREATED)) {
346f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			fio_gettime(&tp, NULL);
347f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ts.tv_sec = tp.tv_sec + 1;
348f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ts.tv_nsec = tp.tv_usec * 1000;
349f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			/* timed wait in case a signal is not received */
350f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			pthread_cond_timedwait(&ipt->cond, &ipt->start_lock, &ts);
351f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
352f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		pthread_mutex_unlock(&ipt->start_lock);
353f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
354f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		/* calculate idleness */
355f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (ipc.cali_mean != 0.0) {
356f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			runt = utime_since(&ipt->tps, &ipt->tpe);
3579da67e75febb49f29b1657e93e592b656ec84f11Jens Axboe			if (runt)
3589da67e75febb49f29b1657e93e592b656ec84f11Jens Axboe				ipt->idleness = ipt->loops * ipc.cali_mean / runt;
3599da67e75febb49f29b1657e93e592b656ec84f11Jens Axboe			else
3609da67e75febb49f29b1657e93e592b656ec84f11Jens Axboe				ipt->idleness = 0.0;
361680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe		} else
362f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ipt->idleness = 0.0;
363f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
364f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
365680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	/*
366680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	 * memory allocations are freed via explicit fio_idle_prof_cleanup
367f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	 * after profiling stats are collected by apps.
368f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	 */
369f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
370f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
371680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe/*
372680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe * return system idle percentage when cpu is -1;
373f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu * return one cpu idle percentage otherwise.
374f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu */
375f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liustatic double fio_idle_prof_cpu_stat(int cpu)
376f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
377f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	int i, nr_cpus = ipc.nr_cpus;
378f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct idle_prof_thread *ipt;
379f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	double p = 0.0;
380f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
381f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.opt == IDLE_PROF_OPT_NONE)
382f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return 0.0;
383f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
384f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if ((cpu >= nr_cpus) || (cpu < -1)) {
385f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		log_err("fio: idle profiling invalid cpu index\n");
386f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return 0.0;
387f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
388f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
389f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (cpu == -1) {
390f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		for (i = 0; i < nr_cpus; i++) {
391f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			ipt = &ipc.ipts[i];
392f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			p += ipt->idleness;
393f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
394f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		p /= nr_cpus;
395f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	} else {
396f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipt = &ipc.ipts[cpu];
397f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		p = ipt->idleness;
398f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
399f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
400680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe	return p * 100.0;
401f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
402f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
40310aa136bddbaa7c845ab4eacb4a9a4a88d6657a3Jens Axboestatic void fio_idle_prof_cleanup(void)
404f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
405f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.ipts) {
406f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		free(ipc.ipts);
407f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipc.ipts = NULL;
408f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
409f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
410f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (ipc.buf) {
411f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		free(ipc.buf);
412f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipc.buf = NULL;
413f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
414f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
415f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
416f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liuint fio_idle_prof_parse_opt(const char *args)
417f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
418f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	ipc.opt = IDLE_PROF_OPT_NONE; /* default */
419f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
420f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (!args) {
421f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		log_err("fio: empty idle-prof option string\n");
422f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return -1;
423f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
424f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
4257e09a9f10bb301635b6f9206b3144878a2710b0aJens Axboe#if defined(FIO_HAVE_CPU_AFFINITY) && defined(CONFIG_SCHED_IDLE)
426f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (strcmp("calibrate", args) == 0) {
427f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipc.opt = IDLE_PROF_OPT_CALI;
428f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		fio_idle_prof_init();
429f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		fio_idle_prof_start();
430f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		fio_idle_prof_stop();
431f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		show_idle_prof_stats(FIO_OUTPUT_NORMAL, NULL);
432f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return 1;
433f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	} else if (strcmp("system", args) == 0) {
434f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipc.opt = IDLE_PROF_OPT_SYSTEM;
435f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return 0;
436f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	} else if (strcmp("percpu", args) == 0) {
437f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		ipc.opt = IDLE_PROF_OPT_PERCPU;
438f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return 0;
439f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	} else {
4404e0a8fa2593006505b7f4e18931a201d221b49e9Jens Axboe		log_err("fio: incorrect idle-prof option: %s\n", args);
441f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return -1;
442f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
443f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu#else
444f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	log_err("fio: idle-prof not supported on this platform\n");
445f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	return -1;
446f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu#endif
447f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
448f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
449f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liuvoid show_idle_prof_stats(int output, struct json_object *parent)
450f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu{
451f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	int i, nr_cpus = ipc.nr_cpus;
452f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	struct json_object *tmp;
453f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	char s[MAX_CPU_STR_LEN];
454680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe
455f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if (output == FIO_OUTPUT_NORMAL) {
456f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (ipc.opt > IDLE_PROF_OPT_CALI)
457f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_info("\nCPU idleness:\n");
458f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		else if (ipc.opt == IDLE_PROF_OPT_CALI)
459f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_info("CPU idleness:\n");
460f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
461f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (ipc.opt >= IDLE_PROF_OPT_SYSTEM)
462f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_info("  system: %3.2f%%\n", fio_idle_prof_cpu_stat(-1));
463f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
464f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (ipc.opt == IDLE_PROF_OPT_PERCPU) {
465f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_info("  percpu: %3.2f%%", fio_idle_prof_cpu_stat(0));
466680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe			for (i = 1; i < nr_cpus; i++)
467f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu				log_info(", %3.2f%%", fio_idle_prof_cpu_stat(i));
468f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_info("\n");
469f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
470f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
471f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (ipc.opt >= IDLE_PROF_OPT_CALI) {
472f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_info("  unit work: mean=%3.2fus,", ipc.cali_mean);
473f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			log_info(" stddev=%3.2f\n", ipc.cali_stddev);
474f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
475f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
476f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		/* dynamic mem allocations can now be freed */
477f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (ipc.opt != IDLE_PROF_OPT_NONE)
478f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			fio_idle_prof_cleanup();
479f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
480f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		return;
481f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
482680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe
483f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	if ((ipc.opt != IDLE_PROF_OPT_NONE) && (output == FIO_OUTPUT_JSON)) {
484f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (!parent)
485f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			return;
486f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
487f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		tmp = json_create_object();
488f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (!tmp)
489f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			return;
490f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
491f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		json_object_add_value_object(parent, "cpu_idleness", tmp);
492f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		json_object_add_value_float(tmp, "system", fio_idle_prof_cpu_stat(-1));
493f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
494f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		if (ipc.opt == IDLE_PROF_OPT_PERCPU) {
495680b5abcb197f52382c8c568c6f1453b410e2b66Jens Axboe			for (i = 0; i < nr_cpus; i++) {
496f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu				snprintf(s, MAX_CPU_STR_LEN, "cpu-%d", i);
497f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu				json_object_add_value_float(tmp, s, fio_idle_prof_cpu_stat(i));
498f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu			}
499f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		}
500f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
501f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		json_object_add_value_float(tmp, "unit_mean", ipc.cali_mean);
502f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		json_object_add_value_float(tmp, "unit_stddev", ipc.cali_stddev);
503f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu
504f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu		fio_idle_prof_cleanup();
505f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu	}
506f2a2ce0eedb44eaa8689e4cbfa77c79b1751b216Huadong Liu}
507