Branch data Line data Source code
1 : :
2 : : #include "gwrl/event.h"
3 : :
4 : : //default amount of struct kevent to pull from kevent when polling.
5 : : #ifndef GWRL_KQUEUE_KEVENT_COUNT
6 : : # define GWRL_KQUEUE_KEVENT_COUNT 64
7 : : #endif
8 : :
9 : : //kqueue backend for gwrl->backend
10 : : typedef struct _gwrlbkd_kqueue {
11 : : gwrlbkd _; //base structure
12 : : int kq; //kq fd
13 : : size_t maxkevents; //count of kevents
14 : : struct kevent * kevents; //container for kevents
15 : : } gwrlbkd_kqueue;
16 : :
17 : : #ifdef __cplusplus
18 : : extern "C" {
19 : : #endif
20 : :
21 : 24 : gwrlbkd * gwrl_bkd_init(gwrl * rl) {
22 : 24 : gwrlbkd_kqueue * kbkd = _gwrlbkdk(gwrl_mem_calloc(1,sizeof(gwrlbkd_kqueue)));
23 : :
24 : : #ifdef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
25 : 24 : if(asserts_var1 == gwrlbkd_init_fail) {
26 : 1 : free(kbkd);
27 : 1 : kbkd = NULL;
28 : 1 : }
29 : : #endif
30 : :
31 [ + + ]: 24 : if(!kbkd) {
32 : : #ifndef GWRL_COVERAGE_INTERNAL_ASSERT_VARS
33 : : gwerr("(3el0L) calloc error");
34 : : #endif
35 : 1 : return NULL;
36 : : }
37 : :
38 : 23 : kbkd->kq = kqueue();
39 [ - + ]: 23 : if(kbkd->kq < 0) {
40 : 0 : gwerr("(1LKdoL) kqueue error");
41 : 0 : free(kbkd);
42 : 0 : return NULL;
43 : : }
44 : 23 : kbkd->kevents = gwrl_mem_calloc(1,sizeof(struct kevent)*GWRL_KQUEUE_KEVENT_COUNT);
45 : 23 : kbkd->maxkevents = GWRL_KQUEUE_KEVENT_COUNT;
46 : 23 : rl->options.gwrl_kqueue_kevent_count = GWRL_KQUEUE_KEVENT_COUNT;
47 : 23 : return _gwrlbkd(kbkd);
48 : 24 : }
49 : :
50 : 2 : void gwrl_bkd_set_options(gwrl * rl,gwrl_options * opts) {
51 : 2 : gwrlbkd_kqueue * kbkd = _gwrlbkdk(rl->backend);
52 : 2 : if(opts->gwrl_kqueue_kevent_count > kbkd->maxkevents) {
53 : 0 : kbkd->maxkevents = opts->gwrl_kqueue_kevent_count;
54 : 0 : }
55 : 2 : void * tmp = gwrl_mem_realloc(kbkd->kevents,sizeof(struct kevent) * kbkd->maxkevents);
56 [ - + ]: 2 : while(!tmp) {
57 : 0 : gwerr("(54oKD0) realloc error");
58 : 0 : tmp = gwrl_mem_realloc(kbkd->kevents,sizeof(struct kevent) * kbkd->maxkevents);
59 : 0 : }
60 : 2 : kbkd->kevents = (struct kevent *)tmp;
61 : 2 : }
62 : :
63 : 4 : void gwrl_bkd_free(gwrl * rl) {
64 : 4 : gwrlbkd_kqueue * kbkd = _gwrlbkdk(rl->backend);
65 : 4 : close(kbkd->kq);
66 : 4 : free(kbkd->kevents);
67 : 4 : free(rl->backend);
68 : 4 : rl->backend = NULL;
69 : 4 : }
70 : :
71 : 33 : void gwrl_bkd_kevent(gwrl * rl, gwrlsrc * src, int kflags, int kfilter) {
72 : 33 : int res = 0;
73 : 33 : struct kevent ke;
74 : 33 : struct timespec ts = {0};
75 : 33 : gwrlbkd_kqueue * kbkd = _gwrlbkdk(rl->backend);
76 : 33 : bzero(&ke,sizeof(ke));
77 : 33 : ke.ident = _gwrlsrcf(src)->fd;
78 : 33 : ke.udata = src;
79 : 33 : ke.flags = kflags;
80 : 33 : ke.filter = kfilter;
81 : 33 : res = kevent(kbkd->kq,&ke,1,NULL,0,&ts);
82 [ # # ]: 0 : if(res < 0 && errno != EBADF) gwprintsyserr("(9dlkF) kevent error",errno);
83 : 33 : }
84 : :
85 : 2 : void gwrl_src_file_update_flags(gwrl * rl, gwrlsrc * src, gwrlsrc_flags_t flags) {
86 : :
87 : : //enable read
88 : 2 : if(flisset(flags,GWRL_RD)) {
89 : 2 : flset(flags,GWRL_ENABLED);
90 : 2 : gwrl_bkd_kevent(rl,src,EV_ADD|EV_ENABLE,EVFILT_READ);
91 : :
92 : : //disable read
93 [ # # ][ # # ]: 2 : } else if(flisset(src->flags,GWRL_RD) && !flisset(flags,GWRL_RD)) {
94 : 0 : gwrl_bkd_kevent(rl,src,EV_ADD|EV_DISABLE,EVFILT_READ);
95 : 0 : }
96 : :
97 : : //enable write
98 [ - + ]: 2 : if(flisset(flags,GWRL_WR)) {
99 : 0 : flset(flags,GWRL_ENABLED);
100 : 0 : gwrl_bkd_kevent(rl,src,EV_ADD|EV_ENABLE,EVFILT_WRITE);
101 : 0 : }
102 : :
103 : : //disable write
104 [ - + ][ # # ]: 2 : else if(flisset(src->flags,GWRL_WR) && !flisset(flags,GWRL_WR)) {
105 : 0 : gwrl_bkd_kevent(rl,src,EV_ADD|EV_DISABLE,EVFILT_WRITE);
106 : 2 : }
107 : :
108 : 2 : src->flags = flags;
109 : 2 : }
110 : :
111 : 37 : void gwrl_bkd_src_add(gwrl * rl, gwrlsrc * src) {
112 : 37 : int kflags = 0;
113 : :
114 : 37 : if(flisset(src->flags,GWRL_RD)) {
115 : 29 : kflags = EV_ADD;
116 [ + + ]: 29 : if(!flisset(src->flags,GWRL_ENABLED)) kflags |= EV_DISABLE;
117 : 29 : gwrl_bkd_kevent(rl,src,kflags,EVFILT_READ);
118 : 29 : }
119 : :
120 [ - + ]: 37 : if(flisset(src->flags,GWRL_WR)) {
121 : 0 : kflags = EV_ADD;
122 [ # # ]: 0 : if(!flisset(src->flags,GWRL_ENABLED)) kflags |= EV_DISABLE;
123 : 0 : gwrl_bkd_kevent(rl,src,kflags,EVFILT_WRITE);
124 : 0 : }
125 : 37 : }
126 : :
127 : 5 : void gwrl_bkd_del_src(gwrl * rl, gwrlsrc * src) {
128 : 5 : if(flisset(src->flags,GWRL_RD)) {
129 : 0 : gwrl_bkd_kevent(rl,src,EV_DELETE,EVFILT_READ);
130 : 0 : }
131 : :
132 [ - + ]: 5 : if(flisset(src->flags,GWRL_WR)) {
133 : 0 : gwrl_bkd_kevent(rl,src,EV_DELETE,EVFILT_WRITE);
134 : 0 : }
135 : :
136 : 5 : flclr(src->flags,GWRL_ENABLED);
137 : 5 : }
138 : :
139 : 0 : void gwrl_bkd_enable_src(gwrl * rl, gwrlsrc * src) {
140 : 0 : if(flisset(src->flags,GWRL_RD)) {
141 : 0 : gwrl_bkd_kevent(rl,src,EV_ENABLE,EVFILT_READ);
142 : 0 : }
143 : :
144 [ # # ]: 0 : if(flisset(src->flags,GWRL_WR)) {
145 : 0 : gwrl_bkd_kevent(rl,src,EV_ENABLE,EVFILT_WRITE);
146 : 0 : }
147 : :
148 : 0 : flset(src->flags,GWRL_ENABLED);
149 : 0 : }
150 : :
151 : 2 : void gwrl_bkd_disable_src(gwrl * rl, gwrlsrc * src) {
152 : 2 : if(flisset(src->flags,GWRL_RD)) {
153 : 2 : gwrl_bkd_kevent(rl,src,EV_DISABLE,EVFILT_READ);
154 : 2 : }
155 : :
156 [ - + ]: 2 : if(flisset(src->flags,GWRL_WR)) {
157 : 0 : gwrl_bkd_kevent(rl,src,EV_DISABLE,EVFILT_WRITE);
158 : 0 : }
159 : :
160 : 2 : flclr(src->flags,GWRL_ENABLED);
161 : 2 : }
162 : :
163 : 198 : void gwrl_bkd_gather(gwrl * rl) {
164 : 198 : int i = 0;
165 : 198 : int res = 0;
166 : 198 : bool postread = false;
167 : 198 : bool postwrite = false;
168 : 198 : struct kevent * event;
169 : 198 : struct timespec * timeout = &rl->backend->timeout;
170 : 198 : gwrlsrc * src = NULL;
171 : 198 : gwrlevt * evt = NULL;
172 : 198 : gwrlsrc_file * fsrc = NULL;
173 : 198 : gwrlbkd_kqueue * kbkd = _gwrlbkdk(rl->backend);
174 : :
175 [ + - ]: 13 : if(timeout->tv_sec == sec_min && timeout->tv_nsec == nsec_min) {
176 : 13 : timeout = NULL;
177 : 13 : }
178 : :
179 [ + + ][ + + ]: 198 : if(!timeout && flisset(rl->flags,GWRL_NOSLEEP)) {
180 : 11 : struct timespec ts = {0};
181 : 11 : timeout = &ts;
182 : 11 : }
183 : :
184 : 198 : flset(rl->flags,GWRL_SLEEPING);
185 : 198 : res = kevent(kbkd->kq,NULL,0,kbkd->kevents,rl->options.gwrl_kqueue_kevent_count,timeout);
186 : 198 : flclr(rl->flags,GWRL_SLEEPING);
187 : :
188 [ + + ]: 198 : if(res == 0) return;
189 [ - + ][ # # ]: 102 : if(res < 0 && (errno == EINVAL || errno == EINTR)) return;
[ # # ]
190 : :
191 [ + - ]: 102 : if(res > 0) {
192 [ + + ]: 204 : while(i < res) {
193 : 102 : event = &kbkd->kevents[i];
194 : 102 : src = event->udata;
195 [ - + ]: 102 : if(!flisset(src->flags,GWRL_ENABLED)) continue;
196 : :
197 [ + - ]: 102 : if(src->type == GWRL_SRC_TYPE_FILE) {
198 : 102 : fsrc = _gwrlsrcf(src);
199 : :
200 [ - + ]: 102 : if(event->flags & EV_ERROR) {
201 : 0 : gwrl_src_disable(rl,src);
202 : 0 : postread = true;
203 : 0 : }
204 : :
205 [ + - ][ - + ]: 102 : if((src->flags & GWRL_RD) && (event->flags & EV_EOF)) {
206 : 0 : postread = true;
207 [ + - ][ + - ]: 102 : } else if((src->flags & GWRL_RD) && (event->filter == EVFILT_READ)) {
208 : 102 : postread = true;
209 : 102 : }
210 : :
211 [ - + ][ # # ]: 102 : if((src->flags & GWRL_WR) && (event->filter == EVFILT_WRITE)) {
212 : 0 : postwrite = true;
213 : 0 : }
214 : :
215 [ + - ]: 102 : if(postread) {
216 : 102 : evt = gwrl_evt_create(rl,src,src->callback,src->userdata,fsrc->fd,GWRL_RD);
217 [ - + ]: 102 : while(!evt) evt = gwrl_evt_create(rl,src,src->callback,src->userdata,fsrc->fd,GWRL_RD);
218 : 102 : gwrl_post_evt(rl,evt);
219 : 102 : }
220 : :
221 [ # # ]: 0 : else if(postwrite) {
222 : 0 : evt = gwrl_evt_create(rl,src,src->callback,src->userdata,fsrc->fd,GWRL_WR);
223 [ # # ]: 0 : while(!evt) evt = gwrl_evt_create(rl,src,src->callback,src->userdata,fsrc->fd,GWRL_WR);
224 : 0 : gwrl_post_evt(rl,evt);
225 : 0 : }
226 : 102 : }
227 : :
228 : 102 : i++;
229 : 102 : }
230 : 102 : }
231 : 198 : }
232 : :
233 : : #ifdef __cplusplus
234 : : }
235 : : #endif
|