1da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe/*
2da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * CPU engine
3da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe *
4da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * Doesn't transfer any data, merely burns CPU cycles according to
5da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe * the settings.
6da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe *
7da751ca9665bcdeca56d2eec5b629a0953c07662Jens Axboe */
85f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe#include "../fio.h"
92866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
100353050fe32065e1932a43a7c39a7c390ea71142Jens Axboestruct cpu_options {
110353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	struct thread_data *td;
120353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	unsigned int cpuload;
130353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	unsigned int cpucycle;
14046395d7ab181288d14737c1d0041e98328f473fJens Axboe	unsigned int exit_io_done;
150353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe};
160353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe
170353050fe32065e1932a43a7c39a7c390ea71142Jens Axboestatic struct fio_option options[] = {
180353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	{
190353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.name	= "cpuload",
200353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.lname	= "CPU load",
210353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.type	= FIO_OPT_INT,
220353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.off1	= offsetof(struct cpu_options, cpuload),
230353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.help	= "Use this percentage of CPU",
240353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.category = FIO_OPT_C_GENERAL,
250353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.group	= FIO_OPT_G_INVALID,
260353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	},
270353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	{
280353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.name	= "cpuchunks",
290353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.lname	= "CPU chunk",
300353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.type	= FIO_OPT_INT,
310353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.off1	= offsetof(struct cpu_options, cpucycle),
320353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.help	= "Length of the CPU burn cycles (usecs)",
330353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.def	= "50000",
340353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.parent = "cpuload",
350353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.hide	= 1,
360353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.category = FIO_OPT_C_GENERAL,
370353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.group	= FIO_OPT_G_INVALID,
380353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	},
390353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	{
40046395d7ab181288d14737c1d0041e98328f473fJens Axboe		.name	= "exit_on_io_done",
41046395d7ab181288d14737c1d0041e98328f473fJens Axboe		.lname	= "Exit when IO threads are done",
42046395d7ab181288d14737c1d0041e98328f473fJens Axboe		.type	= FIO_OPT_BOOL,
43046395d7ab181288d14737c1d0041e98328f473fJens Axboe		.off1	= offsetof(struct cpu_options, exit_io_done),
44046395d7ab181288d14737c1d0041e98328f473fJens Axboe		.help	= "Exit when IO threads finish",
45046395d7ab181288d14737c1d0041e98328f473fJens Axboe		.def	= "0",
46046395d7ab181288d14737c1d0041e98328f473fJens Axboe		.category = FIO_OPT_C_GENERAL,
47046395d7ab181288d14737c1d0041e98328f473fJens Axboe		.group	= FIO_OPT_G_INVALID,
48046395d7ab181288d14737c1d0041e98328f473fJens Axboe	},
49046395d7ab181288d14737c1d0041e98328f473fJens Axboe	{
500353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		.name	= NULL,
510353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	},
520353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe};
530353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe
540353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe
55ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboestatic int fio_cpuio_queue(struct thread_data *td, struct io_u fio_unused *io_u)
56ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe{
570353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	struct cpu_options *co = td->eo;
580353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe
59046395d7ab181288d14737c1d0041e98328f473fJens Axboe	if (co->exit_io_done && !fio_running_or_pending_io_threads()) {
60046395d7ab181288d14737c1d0041e98328f473fJens Axboe		td->done = 1;
61046395d7ab181288d14737c1d0041e98328f473fJens Axboe		return FIO_Q_BUSY;
62046395d7ab181288d14737c1d0041e98328f473fJens Axboe	}
63046395d7ab181288d14737c1d0041e98328f473fJens Axboe
640353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	usec_spin(co->cpucycle);
65ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe	return FIO_Q_COMPLETED;
66ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe}
67ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe
682866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboestatic int fio_cpuio_init(struct thread_data *td)
692866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe{
702dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe	struct thread_options *o = &td->o;
710353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	struct cpu_options *co = td->eo;
722dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe
730353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	if (!co->cpuload) {
74ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe		td_vmsg(td, EINVAL, "cpu thread needs rate (cpuload=)","cpuio");
752866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe		return 1;
76ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe	}
77ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe
780353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	if (co->cpuload > 100)
790353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe		co->cpuload = 100;
802866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
81ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe	/*
82ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe	 * set thinktime_sleep and thinktime_spin appropriately
83ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe	 */
842dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe	o->thinktime_blocks = 1;
852dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe	o->thinktime_spin = 0;
860353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	o->thinktime = (co->cpucycle * (100 - co->cpuload)) / co->cpuload;
872866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
882dc1bbeb58edc85f2829eed6729862c438ea2353Jens Axboe	o->nr_files = o->open_files = 1;
890353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe
900353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	log_info("%s: ioengine=cpu, cpuload=%u, cpucycle=%u\n", td->o.name,
910353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe						co->cpuload, co->cpucycle);
920353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe
93ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe	return 0;
94ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe}
95ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe
96f4e62a5f3640dfe2d2119bbe1e40bf57747f6564Jens Axboestatic int fio_cpuio_open(struct thread_data fio_unused *td,
97f4e62a5f3640dfe2d2119bbe1e40bf57747f6564Jens Axboe			  struct fio_file fio_unused *f)
98ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe{
992866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	return 0;
1002866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe}
1012866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe
1025f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic struct ioengine_ops ioengine = {
1032866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.name		= "cpuio",
1042866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.version	= FIO_IOOPS_VERSION,
105ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe	.queue		= fio_cpuio_queue,
1062866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe	.init		= fio_cpuio_init,
107ba0fbe1029bae1de08d66a72b6d0b2505c67c438Jens Axboe	.open_file	= fio_cpuio_open,
1081f809d151ddc4a4c348c2e4f6007db510e3e08a2Jens Axboe	.flags		= FIO_SYNCIO | FIO_DISKLESSIO | FIO_NOIO,
1090353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	.options		= options,
1100353050fe32065e1932a43a7c39a7c390ea71142Jens Axboe	.option_struct_size	= sizeof(struct cpu_options),
1112866c82d598e30604d8a92723c664ee6ced90fb0Jens Axboe};
1125f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe
1135f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic void fio_init fio_cpuio_register(void)
1145f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe{
1155f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe	register_ioengine(&ioengine);
1165f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe}
1175f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe
1185f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboestatic void fio_exit fio_cpuio_unregister(void)
1195f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe{
1205f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe	unregister_ioengine(&ioengine);
1215f350952eff89948bfbf1eb6ac4d3d08a9109581Jens Axboe}
122