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 125796
vev_bh_update(void *priv, void *a, unsigned u)
97
{
98
        struct vev_root *evb;
99
        struct vev *e;
100
101 125796
        CAST_OBJ_NOTNULL(evb, priv, VEV_BASE_MAGIC);
102 125796
        CAST_OBJ_NOTNULL(e, a, VEV_MAGIC);
103 125796
        assert(u < evb->lpfd);
104 125796
        e->__binheap_idx = u;
105 125796
        if (u != BINHEAP_NOIDX) {
106 112686
                evb->pev[u] = e;
107 112686
                evb->pfd[u].fd = e->fd;
108 225372
                evb->pfd[u].events =
109 112686
                    e->fd_flags & (VEV__RD|VEV__WR|VEV__ERR|VEV__HUP);
110
        }
111 125796
}
112
113
static int v_matchproto_(binheap_cmp_t)
114 77431
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 77431
        CAST_OBJ_NOTNULL(evb, priv, VEV_BASE_MAGIC);
120 77431
        CAST_OBJ_NOTNULL(ea, a, VEV_MAGIC);
121 77431
        CAST_OBJ_NOTNULL(eb, b, VEV_MAGIC);
122 77431
        return (ea->__when < eb->__when);
123
}
124
125
/*--------------------------------------------------------------------*/
126
127
static int
128 11647
vev_get_pfd(struct vev_root *evb)
129
{
130
        unsigned u;
131
132 11647
        if (evb->lpfd + 1 < evb->npfd)
133 9396
                return (0);
134
135 2251
        if (evb->npfd < 8)
136 1541
                u = 8;
137 710
        else if (evb->npfd > 256)
138 0
                u = evb->npfd + 256;
139
        else
140 710
                u = evb->npfd * 2;
141 2251
        evb->npfd = u;
142 2251
        evb->pfd = realloc(evb->pfd, sizeof(*evb->pfd) * u);
143 2251
        AN(evb->pfd);
144 2251
        evb->pev = realloc(evb->pev, sizeof(*evb->pev) * u);
145 2251
        AN(evb->pev);
146 2251
        return (0);
147
}
148
149
/*--------------------------------------------------------------------*/
150
151
static int
152 1420
vev_get_sig(int sig)
153
{
154
        struct vevsig *os;
155
156 1420
        if (sig < vev_nsig)
157 710
                return (0);
158
159 710
        os = calloc((sig + 1L), sizeof *os);
160 710
        if (os == NULL)
161 0
                return (ENOMEM);
162
163 710
        if (vev_sigs != NULL) {
164 0
                memcpy(os, vev_sigs, vev_nsig * sizeof *os);
165 0
                free(vev_sigs);
166
        }
167 710
        vev_sigs = os;
168 710
        vev_nsig = sig + 1;
169
170 710
        return (0);
171
}
172
173
/*--------------------------------------------------------------------*/
174
175
static void
176 2
vev_sighandler(int sig)
177
{
178
        struct vevsig *es;
179
180 2
        assert(sig < vev_nsig);
181 2
        assert(vev_sigs != NULL);
182 2
        es = &vev_sigs[sig];
183 2
        if (!es->happened)
184 2
                es->vevb->psig++;
185 2
        es->happened = 1;
186 2
}
187
188
/*--------------------------------------------------------------------*/
189
190
struct vev_root *
191 1541
VEV_New(void)
192
{
193
        struct vev_root *evb;
194
195 1541
        evb = calloc(1, sizeof *evb);
196 1541
        if (evb == NULL)
197 0
                return (evb);
198 1541
        evb->lpfd = BINHEAP_NOIDX + 1;
199 1541
        if (vev_get_pfd(evb)) {
200 0
                free(evb);
201 0
                return (NULL);
202
        }
203 1541
        evb->magic = VEV_BASE_MAGIC;
204 1541
        evb->binheap = binheap_new(evb, vev_bh_cmp, vev_bh_update);
205 1541
        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 1541
        return (evb);
213
}
214
215
/*--------------------------------------------------------------------*/
216
217
void
218 737
VEV_Destroy(struct vev_root **evbp)
219
{
220
        struct vev_root *evb;
221
222 737
        TAKE_OBJ_NOTNULL(evb, evbp, VEV_BASE_MAGIC);
223 737
        assert(evb->thread == pthread_self());
224 737
        free(evb->pfd);
225 737
        free(evb->pev);
226
        /* destroy evb->binheap */
227 737
        evb->magic = 0;
228 737
        free(evb);
229 737
}
230
231
/*--------------------------------------------------------------------*/
232
233
struct vev *
234 10106
VEV_Alloc(void)
235
{
236
        struct vev *e;
237
238 10106
        e = calloc(1, sizeof *e);
239 10106
        if (e != NULL) {
240 10106
                e->fd = -1;
241
        }
242 10106
        return (e);
243
}
244
245
/*--------------------------------------------------------------------*/
246
247
int
248 10106
VEV_Start(struct vev_root *evb, struct vev *e)
249
{
250
        struct vevsig *es;
251
252 10106
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
253 10106
        assert(e->magic != VEV_MAGIC);
254 10106
        assert(e->callback != NULL);
255 10106
        assert(e->sig >= 0);
256 10106
        assert(e->timeout >= 0.0);
257 10106
        assert(e->fd < 0 || e->fd_flags);
258 10106
        assert(evb->thread == pthread_self());
259
        DBG(evb, "ev_add(%p) fd = %d\n", e, e->fd);
260
261 10106
        if (vev_get_pfd(evb))
262 0
                return (ENOMEM);
263
264 10106
        if (e->sig > 0) {
265 1420
                if (vev_get_sig(e->sig))
266 0
                        return (ENOMEM);
267
268 1420
                assert(e->fd < 0);
269 1420
                es = &vev_sigs[e->sig];
270 1420
                if (es->vev != NULL)
271 0
                        return (EBUSY);
272 1420
                AZ(es->happened);
273 1420
                es->vev = e;
274 1420
                es->vevb = evb;
275 1420
                es->sigact.sa_flags = e->sig_flags;
276 1420
                es->sigact.sa_handler = vev_sighandler;
277
        } else {
278 8686
                es = NULL;
279
        }
280
281 10106
        e->magic = VEV_MAGIC;   /* before binheap_insert() */
282
283 10106
        if (e->timeout != 0.0)
284 3601
                e->__when += VTIM_mono() + e->timeout;
285
        else
286 6505
                e->__when = 9e99;
287
288 10106
        evb->lpfd++;
289 10106
        binheap_insert(evb->binheap, e);
290 10106
        assert(e->__binheap_idx != BINHEAP_NOIDX);
291
292 10106
        e->__vevb = evb;
293 10106
        e->__privflags = 0;
294
295 10106
        if (e->sig > 0) {
296 1420
                assert(es != NULL);
297 1420
                AZ(sigaction(e->sig, &es->sigact, NULL));
298
        }
299
300 10106
        return (0);
301
}
302
303
/*--------------------------------------------------------------------*/
304
305
void
306 4579
VEV_Stop(struct vev_root *evb, struct vev *e)
307
{
308
        struct vevsig *es;
309
310 4579
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
311 4579
        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 4579
        assert(evb == e->__vevb);
314 4579
        assert(evb->thread == pthread_self());
315 4579
        assert(evb->pev[e->__binheap_idx] == e);
316
317 4579
        assert(e->__binheap_idx != BINHEAP_NOIDX);
318 4579
        e->fd = -1;
319 4579
        binheap_delete(evb->binheap, e->__binheap_idx);
320 4579
        assert(e->__binheap_idx == BINHEAP_NOIDX);
321 4579
        evb->lpfd--;
322
323 4579
        if (e->sig > 0) {
324 2
                assert(e->sig < vev_nsig);
325 2
                es = &vev_sigs[e->sig];
326 2
                assert(es->vev == e);
327 2
                es->vev = NULL;
328 2
                es->vevb = NULL;
329 2
                es->sigact.sa_flags = e->sig_flags;
330 2
                es->sigact.sa_handler = SIG_DFL;
331 2
                AZ(sigaction(e->sig, &es->sigact, NULL));
332 2
                es->happened = 0;
333
        }
334
335 4579
        e->magic = 0;
336 4579
        e->__vevb = NULL;
337 4579
}
338
339
/*--------------------------------------------------------------------*/
340
341
int
342 710
VEV_Loop(struct vev_root *evb)
343
{
344
        int i;
345
346 710
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
347 710
        assert(evb->thread == pthread_self());
348
        do
349 30062
                i = VEV_Once(evb);
350 30062
        while (i == 1);
351 710
        return (i);
352
}
353
354
/*--------------------------------------------------------------------*/
355
356
static int
357 8531
vev_sched_timeout(struct vev_root *evb, struct vev *e, double t)
358
{
359
        int i;
360
361
362 8531
        i = e->callback(e, 0);
363 8531
        if (i) {
364 0
                VEV_Stop(evb, e);
365 0
                free(e);
366
        } else {
367 8531
                e->__when = t + e->timeout;
368 8531
                binheap_delete(evb->binheap, e->__binheap_idx);
369 8531
                binheap_insert(evb->binheap, e);
370
        }
371 8531
        return (1);
372
}
373
374
static int
375 2
vev_sched_signal(struct vev_root *evb)
376
{
377 2
        int i, j, retval = 1;
378
        struct vevsig *es;
379
        struct vev *e;
380
381 2
        es = vev_sigs;
382 34
        for (j = 0; j < vev_nsig; j++, es++) {
383 32
                if (!es->happened || es->vevb != evb)
384 30
                        continue;
385 2
                evb->psig--;
386 2
                es->happened = 0;
387 2
                e = es->vev;
388 2
                assert(e != NULL);
389 2
                i = e->callback(e, VEV__SIG);
390 2
                if (i) {
391 2
                        VEV_Stop(evb, e);
392 2
                        free(e);
393
                }
394 2
                if (i < 0)
395 2
                        retval = i;
396
        }
397 2
        return (retval);
398
}
399
400
int
401 32345
VEV_Once(struct vev_root *evb)
402
{
403
        double t;
404
        struct vev *e;
405 32345
        int i, j, k, tmo, retval = 1;
406
407 32345
        CHECK_OBJ_NOTNULL(evb, VEV_BASE_MAGIC);
408 32345
        assert(evb->thread == pthread_self());
409 32345
        assert(evb->lpfd < evb->npfd);
410
411 32345
        if (evb->psig)
412 0
                return (vev_sched_signal(evb));
413
414 32345
        tmo = INFTIM;
415 32345
        e = binheap_root(evb->binheap);
416 32345
        if (e != NULL) {
417 31580
                CHECK_OBJ_NOTNULL(e, VEV_MAGIC);
418 31580
                assert(e->__binheap_idx == BINHEAP_NOIDX + 1);
419 31580
                t = VTIM_mono();
420 31580
                if (e->__when <= t)
421 5044
                        return (vev_sched_timeout(evb, e, t));
422 26536
                if (e->__when < 9e99)
423 25783
                        tmo = (int)((e->__when - t) * 1e3);
424 26536
                if (tmo == 0)
425 195
                        tmo = 1;
426
        }
427
428 27301
        if (tmo == INFTIM && evb->lpfd == BINHEAP_NOIDX + 1)
429 765
                return (0);
430
431 26536
        i = poll(evb->pfd + 1, evb->lpfd - 1, tmo);
432 26536
        if (i == -1 && errno == EINTR)
433 2
                return (vev_sched_signal(evb));
434 26534
        if (i == -1)
435 0
                return (-1);
436
437 26534
        if (i == 0) {
438 3665
                assert(e != NULL);
439 3665
                t = VTIM_mono();
440 3665
                if (e->__when <= t)
441 3487
                        return (vev_sched_timeout(evb, e, t));
442
        }
443
444 23047
        k = 0;
445 241632
        for (j = 1; j < evb->lpfd; j++) {
446 218585
                evb->pev[j]->fd_events = evb->pfd[j].revents;
447 218585
                if (evb->pev[j]->fd_events)
448 23030
                        k++;
449
        }
450 23047
        assert(k == i);
451
452
        DBG(evb, "EVENTS %d\n", i);
453 69029
        while (i > 0) {
454 239427
                for (j = BINHEAP_NOIDX + 1; j < evb->lpfd; j++) {
455 216492
                        e = evb->pev[j];
456 216492
                        if (e->fd_events == 0)
457 193462
                                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 23030
                        k = e->callback(e, e->fd_events);
461 23026
                        e->fd_events = 0;
462 23026
                        i--;
463 23026
                        if (k) {
464 2416
                                VEV_Stop(evb, e);
465 2416
                                free(e);
466
                        }
467 23026
                        if (k < 0)
468 708
                                retval = k;
469
                }
470
        }
471 23043
        AZ(i);
472 23043
        return (retval);
473
}