varnish-cache/bin/varnishd/waiter/cache_waiter.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 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
31
#include "config.h"
32
33
#include "cache/cache_varnishd.h"
34
35
#include <stdlib.h>
36
37
#include "binary_heap.h"
38
39
#include "waiter/waiter.h"
40
#include "waiter/waiter_priv.h"
41
#include "waiter/mgt_waiter.h"
42
43
static int v_matchproto_(binheap_cmp_t)
44 171
waited_cmp(void *priv, const void *a, const void *b)
45
{
46
        const struct waiter *ww;
47
        const struct waited *aa, *bb;
48
49 171
        CAST_OBJ_NOTNULL(ww, priv, WAITER_MAGIC);
50 171
        CAST_OBJ_NOTNULL(aa, a, WAITED_MAGIC);
51 171
        CAST_OBJ_NOTNULL(bb, b, WAITED_MAGIC);
52
53 171
        return (Wait_When(aa) < Wait_When(bb));
54
}
55
56
static void v_matchproto_(binheap_update_t)
57 5343
waited_update(void *priv, void *p, unsigned u)
58
{
59
        struct waited *pp;
60
61
        (void)priv;
62 5343
        CAST_OBJ_NOTNULL(pp, p, WAITED_MAGIC);
63 5343
        pp->idx = u;
64 5343
}
65
66
/**********************************************************************/
67
68
void
69 2508
Wait_Call(const struct waiter *w, struct waited *wp,
70
    enum wait_event ev, double now)
71
{
72 2508
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
73 2508
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
74 2508
        AN(wp->func);
75 2508
        assert(wp->idx == BINHEAP_NOIDX);
76 2508
        wp->func(wp, ev, now);
77 2508
}
78
79
/**********************************************************************/
80
81
void
82 2530
Wait_HeapInsert(const struct waiter *w, struct waited *wp)
83
{
84 2530
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
85 2530
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
86 2530
        assert(wp->idx == BINHEAP_NOIDX);
87 2530
        binheap_insert(w->heap, wp);
88 2530
}
89
90
/*
91
 * XXX: wp is const because otherwise FlexeLint complains.  However, *wp
92
 * XXX: will actually change as a result of calling this function, via
93
 * XXX: the pointer stored in the bin-heap.  I can see how this const
94
 * XXX: could maybe confuse a compilers optimizer, but I do not expect
95
 * XXX: any harm to come from it.  Caveat Emptor.
96
 */
97
98
int
99 2507
Wait_HeapDelete(const struct waiter *w, const struct waited *wp)
100
{
101 2507
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
102 2507
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
103 2507
        if (wp->idx == BINHEAP_NOIDX)
104 0
                return (0);
105 2507
        binheap_delete(w->heap, wp->idx);
106 2508
        return (1);
107
}
108
109
double
110 6284
Wait_HeapDue(const struct waiter *w, struct waited **wpp)
111
{
112
        struct waited *wp;
113
114 6284
        wp = binheap_root(w->heap);
115 6284
        CHECK_OBJ_ORNULL(wp, WAITED_MAGIC);
116 6284
        if (wp == NULL) {
117 4902
                if (wpp != NULL)
118 4902
                        *wpp = NULL;
119 4902
                return (0);
120
        }
121 1382
        if (wpp != NULL)
122 1326
                *wpp = wp;
123 1382
        return(Wait_When(wp));
124
}
125
126
/**********************************************************************/
127
128
int
129 2530
Wait_Enter(const struct waiter *w, struct waited *wp)
130
{
131
132 2530
        CHECK_OBJ_NOTNULL(w, WAITER_MAGIC);
133 2530
        CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
134 2530
        assert(wp->fd > 0);                     // stdin never comes here
135 2530
        AN(wp->func);
136 2530
        AN(wp->tmo);
137 2530
        wp->idx = BINHEAP_NOIDX;
138 2530
        return (w->impl->enter(w->priv, wp));
139
}
140
141
/**********************************************************************/
142
143
const char *
144 10
Waiter_GetName(void)
145
{
146
147 10
        if (waiter != NULL)
148 10
                return (waiter->name);
149
        else
150 0
                return ("(No Waiter?)");
151
}
152
153
struct waiter *
154 2442
Waiter_New(void)
155
{
156
        struct waiter *w;
157
158 2442
        AN(waiter);
159 2442
        AN(waiter->name);
160 2442
        AN(waiter->init);
161 2442
        AN(waiter->enter);
162 2442
        AN(waiter->fini);
163
164 2442
        w = calloc(1, sizeof (struct waiter) + waiter->size);
165 2442
        AN(w);
166 2442
        INIT_OBJ(w, WAITER_MAGIC);
167 2442
        w->priv = (void*)(w + 1);
168 2442
        w->impl = waiter;
169 2442
        VTAILQ_INIT(&w->waithead);
170 2442
        w->heap = binheap_new(w, waited_cmp, waited_update);
171
172 2442
        waiter->init(w);
173
174 2442
        return (w);
175
}
176
177
void
178 4
Waiter_Destroy(struct waiter **wp)
179
{
180
        struct waiter *w;
181
182 4
        TAKE_OBJ_NOTNULL(w, wp, WAITER_MAGIC);
183
184 4
        AZ(binheap_root(w->heap));
185 4
        AN(w->impl->fini);
186 4
        w->impl->fini(w);
187 4
        FREE_OBJ(w);
188 4
}