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 263652
vev_bh_update(void *priv, void *a, unsigned u)
97
{
98
        struct vev_root *evb;
99
        struct vev *e;
100
101 263652
        CAST_OBJ_NOTNULL(evb, priv, VEV_BASE_MAGIC);
102 263652
        CAST_OBJ_NOTNULL(e, a, VEV_MAGIC);
103 263652
        assert(u < evb->lpfd);
104 263652
        e->__binheap_idx = u;
105 263652
        if (u != BINHEAP_NOIDX) {
106 236859
                evb->pev[u] = e;
107 236859
                evb->pfd[u].fd = e->fd;
108 473718
                evb->pfd[u].events =
109 236859
                    e->fd_flags & (VEV__RD|VEV__WR|VEV__ERR|VEV__HUP);
110
        }
111 263652
}
112
113
static int v_matchproto_(binheap_cmp_t)
114 158897
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 158897
        CAST_OBJ_NOTNULL(evb, priv, VEV_BASE_MAGIC);
120 158897
        CAST_OBJ_NOTNULL(ea, a, VEV_MAGIC);
121 158897
        CAST_OBJ_NOTNULL(eb, b, VEV_MAGIC);
122 158897
        return (ea->__when < eb->__when);
123
}
124
125
/*--------------------------------------------------------------------*/
126
127
static int
128 23394
vev_get_pfd(struct vev_root *evb)
129
{
130
        unsigned u;
131
132 23394
        if (evb->lpfd + 1 < evb->npfd)
133 18880
                return (0);
134
135 4514
        if (evb->npfd < 8)
136 3088
                u = 8;
137 1426
        else if (evb->npfd > 256)
138 0
                u = evb->npfd + 256;
139
        else
140 1426
                u = evb->npfd * 2;
141 4514
        evb->npfd = u;
142 4514
        evb->pfd = realloc(evb->pfd, sizeof(*evb->pfd) * u);
143 4514
        AN(evb->pfd);
144 4514
        evb->pev = realloc(evb->pev, sizeof(*evb->pev) * u);
145 4514
        AN(evb->pev);
146 4514
        return (0);
147
}
148
149
/*--------------------------------------------------------------------*/
150
151
static int
152 2852
vev_get_sig(int sig)
153
{
154
        struct vevsig *os;
155
156 2852
        if (sig < vev_nsig)
157 1426
                return (0);
158
159 1426
        os = calloc((sig + 1L), sizeof *os);
160 1426
        if (os == NULL)
161 0
                return (ENOMEM);
162
163 1426
        if (vev_sigs != NULL) {
164 0
                memcpy(os, vev_sigs, vev_nsig * sizeof *os);
165 0
                free(vev_sigs);
166
        }
167 1426
        vev_sigs = os;
168 1426
        vev_nsig = sig + 1;
169
170 1426
        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 3088
VEV_New(void)
192
{
193
        struct vev_root *evb;
194
195 3088
        evb = calloc(1, sizeof *evb);
196 3088
        if (evb == NULL)
197 0
                return (evb);
198 3088
        evb->lpfd = BINHEAP_NOIDX + 1;
199 3088
        if (vev_get_pfd(evb)) {
200 0
                free(evb);
201 0
                return (NULL);
202
        }
203 3088
        evb->magic = VEV_BASE_MAGIC;
204 3088
        evb->binheap = binheap_new(evb, vev_bh_cmp, vev_bh_update);
205 3088
        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 3088
        return (evb);
213
}
214
215
/*--------------------------------------------------------------------*/
216
217
void
218 1492
VEV_Destroy(struct vev_root **evbp)
219
{
220
        struct vev_root *evb;
221
222 1492
        TAKE_OBJ_NOTNULL(evb, evbp, VEV_BASE_MAGIC);
223 1492
        assert(evb->thread == pthread_self());
224 1492
        free(evb->pfd);
225 1492
        free(evb->pev);
226
        /* destroy evb->binheap */
227 1492
        evb->magic = 0;
228 1492
        free(evb);
229 1492
}
230
231
/*--------------------------------------------------------------------*/
232
233
struct vev *
234 20306
VEV_Alloc(void)
235
{
236
        struct vev *e;
237
238 20306
        e = calloc(1, sizeof *e);
239 20306
        if (e != NULL) {
240 20306
                e->fd = -1;
241
        }
242 20306
        return (e);
243
}
244
245
/*--------------------------------------------------------------------*/
246
247
int
248 20306
VEV_Start(struct vev_root *evb, struct vev *e)
249
{
250
        struct vevsig *es;
251
252 20306
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
253 20306
        assert(e->magic != VEV_MAGIC);
254 20306
        assert(e->callback != NULL);
255 20306
        assert(e->sig >= 0);
256 20306
        assert(e->timeout >= 0.0);
257 20306
        assert(e->fd < 0 || e->fd_flags);
258 20306
        assert(evb->thread == pthread_self());
259
        DBG(evb, "ev_add(%p) fd = %d\n", e, e->fd);
260
261 20306
        if (vev_get_pfd(evb))
262 0
                return (ENOMEM);
263
264 20306
        if (e->sig > 0) {
265 2852
                if (vev_get_sig(e->sig))
266 0
                        return (ENOMEM);
267
268 2852
                assert(e->fd < 0);
269 2852
                es = &vev_sigs[e->sig];
270 2852
                if (es->vev != NULL)
271 0
                        return (EBUSY);
272 2852
                AZ(es->happened);
273 2852
                es->vev = e;
274 2852
                es->vevb = evb;
275 2852
                es->sigact.sa_flags = e->sig_flags;
276 2852
                es->sigact.sa_handler = vev_sighandler;
277
        } else {
278 17454
                es = NULL;
279
        }
280
281 20306
        e->magic = VEV_MAGIC;   /* before binheap_insert() */
282
283 20306
        if (e->timeout != 0.0)
284 7222
                e->__when += VTIM_mono() + e->timeout;
285
        else
286 13084
                e->__when = 9e99;
287
288 20306
        evb->lpfd++;
289 20306
        binheap_insert(evb->binheap, e);
290 20306
        assert(e->__binheap_idx != BINHEAP_NOIDX);
291
292 20306
        e->__vevb = evb;
293 20306
        e->__privflags = 0;
294
295 20306
        if (e->sig > 0) {
296 2852
                assert(es != NULL);
297 2852
                AZ(sigaction(e->sig, &es->sigact, NULL));
298
        }
299
300 20306
        return (0);
301
}
302
303
/*--------------------------------------------------------------------*/
304
305
void
306 9401
VEV_Stop(struct vev_root *evb, struct vev *e)
307
{
308
        struct vevsig *es;
309
310 9401
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
311 9401
        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 9401
        assert(evb == e->__vevb);
314 9401
        assert(evb->thread == pthread_self());
315 9401
        assert(evb->pev[e->__binheap_idx] == e);
316
317 9401
        assert(e->__binheap_idx != BINHEAP_NOIDX);
318 9401
        e->fd = -1;
319 9401
        binheap_delete(evb->binheap, e->__binheap_idx);
320 9401
        assert(e->__binheap_idx == BINHEAP_NOIDX);
321 9401
        evb->lpfd--;
322
323 9401
        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 9401
        e->magic = 0;
336 9401
        e->__vevb = NULL;
337 9401
}
338
339
/*--------------------------------------------------------------------*/
340
341
int
342 1426
VEV_Loop(struct vev_root *evb)
343
{
344
        int i;
345
346 1426
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
347 1426
        assert(evb->thread == pthread_self());
348
        do
349 61326
                i = VEV_Once(evb);
350 61326
        while (i == 1);
351 1426
        return (i);
352
}
353
354
/*--------------------------------------------------------------------*/
355
356
static int
357 17392
vev_sched_timeout(struct vev_root *evb, struct vev *e, double t)
358
{
359
        int i;
360
361
362 17392
        i = e->callback(e, 0);
363 17392
        if (i) {
364 0
                VEV_Stop(evb, e);
365 0
                free(e);
366
        } else {
367 17392
                e->__when = t + e->timeout;
368 17392
                binheap_delete(evb->binheap, e->__binheap_idx);
369 17392
                binheap_insert(evb->binheap, e);
370
        }
371 17392
        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 66040
VEV_Once(struct vev_root *evb)
402
{
403
        double t;
404
        struct vev *e;
405 66040
        int i, j, k, tmo, retval = 1;
406
407 66040
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
408 66040
        assert(evb->thread == pthread_self());
409 66040
        assert(evb->lpfd < evb->npfd);
410
411 66040
        if (evb->psig)
412 0
                return (vev_sched_signal(evb));
413
414 66040
        tmo = INFTIM;
415 66040
        e = binheap_root(evb->binheap);
416 66040
        if (e != NULL) {
417 64496
                CHECK_OBJ_NOTNULL(e, VEV_MAGIC);
418 64496
                assert(e->__binheap_idx == BINHEAP_NOIDX + 1);
419 64496
                t = VTIM_mono();
420 64496
                if (e->__when <= t)
421 9787
                        return (vev_sched_timeout(evb, e, t));
422 54709
                if (e->__when < 9e99)
423 53069
                        tmo = (int)((e->__when - t) * 1e3);
424 54709
                if (tmo == 0)
425 883
                        tmo = 1;
426
        }
427
428 56253
        if (tmo == INFTIM && evb->lpfd == BINHEAP_NOIDX + 1)
429 1544
                return (0);
430
431 54709
        i = poll(evb->pfd + 1, evb->lpfd - 1, tmo);
432 54709
        if (i == -1 && errno == EINTR)
433 4
                return (vev_sched_signal(evb));
434 54705
        if (i == -1)
435 0
                return (-1);
436
437 54705
        if (i == 0) {
438 8411
                assert(e != NULL);
439 8411
                t = VTIM_mono();
440 8411
                if (e->__when <= t)
441 7605
                        return (vev_sched_timeout(evb, e, t));
442
        }
443
444 47100
        k = 0;
445 493552
        for (j = 1; j < evb->lpfd; j++) {
446 446452
                evb->pev[j]->fd_events = evb->pfd[j].revents;
447 446452
                if (evb->pev[j]->fd_events)
448 46829
                        k++;
449
        }
450 47100
        assert(k == i);
451
452
        DBG(evb, "EVENTS %d\n", i);
453 140548
        while (i > 0) {
454 482619
                for (j = BINHEAP_NOIDX + 1; j < evb->lpfd; j++) {
455 436271
                        e = evb->pev[j];
456 436271
                        if (e->fd_events == 0)
457 389442
                                continue;
458
                        DBG(evb, "EVENT %p j=%d fd=%d ev=0x%x %d\n",
459
                            e, j, e->fd, e->fd_events, i);
460 46829
                        k = e->callback(e, e->fd_events);
461 46821
                        e->fd_events = 0;
462 46821
                        i--;
463 46821
                        if (k) {
464 5065
                                VEV_Stop(evb, e);
465 5065
                                free(e);
466
                        }
467 46821
                        if (k < 0)
468 1422
                                retval = k;
469
                }
470
        }
471 47092
        AZ(i);
472 47092
        return (retval);
473
}