flist: add flist_first_entry()
[fio.git] / lib / tp.c
CommitLineData
aee2ab67
JA
1#include <stdio.h>
2#include <stdlib.h>
3#include <stdarg.h>
4#include <unistd.h>
5#include <errno.h>
6#include <pthread.h>
7
78d55e72
JA
8#include "../smalloc.h"
9#include "../log.h"
aee2ab67
JA
10#include "tp.h"
11
12static void tp_flush_work(struct flist_head *list)
13{
14 struct tp_work *work;
15
16 while (!flist_empty(list)) {
17 work = flist_entry(list->next, struct tp_work, list);
18 flist_del(&work->list);
19 work->fn(work);
20 }
21}
22
23static void *tp_thread(void *data)
24{
25 struct tp_data *tdat = data;
26 struct flist_head work_list;
27
28 INIT_FLIST_HEAD(&work_list);
29
aee2ab67
JA
30 while (1) {
31 pthread_mutex_lock(&tdat->lock);
32
33 if (!tdat->thread_exit && flist_empty(&tdat->work))
34 pthread_cond_wait(&tdat->cv, &tdat->lock);
35
9342d5f8
JA
36 if (!flist_empty(&tdat->work))
37 flist_splice_tail_init(&tdat->work, &work_list);
aee2ab67
JA
38
39 pthread_mutex_unlock(&tdat->lock);
40
41 if (flist_empty(&work_list)) {
42 if (tdat->thread_exit)
43 break;
44 continue;
45 }
46
47 tp_flush_work(&work_list);
48 }
49
aee2ab67
JA
50 return NULL;
51}
52
53void tp_queue_work(struct tp_data *tdat, struct tp_work *work)
54{
55 work->done = 0;
56
57 pthread_mutex_lock(&tdat->lock);
58 flist_add_tail(&work->list, &tdat->work);
59 pthread_cond_signal(&tdat->cv);
60 pthread_mutex_unlock(&tdat->lock);
61}
62
63void tp_init(struct tp_data **tdatp)
64{
65 struct tp_data *tdat;
66 int ret;
67
68 if (*tdatp)
69 return;
70
71 *tdatp = tdat = smalloc(sizeof(*tdat));
72 pthread_mutex_init(&tdat->lock, NULL);
73 INIT_FLIST_HEAD(&tdat->work);
74 pthread_cond_init(&tdat->cv, NULL);
75 pthread_cond_init(&tdat->sleep_cv, NULL);
76
77 ret = pthread_create(&tdat->thread, NULL, tp_thread, tdat);
78 if (ret)
79 log_err("fio: failed to create tp thread\n");
80}
81
82void tp_exit(struct tp_data **tdatp)
83{
84 struct tp_data *tdat = *tdatp;
85 void *ret;
86
87 if (!tdat)
88 return;
89
90 tdat->thread_exit = 1;
91 pthread_mutex_lock(&tdat->lock);
92 pthread_cond_signal(&tdat->cv);
93 pthread_mutex_unlock(&tdat->lock);
94
95 pthread_join(tdat->thread, &ret);
96
97 sfree(tdat);
98 *tdatp = NULL;
99}