2 * Basic workqueue like code, that sets up a thread and allows async
3 * processing of some sort. Could be extended to allow for multiple
4 * worker threads. But right now fio associates one of this per IO
5 * thread, so should be enough to have just a single thread doing the
16 #include "../smalloc.h"
20 static void tp_flush_work(struct flist_head *list)
24 while (!flist_empty(list)) {
27 work = flist_entry(list->next, struct tp_work, list);
28 flist_del(&work->list);
32 log_err("fio: nice %s\n", strerror(errno));
37 log_err("fio: nice %s\n", strerror(errno));
41 static void *tp_thread(void *data)
43 struct tp_data *tdat = data;
44 struct flist_head work_list;
46 INIT_FLIST_HEAD(&work_list);
49 pthread_mutex_lock(&tdat->lock);
51 if (!tdat->thread_exit && flist_empty(&tdat->work))
52 pthread_cond_wait(&tdat->cv, &tdat->lock);
54 if (!flist_empty(&tdat->work))
55 flist_splice_tail_init(&tdat->work, &work_list);
57 pthread_mutex_unlock(&tdat->lock);
59 if (flist_empty(&work_list)) {
60 if (tdat->thread_exit)
65 tp_flush_work(&work_list);
71 void tp_queue_work(struct tp_data *tdat, struct tp_work *work)
75 pthread_mutex_lock(&tdat->lock);
76 flist_add_tail(&work->list, &tdat->work);
77 pthread_mutex_unlock(&tdat->lock);
79 pthread_cond_signal(&tdat->cv);
82 void tp_init(struct tp_data **tdatp)
90 *tdatp = tdat = smalloc(sizeof(*tdat));
91 pthread_mutex_init(&tdat->lock, NULL);
92 INIT_FLIST_HEAD(&tdat->work);
93 pthread_cond_init(&tdat->cv, NULL);
94 pthread_cond_init(&tdat->sleep_cv, NULL);
96 ret = pthread_create(&tdat->thread, NULL, tp_thread, tdat);
98 log_err("fio: failed to create tp thread\n");
101 void tp_exit(struct tp_data **tdatp)
103 struct tp_data *tdat = *tdatp;
109 pthread_mutex_lock(&tdat->lock);
110 tdat->thread_exit = 1;
111 pthread_mutex_unlock(&tdat->lock);
113 pthread_cond_signal(&tdat->cv);
115 pthread_join(tdat->thread, &ret);