varnish-cache/lib/libvarnish/vev.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2009 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include "config.h"
31
32
#include <time.h>
33
#include <errno.h>
34
#include <poll.h>
35
#include <pthread.h>
36
#include <signal.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
41
#include "vdef.h"
42
#include "miniobj.h"
43
#include "vas.h"
44
45
#include "binary_heap.h"
46
#include "vev.h"
47
#include "vtim.h"
48
49
#undef DEBUG_EVENTS
50
51
/* INFTIM indicates an infinite timeout for poll(2) */
52
#ifndef INFTIM
53
#define INFTIM -1
54
#endif
55
56
struct vevsig {
57
        struct vev_root         *vevb;
58
        struct vev              *vev;
59
        struct sigaction        sigact;
60
        unsigned char           happened;
61
};
62
63
static struct vevsig            *vev_sigs;
64
static int                      vev_nsig;
65
66
struct vev_root {
67
        unsigned                magic;
68
#define VEV_BASE_MAGIC          0x477bcf3d
69
        struct pollfd           *pfd;
70
        struct vev              **pev;
71
        unsigned                npfd;
72
        unsigned                lpfd;
73
        struct binheap          *binheap;
74
        unsigned                psig;
75
        pthread_t               thread;
76
#ifdef DEBUG_EVENTS
77
        FILE                    *debug;
78
#endif
79
};
80
81
/*--------------------------------------------------------------------*/
82
83
#ifdef DEBUG_EVENTS
84
#define DBG(evb, ...) do {                              \
85
        if ((evb)->debug != NULL)                       \
86
                fprintf((evb)->debug, __VA_ARGS__);     \
87
        } while (0);
88
#else
89
#define DBG(evb, ...)   /* ... */
90
//#define DBG(evb, ...) fprintf(stderr, __VA_ARGS__);
91
#endif
92
93
/*--------------------------------------------------------------------*/
94
95
static void v_matchproto_(binheap_update_t)
96 219991
vev_bh_update(void *priv, void *a, unsigned u)
97
{
98
        struct vev_root *evb;
99
        struct vev *e;
100
101 219991
        CAST_OBJ_NOTNULL(evb, priv, VEV_BASE_MAGIC);
102 219991
        CAST_OBJ_NOTNULL(e, a, VEV_MAGIC);
103 219991
        assert(u < evb->lpfd);
104 219991
        e->__binheap_idx = u;
105 219991
        if (u != BINHEAP_NOIDX) {
106 196897
                evb->pev[u] = e;
107 196897
                evb->pfd[u].fd = e->fd;
108 393794
                evb->pfd[u].events =
109 196897
                    e->fd_flags & (VEV__RD|VEV__WR|VEV__ERR|VEV__HUP);
110
        }
111 219991
}
112
113
static int v_matchproto_(binheap_cmp_t)
114 132100
vev_bh_cmp(void *priv, const void *a, const void *b)
115
{
116
        struct vev_root *evb;
117
        const struct vev *ea, *eb;
118
119 132100
        CAST_OBJ_NOTNULL(evb, priv, VEV_BASE_MAGIC);
120 132100
        CAST_OBJ_NOTNULL(ea, a, VEV_MAGIC);
121 132100
        CAST_OBJ_NOTNULL(eb, b, VEV_MAGIC);
122 132100
        return (ea->__when < eb->__when);
123
}
124
125
/*--------------------------------------------------------------------*/
126
127
static int
128 20288
vev_get_pfd(struct vev_root *evb)
129
{
130
        unsigned u;
131
132 20288
        if (evb->lpfd + 1 < evb->npfd)
133 16404
                return (0);
134
135 3884
        if (evb->npfd < 8)
136 2640
                u = 8;
137 1244
        else if (evb->npfd > 256)
138 0
                u = evb->npfd + 256;
139
        else
140 1244
                u = evb->npfd * 2;
141 3884
        evb->npfd = u;
142 3884
        evb->pfd = realloc(evb->pfd, sizeof(*evb->pfd) * u);
143 3884
        AN(evb->pfd);
144 3884
        evb->pev = realloc(evb->pev, sizeof(*evb->pev) * u);
145 3884
        AN(evb->pev);
146 3884
        return (0);
147
}
148
149
/*--------------------------------------------------------------------*/
150
151
static int
152 2488
vev_get_sig(int sig)
153
{
154
        struct vevsig *os;
155
156 2488
        if (sig < vev_nsig)
157 1244
                return (0);
158
159 1244
        os = calloc((sig + 1L), sizeof *os);
160 1244
        if (os == NULL)
161 0
                return (ENOMEM);
162
163 1244
        if (vev_sigs != NULL) {
164 0
                memcpy(os, vev_sigs, vev_nsig * sizeof *os);
165 0
                free(vev_sigs);
166
        }
167 1244
        vev_sigs = os;
168 1244
        vev_nsig = sig + 1;
169
170 1244
        return (0);
171
}
172
173
/*--------------------------------------------------------------------*/
174
175
static void
176 4
vev_sighandler(int sig)
177
{
178
        struct vevsig *es;
179
180 4
        assert(sig < vev_nsig);
181 4
        assert(vev_sigs != NULL);
182 4
        es = &vev_sigs[sig];
183 4
        if (!es->happened)
184 4
                es->vevb->psig++;
185 4
        es->happened = 1;
186 4
}
187
188
/*--------------------------------------------------------------------*/
189
190
struct vev_root *
191 2640
VEV_New(void)
192
{
193
        struct vev_root *evb;
194
195 2640
        evb = calloc(1, sizeof *evb);
196 2640
        if (evb == NULL)
197 0
                return (evb);
198 2640
        evb->lpfd = BINHEAP_NOIDX + 1;
199 2640
        if (vev_get_pfd(evb)) {
200 0
                free(evb);
201 0
                return (NULL);
202
        }
203 2640
        evb->magic = VEV_BASE_MAGIC;
204 2640
        evb->binheap = binheap_new(evb, vev_bh_cmp, vev_bh_update);
205 2640
        evb->thread = pthread_self();
206
#ifdef DEBUG_EVENTS
207
        evb->debug = fopen("/tmp/_.events", "w");
208
        AN(evb->debug);
209
        setbuf(evb->debug, NULL);
210
        DBG(evb, "\n\nStart debugging\n");
211
#endif
212 2640
        return (evb);
213
}
214
215
/*--------------------------------------------------------------------*/
216
217
void
218 1244
VEV_Destroy(struct vev_root **evbp)
219
{
220
        struct vev_root *evb;
221
222 1244
        AN(evbp);
223 1244
        evb = *evbp;
224 1244
        *evbp = NULL;
225 1244
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
226 1244
        assert(evb->thread == pthread_self());
227 1244
        evb->magic = 0;
228 1244
        free(evb);
229 1244
}
230
231
/*--------------------------------------------------------------------*/
232
233
struct vev *
234 17648
VEV_Alloc(void)
235
{
236
        struct vev *e;
237
238 17648
        e = calloc(1, sizeof *e);
239 17648
        if (e != NULL) {
240 17648
                e->fd = -1;
241
        }
242 17648
        return (e);
243
}
244
245
/*--------------------------------------------------------------------*/
246
247
int
248 17648
VEV_Start(struct vev_root *evb, struct vev *e)
249
{
250
        struct vevsig *es;
251
252 17648
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
253 17648
        assert(e->magic != VEV_MAGIC);
254 17648
        assert(e->callback != NULL);
255 17648
        assert(e->sig >= 0);
256 17648
        assert(e->timeout >= 0.0);
257 17648
        assert(e->fd < 0 || e->fd_flags);
258 17648
        assert(evb->thread == pthread_self());
259
        DBG(evb, "ev_add(%p) fd = %d\n", e, e->fd);
260
261 17648
        if (vev_get_pfd(evb))
262 0
                return (ENOMEM);
263
264 17648
        if (e->sig > 0) {
265 2488
                if (vev_get_sig(e->sig))
266 0
                        return (ENOMEM);
267
268 2488
                assert(e->fd < 0);
269 2488
                es = &vev_sigs[e->sig];
270 2488
                if (es->vev != NULL)
271 0
                        return (EBUSY);
272 2488
                AZ(es->happened);
273 2488
                es->vev = e;
274 2488
                es->vevb = evb;
275 2488
                es->sigact.sa_flags = e->sig_flags;
276 2488
                es->sigact.sa_handler = vev_sighandler;
277
        } else {
278 15160
                es = NULL;
279
        }
280
281 17648
        e->magic = VEV_MAGIC;   /* before binheap_insert() */
282
283 17648
        if (e->timeout != 0.0)
284 6328
                e->__when += VTIM_mono() + e->timeout;
285
        else
286 11320
                e->__when = 9e99;
287
288 17648
        evb->lpfd++;
289 17648
        binheap_insert(evb->binheap, e);
290 17648
        assert(e->__binheap_idx != BINHEAP_NOIDX);
291
292 17648
        e->__vevb = evb;
293 17648
        e->__privflags = 0;
294
295 17648
        if (e->sig > 0) {
296 2488
                assert(es != NULL);
297 2488
                AZ(sigaction(e->sig, &es->sigact, NULL));
298
        }
299
300 17648
        return (0);
301
}
302
303
/*--------------------------------------------------------------------*/
304
305
void
306 8848
VEV_Stop(struct vev_root *evb, struct vev *e)
307
{
308
        struct vevsig *es;
309
310 8848
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
311 8848
        CHECK_OBJ_NOTNULL(e, VEV_MAGIC);
312
        DBG(evb, "ev_del(%p) fd = %d i=%u L=%d\n", e, e->fd, e->__binheap_idx, evb->lpfd);
313 8848
        assert(evb == e->__vevb);
314 8848
        assert(evb->thread == pthread_self());
315 8848
        assert(evb->pev[e->__binheap_idx] == e);
316
317 8848
        assert(e->__binheap_idx != BINHEAP_NOIDX);
318 8848
        e->fd = -1;
319 8848
        binheap_delete(evb->binheap, e->__binheap_idx);
320 8848
        assert(e->__binheap_idx == BINHEAP_NOIDX);
321 8848
        evb->lpfd--;
322
323 8848
        if (e->sig > 0) {
324 4
                assert(e->sig < vev_nsig);
325 4
                es = &vev_sigs[e->sig];
326 4
                assert(es->vev == e);
327 4
                es->vev = NULL;
328 4
                es->vevb = NULL;
329 4
                es->sigact.sa_flags = e->sig_flags;
330 4
                es->sigact.sa_handler = SIG_DFL;
331 4
                AZ(sigaction(e->sig, &es->sigact, NULL));
332 4
                es->happened = 0;
333
        }
334
335 8848
        e->magic = 0;
336 8848
        e->__vevb = NULL;
337 8848
}
338
339
/*--------------------------------------------------------------------*/
340
341
int
342 1244
VEV_Loop(struct vev_root *evb)
343
{
344
        int i;
345
346 1244
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
347 1244
        assert(evb->thread == pthread_self());
348
        do
349 51839
                i = VEV_Once(evb);
350 51839
        while (i == 1);
351 1244
        return (i);
352
}
353
354
/*--------------------------------------------------------------------*/
355
356
static int
357 14246
vev_sched_timeout(struct vev_root *evb, struct vev *e, double t)
358
{
359
        int i;
360
361
362 14246
        i = e->callback(e, 0);
363 14246
        if (i) {
364 0
                VEV_Stop(evb, e);
365 0
                free(e);
366
        } else {
367 14246
                e->__when = t + e->timeout;
368 14246
                binheap_delete(evb->binheap, e->__binheap_idx);
369 14246
                binheap_insert(evb->binheap, e);
370
        }
371 14246
        return (1);
372
}
373
374
static int
375 4
vev_sched_signal(struct vev_root *evb)
376
{
377 4
        int i, j, retval = 1;
378
        struct vevsig *es;
379
        struct vev *e;
380
381 4
        es = vev_sigs;
382 68
        for (j = 0; j < vev_nsig; j++, es++) {
383 64
                if (!es->happened || es->vevb != evb)
384 60
                        continue;
385 4
                evb->psig--;
386 4
                es->happened = 0;
387 4
                e = es->vev;
388 4
                assert(e != NULL);
389 4
                i = e->callback(e, VEV__SIG);
390 4
                if (i) {
391 4
                        VEV_Stop(evb, e);
392 4
                        free(e);
393
                }
394 4
                if (i < 0)
395 4
                        retval = i;
396
        }
397 4
        return (retval);
398
}
399
400
int
401 54509
VEV_Once(struct vev_root *evb)
402
{
403
        double t;
404
        struct vev *e;
405 54509
        int i, j, k, tmo, retval = 1;
406
407 54509
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
408 54509
        assert(evb->thread == pthread_self());
409 54509
        assert(evb->lpfd < evb->npfd);
410
411 54509
        if (evb->psig)
412 0
                return (vev_sched_signal(evb));
413
414 54509
        e = binheap_root(evb->binheap);
415 54509
        if (e != NULL) {
416 53201
                CHECK_OBJ_NOTNULL(e, VEV_MAGIC);
417 53201
                assert(e->__binheap_idx == BINHEAP_NOIDX + 1);
418 53201
                t = VTIM_mono();
419 53201
                if (e->__when <= t)
420 9156
                        return (vev_sched_timeout(evb, e, t));
421 44045
                tmo = (int)((e->__when - t) * 1e3);
422 44045
                if (tmo == 0)
423 353
                        tmo = 1;
424
        } else
425 1308
                tmo = INFTIM;
426
427 45353
        if (tmo == INFTIM && evb->lpfd == BINHEAP_NOIDX + 1)
428 1308
                return (0);
429
430 44045
        i = poll(evb->pfd + 1, evb->lpfd - 1, tmo);
431 44045
        if (i == -1 && errno == EINTR)
432 4
                return (vev_sched_signal(evb));
433
434 44041
        if (i == 0) {
435 5373
                assert(e != NULL);
436 5373
                t = VTIM_mono();
437 5373
                if (e->__when <= t)
438 5090
                        return (vev_sched_timeout(evb, e, t));
439
        }
440
441 38951
        k = 0;
442 418916
        for (j = 1; j < evb->lpfd; j++) {
443 379965
                evb->pev[j]->fd_events = evb->pfd[j].revents;
444 379965
                if (evb->pev[j]->fd_events)
445 39843
                        k++;
446
        }
447 38951
        assert(k == i);
448
449
        DBG(evb, "EVENTS %d\n", i);
450 116563
        while (i > 0) {
451 413411
                for (j = BINHEAP_NOIDX + 1; j < evb->lpfd; j++) {
452 374750
                        e = evb->pev[j];
453 374750
                        if (e->fd_events == 0)
454 334907
                                continue;
455
                        DBG(evb, "EVENT %p j=%d fd=%d ev=0x%x %d\n",
456
                            e, j, e->fd, e->fd_events, i);
457 39843
                        k = e->callback(e, e->fd_events);
458 39835
                        e->fd_events = 0;
459 39835
                        i--;
460 39835
                        if (k) {
461 5042
                                VEV_Stop(evb, e);
462 5042
                                free(e);
463
                        }
464 39835
                        if (k < 0)
465 1240
                                retval = k;
466
                }
467
        }
468 38943
        AZ(i);
469 38943
        return (retval);
470
}