1c5971cd144c7b33e8bf2f38ebd296b3276014de7Jens Axboe/* 2c5971cd144c7b33e8bf2f38ebd296b3276014de7Jens Axboe * Basic workqueue like code, that sets up a thread and allows async 3c5971cd144c7b33e8bf2f38ebd296b3276014de7Jens Axboe * processing of some sort. Could be extended to allow for multiple 4c5971cd144c7b33e8bf2f38ebd296b3276014de7Jens Axboe * worker threads. But right now fio associates one of this per IO 5c5971cd144c7b33e8bf2f38ebd296b3276014de7Jens Axboe * thread, so should be enough to have just a single thread doing the 6c5971cd144c7b33e8bf2f38ebd296b3276014de7Jens Axboe * work. 7c5971cd144c7b33e8bf2f38ebd296b3276014de7Jens Axboe */ 838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe#include <stdio.h> 938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe#include <stdlib.h> 1038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe#include <stdarg.h> 1138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe#include <unistd.h> 1238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe#include <errno.h> 1338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe#include <pthread.h> 14c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe#include <string.h> 1538a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 1665f93caca2ca0dd8d8150831f16854b3a8c3845aJens Axboe#include "../smalloc.h" 1765f93caca2ca0dd8d8150831f16854b3a8c3845aJens Axboe#include "../log.h" 1838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe#include "tp.h" 1938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 2038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboestatic void tp_flush_work(struct flist_head *list) 2138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe{ 2238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe struct tp_work *work; 2338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 2438a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe while (!flist_empty(list)) { 25c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe int prio; 26c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe 2738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe work = flist_entry(list->next, struct tp_work, list); 2838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe flist_del(&work->list); 29c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe 30c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe prio = work->prio; 31c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe if (nice(prio) < 0) 32c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe log_err("fio: nice %s\n", strerror(errno)); 33c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe 3438a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe work->fn(work); 35c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe 36c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe if (nice(prio) < 0) 37c9a5f3981c3678d53e532296082ba80ded59f74aJens Axboe log_err("fio: nice %s\n", strerror(errno)); 3838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe } 3938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe} 4038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 4138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboestatic void *tp_thread(void *data) 4238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe{ 4338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe struct tp_data *tdat = data; 4438a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe struct flist_head work_list; 4538a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 4638a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe INIT_FLIST_HEAD(&work_list); 4738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 4838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe while (1) { 4938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_mutex_lock(&tdat->lock); 5038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 5138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe if (!tdat->thread_exit && flist_empty(&tdat->work)) 5238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_cond_wait(&tdat->cv, &tdat->lock); 5338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 5412dbd06d3203840c8ebdc4d0a6135a69c4380949Jens Axboe if (!flist_empty(&tdat->work)) 5512dbd06d3203840c8ebdc4d0a6135a69c4380949Jens Axboe flist_splice_tail_init(&tdat->work, &work_list); 5638a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 5738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_mutex_unlock(&tdat->lock); 5838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 5938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe if (flist_empty(&work_list)) { 6038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe if (tdat->thread_exit) 6138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe break; 6238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe continue; 6338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe } 6438a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 6538a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe tp_flush_work(&work_list); 6638a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe } 6738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 6838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe return NULL; 6938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe} 7038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 7138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboevoid tp_queue_work(struct tp_data *tdat, struct tp_work *work) 7238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe{ 7338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe work->done = 0; 7438a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 7538a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_mutex_lock(&tdat->lock); 7638a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe flist_add_tail(&work->list, &tdat->work); 7738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_mutex_unlock(&tdat->lock); 78de6504ecd252b953c5fecf7277b4a9cc002a6602Jens Axboe 79de6504ecd252b953c5fecf7277b4a9cc002a6602Jens Axboe pthread_cond_signal(&tdat->cv); 8038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe} 8138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 8238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboevoid tp_init(struct tp_data **tdatp) 8338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe{ 8438a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe struct tp_data *tdat; 8538a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe int ret; 8638a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 8738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe if (*tdatp) 8838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe return; 8938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 9038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe *tdatp = tdat = smalloc(sizeof(*tdat)); 9138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_mutex_init(&tdat->lock, NULL); 9238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe INIT_FLIST_HEAD(&tdat->work); 9338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_cond_init(&tdat->cv, NULL); 9438a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_cond_init(&tdat->sleep_cv, NULL); 9538a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 9638a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe ret = pthread_create(&tdat->thread, NULL, tp_thread, tdat); 9738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe if (ret) 9838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe log_err("fio: failed to create tp thread\n"); 9938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe} 10038a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 10138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboevoid tp_exit(struct tp_data **tdatp) 10238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe{ 10338a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe struct tp_data *tdat = *tdatp; 10438a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe void *ret; 10538a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 10638a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe if (!tdat) 10738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe return; 10838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 10938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_mutex_lock(&tdat->lock); 110de6504ecd252b953c5fecf7277b4a9cc002a6602Jens Axboe tdat->thread_exit = 1; 11138a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_mutex_unlock(&tdat->lock); 11238a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 113de6504ecd252b953c5fecf7277b4a9cc002a6602Jens Axboe pthread_cond_signal(&tdat->cv); 114de6504ecd252b953c5fecf7277b4a9cc002a6602Jens Axboe 11538a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe pthread_join(tdat->thread, &ret); 11638a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe 11738a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe sfree(tdat); 11838a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe *tdatp = NULL; 11938a812d7fa79a673855efb6324c8fc68b92b89c1Jens Axboe} 120