varnish-cache/bin/varnishd/cache/cache_hash.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2015 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * This is the central hash-table code, it relies on a chosen hash
31
 * implementation only for the actual hashing, all the housekeeping
32
 * happens here.
33
 *
34
 * We have two kinds of structures, objecthead and object.  An objecthead
35
 * corresponds to a given (Host:, URL) tupple, and the objects hung from
36
 * the objecthead may represent various variations (ie: Vary: header,
37
 * different TTL etc) instances of that web-entity.
38
 *
39
 * Each objecthead has a mutex which locks both its own fields, the
40
 * list of objects and fields in the objects.
41
 *
42
 * The hash implementation must supply a reference count facility on
43
 * the objecthead, and return with a reference held after a lookup.
44
 *
45
 * Lookups in the hash implementation returns with a ref held and each
46
 * object hung from the objhead holds a ref as well.
47
 *
48
 * Objects have refcounts which are locked by the objecthead mutex.
49
 *
50
 * New objects are always marked busy, and they can go from busy to
51
 * not busy only once.
52
 */
53
54
#include "config.h"
55
56
#include <stdio.h>
57
#include <stdlib.h>
58
59
#include "cache_varnishd.h"
60
61
#include "cache/cache_objhead.h"
62
#include "cache/cache_transport.h"
63
64
#include "hash/hash_slinger.h"
65
66
#include "vsha256.h"
67
68
struct rush {
69
        unsigned                magic;
70
#define RUSH_MAGIC              0xa1af5f01
71
        VTAILQ_HEAD(,req)       reqs;
72
};
73
74
static const struct hash_slinger *hash;
75
static struct objhead *private_oh;
76
77
static void hsh_rush1(const struct worker *, struct objhead *,
78
    struct rush *, int);
79
static void hsh_rush2(struct worker *, struct rush *);
80
static int hsh_deref_objhead(struct worker *wrk, struct objhead **poh);
81
static int hsh_deref_objhead_unlock(struct worker *wrk, struct objhead **poh,
82
    int);
83
84
/*---------------------------------------------------------------------*/
85
86
#define VCF_RETURN(x) const struct vcf_return VCF_##x[1] = { \
87
        { .name = #x, } \
88
};
89
90
VCF_RETURNS()
91
#undef VCF_RETURN
92
93
/*---------------------------------------------------------------------*/
94
95
static struct objhead *
96 59233
hsh_newobjhead(void)
97
{
98
        struct objhead *oh;
99
100 59233
        ALLOC_OBJ(oh, OBJHEAD_MAGIC);
101 59233
        XXXAN(oh);
102 59233
        oh->refcnt = 1;
103 59233
        VTAILQ_INIT(&oh->objcs);
104 59233
        VTAILQ_INIT(&oh->waitinglist);
105 59233
        Lck_New(&oh->mtx, lck_objhdr);
106 59233
        return (oh);
107
}
108
109
/*---------------------------------------------------------------------*/
110
/* Precreate an objhead and object for later use */
111
static void
112 61641
hsh_prealloc(struct worker *wrk)
113
{
114
115 61641
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
116
117 61641
        if (wrk->wpriv->nobjcore == NULL)
118 42321
                wrk->wpriv->nobjcore = ObjNew(wrk);
119 61641
        CHECK_OBJ_NOTNULL(wrk->wpriv->nobjcore, OBJCORE_MAGIC);
120
121 61641
        if (wrk->wpriv->nobjhead == NULL) {
122 37038
                wrk->wpriv->nobjhead = hsh_newobjhead();
123 37038
                wrk->stats->n_objecthead++;
124 37038
        }
125 61641
        CHECK_OBJ_NOTNULL(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
126
127 61641
        if (hash->prep != NULL)
128 61490
                hash->prep(wrk);
129 61641
}
130
131
/*---------------------------------------------------------------------*/
132
133
struct objcore *
134 31575
HSH_Private(const struct worker *wrk)
135
{
136
        struct objcore *oc;
137
138 31575
        CHECK_OBJ_NOTNULL(private_oh, OBJHEAD_MAGIC);
139
140 31575
        oc = ObjNew(wrk);
141 31575
        AN(oc);
142 31575
        oc->refcnt = 1;
143 31575
        oc->objhead = private_oh;
144 31575
        oc->flags |= OC_F_PRIVATE;
145 31575
        Lck_Lock(&private_oh->mtx);
146 31575
        VTAILQ_INSERT_TAIL(&private_oh->objcs, oc, hsh_list);
147 31575
        private_oh->refcnt++;
148 31575
        Lck_Unlock(&private_oh->mtx);
149 31575
        return (oc);
150
}
151
152
/*---------------------------------------------------------------------*/
153
154
void
155 22571
HSH_Cleanup(const struct worker *wrk)
156
{
157
158 22571
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
159 22571
        CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
160 22571
        if (wrk->wpriv->nobjcore != NULL)
161 34
                ObjDestroy(wrk, &wrk->wpriv->nobjcore);
162
163 22571
        if (wrk->wpriv->nobjhead != NULL) {
164 34
                CHECK_OBJ(wrk->wpriv->nobjhead, OBJHEAD_MAGIC);
165 34
                Lck_Delete(&wrk->wpriv->nobjhead->mtx);
166 34
                FREE_OBJ(wrk->wpriv->nobjhead);
167 34
                wrk->stats->n_objecthead--;
168 34
        }
169 22571
        if (wrk->wpriv->nhashpriv != NULL) {
170
                /* XXX: If needed, add slinger method for this */
171 50
                free(wrk->wpriv->nhashpriv);
172 50
                wrk->wpriv->nhashpriv = NULL;
173 50
        }
174 22571
}
175
176
void
177 0
HSH_DeleteObjHead(const struct worker *wrk, struct objhead *oh)
178
{
179 0
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
180 0
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
181
182 0
        AZ(oh->refcnt);
183 0
        assert(VTAILQ_EMPTY(&oh->objcs));
184 0
        assert(VTAILQ_EMPTY(&oh->waitinglist));
185 0
        Lck_Delete(&oh->mtx);
186 0
        wrk->stats->n_objecthead--;
187 0
        FREE_OBJ(oh);
188 0
}
189
190
void
191 341735
HSH_AddString(struct req *req, void *ctx, const char *str)
192
{
193
194 341735
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
195 341735
        AN(ctx);
196 341735
        if (str != NULL) {
197 170934
                VSHA256_Update(ctx, str, strlen(str));
198 170934
                VSLbs(req->vsl, SLT_Hash, TOSTRAND(str));
199 170934
        } else
200 170801
                VSHA256_Update(ctx, &str, 1);
201 341735
}
202
203
/*---------------------------------------------------------------------
204
 * This is a debugging hack to enable testing of boundary conditions
205
 * in the hash algorithm.
206
 * We trap the first 9 different digests and translate them to different
207
 * digests with edge bit conditions
208
 */
209
210
static struct hsh_magiclist {
211
        unsigned char was[VSHA256_LEN];
212
        unsigned char now[VSHA256_LEN];
213
} hsh_magiclist[] = {
214
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
218
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
221
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 } },
222
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
223
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 } },
226
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
228
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
229
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 } },
230
        { .now = {      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
231
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 } },
234
        { .now = {      0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
238
        { .now = {      0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
240
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
241
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
242
        { .now = {      0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
243
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
244
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
245
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
246
        { .now = {      0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
247
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
248
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
249
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
250
};
251
252
#define HSH_NMAGIC (sizeof hsh_magiclist / sizeof hsh_magiclist[0])
253
254
static void
255 450
hsh_testmagic(void *result)
256
{
257
        size_t i, j;
258
        static size_t nused = 0;
259
260 2250
        for (i = 0; i < nused; i++)
261 2025
                if (!memcmp(hsh_magiclist[i].was, result, VSHA256_LEN))
262 225
                        break;
263 450
        if (i == nused && i < HSH_NMAGIC)
264 225
                memcpy(hsh_magiclist[nused++].was, result, VSHA256_LEN);
265 450
        if (i == nused)
266 0
                return;
267 450
        assert(i < HSH_NMAGIC);
268 450
        fprintf(stderr, "HASHMAGIC: <");
269 14850
        for (j = 0; j < VSHA256_LEN; j++)
270 14400
                fprintf(stderr, "%02x", ((unsigned char*)result)[j]);
271 450
        fprintf(stderr, "> -> <");
272 450
        memcpy(result, hsh_magiclist[i].now, VSHA256_LEN);
273 14850
        for (j = 0; j < VSHA256_LEN; j++)
274 14400
                fprintf(stderr, "%02x", ((unsigned char*)result)[j]);
275 450
        fprintf(stderr, ">\n");
276 450
}
277
278
/*---------------------------------------------------------------------
279
 * Insert an object which magically appears out of nowhere or, more likely,
280
 * comes off some persistent storage device.
281
 * Insert it with a reference held.
282
 */
283
284
void
285 425
HSH_Insert(struct worker *wrk, const void *digest, struct objcore *oc,
286
    struct ban *ban)
287
{
288
        struct objhead *oh;
289
        struct rush rush;
290
291 425
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
292 425
        CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
293 425
        AN(digest);
294 425
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
295 425
        AN(ban);
296 425
        AN(oc->flags & OC_F_BUSY);
297 425
        AZ(oc->flags & OC_F_PRIVATE);
298 425
        assert(oc->refcnt == 1);
299 425
        INIT_OBJ(&rush, RUSH_MAGIC);
300
301 425
        hsh_prealloc(wrk);
302
303 425
        AN(wrk->wpriv->nobjhead);
304 425
        oh = hash->lookup(wrk, digest, &wrk->wpriv->nobjhead);
305 425
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
306 425
        Lck_AssertHeld(&oh->mtx);
307 425
        assert(oh->refcnt > 0);
308
309
        /* Mark object busy and insert (precreated) objcore in
310
           objecthead. The new object inherits our objhead reference. */
311 425
        oc->objhead = oh;
312 425
        VTAILQ_INSERT_TAIL(&oh->objcs, oc, hsh_list);
313 425
        EXP_RefNewObjcore(oc);
314 425
        Lck_Unlock(&oh->mtx);
315
316 425
        BAN_RefBan(oc, ban);
317 425
        AN(oc->ban);
318
319
        /* Move the object first in the oh list, unbusy it and run the
320
           waitinglist if necessary */
321 425
        Lck_Lock(&oh->mtx);
322 425
        VTAILQ_REMOVE(&oh->objcs, oc, hsh_list);
323 425
        VTAILQ_INSERT_HEAD(&oh->objcs, oc, hsh_list);
324 425
        oc->flags &= ~OC_F_BUSY;
325 425
        if (!VTAILQ_EMPTY(&oh->waitinglist))
326 0
                hsh_rush1(wrk, oh, &rush, HSH_RUSH_POLICY);
327 425
        Lck_Unlock(&oh->mtx);
328 425
        hsh_rush2(wrk, &rush);
329
330 425
        EXP_Insert(wrk, oc);
331 425
}
332
333
/*---------------------------------------------------------------------
334
 */
335
336
static struct objcore *
337 35913
hsh_insert_busyobj(const struct worker *wrk, struct objhead *oh)
338
{
339
        struct objcore *oc;
340
341 35913
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
342 35913
        CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
343 35913
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
344 35913
        Lck_AssertHeld(&oh->mtx);
345
346 35913
        oc = wrk->wpriv->nobjcore;
347 35913
        wrk->wpriv->nobjcore = NULL;
348 35913
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
349
350 35913
        AN(oc->flags & OC_F_BUSY);
351 35913
        oc->refcnt = 1;         /* Owned by busyobj */
352 35913
        oc->objhead = oh;
353 35913
        VTAILQ_INSERT_TAIL(&oh->objcs, oc, hsh_list);
354 35913
        return (oc);
355
}
356
357
/*---------------------------------------------------------------------
358
 */
359
360
enum lookup_e
361 61217
HSH_Lookup(struct req *req, struct objcore **ocp, struct objcore **bocp)
362
{
363
        struct worker *wrk;
364
        struct objhead *oh;
365
        struct objcore *oc;
366
        struct objcore *exp_oc;
367
        const struct vcf_return *vr;
368
        vtim_real exp_t_origin;
369
        int busy_found;
370
        const uint8_t *vary;
371
        intmax_t boc_progress;
372 61217
        unsigned xid = 0;
373 61217
        float dttl = 0.0;
374
375 61217
        AN(ocp);
376 61217
        *ocp = NULL;
377 61217
        AN(bocp);
378 61217
        *bocp = NULL;
379
380 61217
        CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
381 61217
        wrk = req->wrk;
382 61217
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
383 61217
        CHECK_OBJ_NOTNULL(wrk->wpriv, WORKER_PRIV_MAGIC);
384 61217
        CHECK_OBJ_NOTNULL(req->http, HTTP_MAGIC);
385 61217
        CHECK_OBJ_ORNULL(req->vcf, VCF_MAGIC);
386 61217
        AN(hash);
387
388 61217
        hsh_prealloc(wrk);
389 61217
        if (DO_DEBUG(DBG_HASHEDGE))
390 450
                hsh_testmagic(req->digest);
391
392 61217
        if (req->hash_objhead != NULL) {
393
                /*
394
                 * This req came off the waiting list, and brings an
395
                 * oh refcnt with it.
396
                 */
397 1162
                CHECK_OBJ_NOTNULL(req->hash_objhead, OBJHEAD_MAGIC);
398 1162
                oh = req->hash_objhead;
399 1162
                Lck_Lock(&oh->mtx);
400 1162
                req->hash_objhead = NULL;
401 1162
        } else {
402 60055
                AN(wrk->wpriv->nobjhead);
403 60055
                oh = hash->lookup(wrk, req->digest, &wrk->wpriv->nobjhead);
404
        }
405
406 61217
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
407 61217
        Lck_AssertHeld(&oh->mtx);
408
409 61217
        if (req->hash_always_miss) {
410
                /* XXX: should we do predictive Vary in this case ? */
411
                /* Insert new objcore in objecthead and release mutex */
412 350
                *bocp = hsh_insert_busyobj(wrk, oh);
413
                /* NB: no deref of objhead, new object inherits reference */
414 350
                Lck_Unlock(&oh->mtx);
415 350
                return (HSH_MISS);
416
        }
417
418 60867
        assert(oh->refcnt > 0);
419 60867
        busy_found = 0;
420 60867
        exp_oc = NULL;
421 60867
        exp_t_origin = 0.0;
422 132815
        VTAILQ_FOREACH(oc, &oh->objcs, hsh_list) {
423
                /* Must be at least our own ref + the objcore we examine */
424 96843
                assert(oh->refcnt > 1);
425 96843
                CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
426 96843
                assert(oc->objhead == oh);
427 96843
                assert(oc->refcnt > 0);
428
429 96843
                if (oc->flags & OC_F_DYING)
430 0
                        continue;
431 96843
                if (oc->flags & OC_F_FAILED)
432 0
                        continue;
433
434 96843
                CHECK_OBJ_ORNULL(oc->boc, BOC_MAGIC);
435 96843
                if (oc->flags & OC_F_BUSY) {
436 1309
                        if (req->hash_ignore_busy)
437 25
                                continue;
438
439 1357
                        if (oc->boc && oc->boc->vary != NULL &&
440 73
                            !req->hash_ignore_vary &&
441 73
                            !VRY_Match(req, oc->boc->vary)) {
442 25
                                wrk->strangelove++;
443 25
                                continue;
444
                        }
445
446 1259
                        busy_found = 1;
447 1259
                        continue;
448
                }
449
450 95534
                if (oc->ttl <= 0.)
451 1150
                        continue;
452
453 94384
                if (BAN_CheckObject(wrk, oc, req)) {
454 800
                        oc->flags |= OC_F_DYING;
455 800
                        EXP_Remove(oc);
456 800
                        continue;
457
                }
458
459 93584
                if (!req->hash_ignore_vary && ObjHasAttr(wrk, oc, OA_VARY)) {
460 69175
                        vary = ObjGetAttr(wrk, oc, OA_VARY, NULL);
461 69175
                        AN(vary);
462 69175
                        if (!VRY_Match(req, vary)) {
463 65450
                                wrk->strangelove++;
464 65450
                                continue;
465
                        }
466 3725
                }
467
468 28134
                if (req->vcf != NULL) {
469 200
                        vr = req->vcf->func(req, &oc, &exp_oc, 0);
470 200
                        if (vr == VCF_CONTINUE)
471 100
                                continue;
472 100
                        if (vr == VCF_MISS) {
473 75
                                oc = NULL;
474 75
                                break;
475
                        }
476 25
                        if (vr == VCF_HIT)
477 25
                                break;
478 0
                        assert(vr == VCF_DEFAULT);
479 0
                }
480
481 27934
                if (EXP_Ttl(req, oc) > req->t_req) {
482 24795
                        assert(oh->refcnt > 1);
483 24795
                        assert(oc->objhead == oh);
484 24795
                        break;
485
                }
486
487 3139
                if (EXP_Ttl(NULL, oc) < req->t_req && /* ignore req.ttl */
488 3050
                    oc->t_origin > exp_t_origin) {
489
                        /* record the newest object */
490 3025
                        exp_oc = oc;
491 3025
                        exp_t_origin = oc->t_origin;
492 3025
                        assert(oh->refcnt > 1);
493 3025
                        assert(exp_oc->objhead == oh);
494 3025
                }
495 3139
        }
496
497 60867
        if (req->vcf != NULL)
498 150
                (void)req->vcf->func(req, &oc, &exp_oc, 1);
499
500 60867
        if (oc != NULL && oc->flags & OC_F_HFP) {
501 250
                xid = VXID(ObjGetXID(wrk, oc));
502 250
                dttl = EXP_Dttl(req, oc);
503 250
                AN(hsh_deref_objhead_unlock(wrk, &oh, HSH_RUSH_POLICY));
504 250
                wrk->stats->cache_hitpass++;
505 250
                VSLb(req->vsl, SLT_HitPass, "%u %.6f", xid, dttl);
506 250
                return (HSH_HITPASS);
507
        }
508
509 60617
        if (oc != NULL) {
510 24595
                *ocp = oc;
511 24595
                oc->refcnt++;
512 24595
                if (oc->flags & OC_F_HFM) {
513 775
                        xid = VXID(ObjGetXID(wrk, oc));
514 775
                        dttl = EXP_Dttl(req, oc);
515 775
                        *bocp = hsh_insert_busyobj(wrk, oh);
516 775
                        Lck_Unlock(&oh->mtx);
517 775
                        wrk->stats->cache_hitmiss++;
518 775
                        VSLb(req->vsl, SLT_HitMiss, "%u %.6f", xid, dttl);
519 775
                        return (HSH_HITMISS);
520
                }
521 23820
                oc->hits++;
522 23820
                boc_progress = oc->boc == NULL ? -1 : oc->boc->fetched_so_far;
523 23820
                AN(hsh_deref_objhead_unlock(wrk, &oh, HSH_RUSH_POLICY));
524 23820
                Req_LogHit(wrk, req, oc, boc_progress);
525 23820
                return (HSH_HIT);
526
        }
527
528 36022
        if (exp_oc != NULL && exp_oc->flags & OC_F_HFM) {
529
                /*
530
                 * expired HFM ("grace/keep HFM")
531
                 *
532
                 * XXX should HFM objects actually have grace/keep ?
533
                 * XXX also:  why isn't *ocp = exp_oc ?
534
                 */
535 100
                xid = VXID(ObjGetXID(wrk, exp_oc));
536 100
                dttl = EXP_Dttl(req, exp_oc);
537 100
                *bocp = hsh_insert_busyobj(wrk, oh);
538 100
                Lck_Unlock(&oh->mtx);
539 100
                wrk->stats->cache_hitmiss++;
540 100
                VSLb(req->vsl, SLT_HitMiss, "%u %.6f", xid, dttl);
541 100
                return (HSH_HITMISS);
542
        }
543
544 35922
        if (exp_oc != NULL && exp_oc->boc != NULL)
545 100
                boc_progress = exp_oc->boc->fetched_so_far;
546
        else
547 35822
                boc_progress = -1;
548
549 35922
        if (!busy_found) {
550 34688
                *bocp = hsh_insert_busyobj(wrk, oh);
551
552 34688
                if (exp_oc != NULL) {
553 2775
                        exp_oc->refcnt++;
554 2775
                        *ocp = exp_oc;
555 2775
                        if (EXP_Ttl_grace(req, exp_oc) >= req->t_req) {
556 2125
                                exp_oc->hits++;
557 2125
                                Lck_Unlock(&oh->mtx);
558 2125
                                Req_LogHit(wrk, req, exp_oc, boc_progress);
559 2125
                                return (HSH_GRACE);
560
                        }
561 650
                }
562 32563
                Lck_Unlock(&oh->mtx);
563 32563
                return (HSH_MISS);
564
        }
565
566 1234
        AN(busy_found);
567 1234
        if (exp_oc != NULL && EXP_Ttl_grace(req, exp_oc) >= req->t_req) {
568
                /* we do not wait on the busy object if in grace */
569 75
                exp_oc->refcnt++;
570 75
                *ocp = exp_oc;
571 75
                exp_oc->hits++;
572 75
                AN(hsh_deref_objhead_unlock(wrk, &oh, 0));
573 75
                Req_LogHit(wrk, req, exp_oc, boc_progress);
574 75
                return (HSH_GRACE);
575
        }
576
577
        /* There are one or more busy objects, wait for them */
578 1159
        VTAILQ_INSERT_TAIL(&oh->waitinglist, req, w_list);
579
580 1159
        AZ(req->hash_ignore_busy);
581
582
        /*
583
         * The objhead reference transfers to the sess, we get it
584
         * back when the sess comes off the waiting list and
585
         * calls us again
586
         */
587 1159
        req->hash_objhead = oh;
588 1159
        req->wrk = NULL;
589 1159
        req->waitinglist = 1;
590
591 1159
        if (DO_DEBUG(DBG_WAITINGLIST))
592 350
                VSLb(req->vsl, SLT_Debug, "on waiting list <%p>", oh);
593
594 1159
        Lck_Unlock(&oh->mtx);
595
596 1159
        wrk->stats->busy_sleep++;
597 1159
        return (HSH_BUSY);
598 61217
}
599
600
/*---------------------------------------------------------------------
601
 * Pick the req's we are going to rush from the waiting list
602
 */
603
604
static void
605 904
hsh_rush1(const struct worker *wrk, struct objhead *oh, struct rush *r, int max)
606
{
607
        int i;
608
        struct req *req;
609
610 904
        if (max == 0)
611 40
                return;
612 864
        if (max == HSH_RUSH_POLICY)
613 864
                max = cache_param->rush_exponent;
614 864
        assert(max > 0);
615
616 864
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
617 864
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
618 864
        CHECK_OBJ_NOTNULL(r, RUSH_MAGIC);
619 864
        VTAILQ_INIT(&r->reqs);
620 864
        Lck_AssertHeld(&oh->mtx);
621 2023
        for (i = 0; i < max; i++) {
622 1823
                req = VTAILQ_FIRST(&oh->waitinglist);
623 1823
                if (req == NULL)
624 664
                        break;
625 1159
                CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
626 1159
                wrk->stats->busy_wakeup++;
627 1159
                AZ(req->wrk);
628 1159
                VTAILQ_REMOVE(&oh->waitinglist, req, w_list);
629 1159
                VTAILQ_INSERT_TAIL(&r->reqs, req, w_list);
630 1159
                req->waitinglist = 0;
631 1159
        }
632 904
}
633
634
/*---------------------------------------------------------------------
635
 * Rush req's that came from waiting list.
636
 */
637
638
static void
639 252060
hsh_rush2(struct worker *wrk, struct rush *r)
640
{
641
        struct req *req;
642
643 252060
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
644 252060
        CHECK_OBJ_NOTNULL(r, RUSH_MAGIC);
645
646 253219
        while (!VTAILQ_EMPTY(&r->reqs)) {
647 1159
                req = VTAILQ_FIRST(&r->reqs);
648 1159
                CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
649 1159
                VTAILQ_REMOVE(&r->reqs, req, w_list);
650 1159
                DSL(DBG_WAITINGLIST, req->vsl->wid, "off waiting list");
651 1159
                if (req->transport->reembark != NULL) {
652
                        // For ESI includes
653 31
                        req->transport->reembark(wrk, req);
654 31
                } else {
655
                        /*
656
                         * We ignore the queue limits which apply to new
657
                         * requests because if we fail to reschedule there
658
                         * may be vmod_privs to cleanup and we need a proper
659
                         * workerthread for that.
660
                         */
661 1128
                        AZ(Pool_Task(req->sp->pool, req->task, TASK_QUEUE_RUSH));
662
                }
663
        }
664 252060
}
665
666
/*---------------------------------------------------------------------
667
 * Purge an entire objhead
668
 */
669
670
unsigned
671 300
HSH_Purge(struct worker *wrk, struct objhead *oh, vtim_real ttl_now,
672
    vtim_dur ttl, vtim_dur grace, vtim_dur keep)
673
{
674
        struct objcore *oc, *oc_nows[2], **ocp;
675 300
        unsigned i, j, n, n_max, total = 0;
676
        int is_purge;
677
678 300
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
679 300
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
680
681 300
        is_purge = (ttl == 0 && grace == 0 && keep == 0);
682 300
        n_max = WS_ReserveLumps(wrk->aws, sizeof *ocp);
683 300
        if (n_max < 2) {
684
                /* No space on the workspace. Give it a stack buffer of 2
685
                 * elements, which is the minimum for the algorithm
686
                 * below. */
687 0
                ocp = oc_nows;
688 0
                n_max = 2;
689 0
        } else
690 300
                ocp = WS_Reservation(wrk->aws);
691 300
        AN(ocp);
692
693
        /* Note: This algorithm uses OC references in the list as
694
         * bookmarks, in order to know how far into the list we were when
695
         * releasing the mutex partway through and want to resume
696
         * again. This relies on the list not being reordered while we are
697
         * not holding the mutex. The only place where that happens is in
698
         * HSH_Unbusy(), where an OC_F_BUSY OC is moved first in the
699
         * list. This does not cause problems because we skip OC_F_BUSY
700
         * OCs. */
701
702 300
        Lck_Lock(&oh->mtx);
703 300
        oc = VTAILQ_FIRST(&oh->objcs);
704 300
        n = 0;
705 325
        while (1) {
706 2650
                for (; n < n_max && oc != NULL; oc = VTAILQ_NEXT(oc, hsh_list))
707
                {
708 2325
                        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
709 2325
                        assert(oc->objhead == oh);
710 2325
                        if (oc->flags & OC_F_BUSY) {
711
                                /* We cannot purge busy objects here, because
712
                                 * their owners have special rights to them,
713
                                 * and may nuke them without concern for the
714
                                 * refcount, which by definition always must
715
                                 * be one, so they don't check. */
716 275
                                continue;
717
                        }
718 2050
                        if (oc->flags & OC_F_DYING)
719 0
                                continue;
720 2050
                        oc->refcnt++;
721 2050
                        ocp[n++] = oc;
722 2050
                }
723
724 325
                Lck_Unlock(&oh->mtx);
725
726 325
                if (n == 0) {
727
                        /* No eligible objcores found. We are finished. */
728 100
                        break;
729
                }
730
731 225
                j = n;
732 225
                if (oc != NULL) {
733
                        /* There are more objects on the objhead that we
734
                         * have not yet looked at, but no more space on
735
                         * the objcore reference list. Do not process the
736
                         * last one, it will be used as the bookmark into
737
                         * the objcore list for the next iteration of the
738
                         * outer loop. */
739 25
                        j--;
740 25
                        assert(j >= 1); /* True because n_max >= 2 */
741 25
                }
742 2275
                for (i = 0; i < j; i++) {
743 2050
                        CHECK_OBJ_NOTNULL(ocp[i], OBJCORE_MAGIC);
744 2050
                        if (is_purge)
745 2025
                                EXP_Remove(ocp[i]);
746
                        else
747 25
                                EXP_Rearm(ocp[i], ttl_now, ttl, grace, keep);
748 2050
                        (void)HSH_DerefObjCore(wrk, &ocp[i], 0);
749 2050
                        AZ(ocp[i]);
750 2050
                        total++;
751 2050
                }
752
753 225
                if (j == n) {
754
                        /* No bookmark set, that means we got to the end
755
                         * of the objcore list in the previous run and are
756
                         * finished. */
757 200
                        break;
758
                }
759
760 25
                Lck_Lock(&oh->mtx);
761
762
                /* Move the bookmark first and continue scanning the
763
                 * objcores */
764 25
                CHECK_OBJ_NOTNULL(ocp[j], OBJCORE_MAGIC);
765 25
                ocp[0] = ocp[j];
766 25
                n = 1;
767 25
                oc = VTAILQ_NEXT(ocp[0], hsh_list);
768 25
                CHECK_OBJ_ORNULL(oc, OBJCORE_MAGIC);
769
        }
770
771 300
        WS_Release(wrk->aws, 0);
772 300
        if (is_purge)
773 275
                Pool_PurgeStat(total);
774 300
        return (total);
775
}
776
777
/*---------------------------------------------------------------------
778
 * Fail an objcore
779
 */
780
781
void
782 1650
HSH_Fail(struct objcore *oc)
783
{
784
        struct objhead *oh;
785
786 1650
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
787 1650
        oh = oc->objhead;
788 1650
        CHECK_OBJ(oh, OBJHEAD_MAGIC);
789
790
        /*
791
         * We have to have either a busy bit, so that HSH_Lookup
792
         * will not consider this oc, or an object hung of the oc
793
         * so that it can consider it.
794
         */
795 1650
        assert((oc->flags & OC_F_BUSY) || (oc->stobj->stevedore != NULL));
796
797 1650
        Lck_Lock(&oh->mtx);
798 1650
        oc->flags |= OC_F_FAILED;
799 1650
        Lck_Unlock(&oh->mtx);
800 1650
}
801
802
/*---------------------------------------------------------------------
803
 * Mark a fetch we will not need as cancelled
804
 */
805
806
static void
807 8885
hsh_cancel(struct objcore *oc)
808
{
809
        struct objhead *oh;
810
811 8885
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
812 8885
        oh = oc->objhead;
813 8885
        CHECK_OBJ(oh, OBJHEAD_MAGIC);
814
815 8885
        Lck_Lock(&oh->mtx);
816 8885
        oc->flags |= OC_F_CANCEL;
817 8885
        Lck_Unlock(&oh->mtx);
818 8885
}
819
820
/*---------------------------------------------------------------------
821
 * Cancel a fetch when the client does not need it any more
822
 */
823
824
void
825 92075
HSH_Cancel(struct worker *wrk, struct objcore *oc, struct boc *boc)
826
{
827 92075
        struct boc *bocref = NULL;
828
829 92075
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
830
831 92075
        if ((oc->flags & (OC_F_PRIVATE | OC_F_HFM | OC_F_HFP)) == 0)
832 56726
                return;
833
834
        /*
835
         * NB: we use two distinct variables to only release the reference if
836
         * we had to acquire one. The caller-provided boc is optional.
837
         */
838 35349
        if (boc == NULL)
839 26543
                bocref = boc = HSH_RefBoc(oc);
840
841 35349
        CHECK_OBJ_ORNULL(boc, BOC_MAGIC);
842
843 35349
        if (oc->flags & OC_F_HFP)
844 499
                AN(oc->flags & OC_F_HFM);
845
846 35349
        if (boc != NULL) {
847 8885
                hsh_cancel(oc);
848 8885
                ObjWaitState(oc, BOS_FINISHED);
849 8885
        }
850
851 35349
        if (bocref != NULL)
852 80
                HSH_DerefBoc(wrk, oc);
853
854 35349
        ObjSlim(wrk, oc);
855 92075
}
856
857
/*---------------------------------------------------------------------
858
 * Unbusy an objcore when the object is completely fetched.
859
 */
860
861
void
862 52274
HSH_Unbusy(struct worker *wrk, struct objcore *oc)
863
{
864
        struct objhead *oh;
865
        struct rush rush;
866
867 52274
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
868 52274
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
869 52274
        CHECK_OBJ_NOTNULL(oc->boc, BOC_MAGIC);
870
871 52274
        oh = oc->objhead;
872 52274
        CHECK_OBJ(oh, OBJHEAD_MAGIC);
873 52274
        INIT_OBJ(&rush, RUSH_MAGIC);
874
875 52274
        AN(oc->stobj->stevedore);
876 52274
        AN(oc->flags & OC_F_BUSY);
877 52274
        assert(oh->refcnt > 0);
878 52274
        assert(oc->refcnt > 0);
879
880 52274
        if (!(oc->flags & OC_F_PRIVATE)) {
881 34125
                BAN_NewObjCore(oc);
882 34125
                AN(oc->ban);
883 34125
        }
884
885
        /* XXX: pretouch neighbors on oh->objcs to prevent page-on under mtx */
886 52274
        Lck_Lock(&oh->mtx);
887 52274
        assert(oh->refcnt > 0);
888 52274
        assert(oc->refcnt > 0);
889 52274
        if (!(oc->flags & OC_F_PRIVATE))
890 34125
                EXP_RefNewObjcore(oc); /* Takes a ref for expiry */
891
        /* XXX: strictly speaking, we should sort in Date: order. */
892 52274
        VTAILQ_REMOVE(&oh->objcs, oc, hsh_list);
893 52274
        VTAILQ_INSERT_HEAD(&oh->objcs, oc, hsh_list);
894 52274
        oc->flags &= ~OC_F_BUSY;
895 52274
        if (!VTAILQ_EMPTY(&oh->waitinglist)) {
896 675
                assert(oh->refcnt > 1);
897 675
                hsh_rush1(wrk, oh, &rush, HSH_RUSH_POLICY);
898 675
        }
899 52274
        Lck_Unlock(&oh->mtx);
900 52274
        EXP_Insert(wrk, oc); /* Does nothing unless EXP_RefNewObjcore was
901
                              * called */
902 52274
        hsh_rush2(wrk, &rush);
903 52274
}
904
905
/*====================================================================
906
 * HSH_Kill()
907
 *
908
 * It's dead Jim, kick it...
909
 */
910
911
void
912 5973
HSH_Kill(struct objcore *oc)
913
{
914
915 5973
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
916 5973
        CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC);
917
918 5973
        Lck_Lock(&oc->objhead->mtx);
919 5973
        oc->flags |= OC_F_DYING;
920 5973
        Lck_Unlock(&oc->objhead->mtx);
921 5973
        EXP_Remove(oc);
922 5973
}
923
924
/*====================================================================
925
 * HSH_Snipe()
926
 *
927
 * If objcore is idle, gain a ref and mark it dead.
928
 */
929
930
int
931 275
HSH_Snipe(const struct worker *wrk, struct objcore *oc)
932
{
933 275
        int retval = 0;
934
935 275
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
936 275
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
937 275
        CHECK_OBJ_NOTNULL(oc->objhead, OBJHEAD_MAGIC);
938
939 275
        if (oc->refcnt == 1 && !Lck_Trylock(&oc->objhead->mtx)) {
940 275
                if (oc->refcnt == 1 && !(oc->flags & OC_F_DYING)) {
941 275
                        oc->flags |= OC_F_DYING;
942 275
                        oc->refcnt++;
943 275
                        retval = 1;
944 275
                }
945 275
                Lck_Unlock(&oc->objhead->mtx);
946 275
        }
947 275
        if (retval)
948 275
                EXP_Remove(oc);
949 275
        return (retval);
950
}
951
952
953
/*---------------------------------------------------------------------
954
 * Gain a reference on an objcore
955
 */
956
957
void
958 57524
HSH_Ref(struct objcore *oc)
959
{
960
        struct objhead *oh;
961
962 57524
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
963 57524
        oh = oc->objhead;
964 57524
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
965 57524
        Lck_Lock(&oh->mtx);
966 57524
        assert(oc->refcnt > 0);
967 57524
        oc->refcnt++;
968 57524
        Lck_Unlock(&oh->mtx);
969 57524
}
970
971
/*---------------------------------------------------------------------
972
 * Gain a reference on the busyobj, if the objcore has one
973
 */
974
975
struct boc *
976 222095
HSH_RefBoc(const struct objcore *oc)
977
{
978
        struct objhead *oh;
979
        struct boc *boc;
980
981 222095
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
982 222095
        oh = oc->objhead;
983 222095
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
984 222095
        if (oc->boc == NULL)
985 127580
                return (NULL);
986 94515
        Lck_Lock(&oh->mtx);
987 94515
        assert(oc->refcnt > 0);
988 94515
        boc = oc->boc;
989 94515
        CHECK_OBJ_ORNULL(boc, BOC_MAGIC);
990 94515
        if (boc != NULL) {
991 94471
                assert(boc->refcount > 0);
992 94471
                if (boc->state < BOS_FINISHED)
993 93670
                        boc->refcount++;
994
                else
995 801
                        boc = NULL;
996 94471
        }
997 94515
        Lck_Unlock(&oh->mtx);
998 94515
        return (boc);
999 222095
}
1000
1001
void
1002 160868
HSH_DerefBoc(struct worker *wrk, struct objcore *oc)
1003
{
1004
        struct boc *boc;
1005
        unsigned r;
1006
1007 160868
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1008 160868
        CHECK_OBJ_NOTNULL(oc, OBJCORE_MAGIC);
1009 160868
        boc = oc->boc;
1010 160868
        CHECK_OBJ_NOTNULL(boc, BOC_MAGIC);
1011 160868
        Lck_Lock(&oc->objhead->mtx);
1012 160868
        assert(oc->refcnt > 0);
1013 160868
        assert(boc->refcount > 0);
1014 160868
        r = --boc->refcount;
1015 160868
        if (r == 0)
1016 67225
                oc->boc = NULL;
1017 160868
        Lck_Unlock(&oc->objhead->mtx);
1018 160868
        if (r == 0)
1019 67225
                ObjBocDone(wrk, oc, &boc);
1020 160868
}
1021
1022
/*--------------------------------------------------------------------
1023
 * Dereference objcore
1024
 *
1025
 * Returns zero if target was destroyed.
1026
 */
1027
1028
int
1029 164515
HSH_DerefObjCore(struct worker *wrk, struct objcore **ocp, int rushmax)
1030
{
1031
        struct objcore *oc;
1032
        struct objhead *oh;
1033
        struct rush rush;
1034
        int r;
1035
1036 164515
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1037 164515
        TAKE_OBJ_NOTNULL(oc, ocp, OBJCORE_MAGIC);
1038 164515
        assert(oc->refcnt > 0);
1039 164515
        INIT_OBJ(&rush, RUSH_MAGIC);
1040
1041 164515
        oh = oc->objhead;
1042 164515
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
1043
1044 164515
        Lck_Lock(&oh->mtx);
1045 164515
        assert(oh->refcnt > 0);
1046 164515
        r = --oc->refcnt;
1047 164515
        if (!r)
1048 42277
                VTAILQ_REMOVE(&oh->objcs, oc, hsh_list);
1049 164515
        if (!VTAILQ_EMPTY(&oh->waitinglist)) {
1050 85
                assert(oh->refcnt > 1);
1051 85
                hsh_rush1(wrk, oh, &rush, rushmax);
1052 85
        }
1053 164515
        Lck_Unlock(&oh->mtx);
1054 164515
        hsh_rush2(wrk, &rush);
1055 164515
        if (r != 0)
1056 122239
                return (r);
1057
1058 42276
        AZ(oc->exp_flags);
1059
1060 42276
        BAN_DestroyObj(oc);
1061 42276
        AZ(oc->ban);
1062
1063 42276
        if (oc->stobj->stevedore != NULL)
1064 40289
                ObjFreeObj(wrk, oc);
1065 42276
        ObjDestroy(wrk, &oc);
1066
1067
        /* Drop our ref on the objhead */
1068 42276
        assert(oh->refcnt > 0);
1069 42276
        (void)hsh_deref_objhead(wrk, &oh);
1070 42276
        return (0);
1071 164515
}
1072
1073
static int
1074 66422
hsh_deref_objhead_unlock(struct worker *wrk, struct objhead **poh, int max)
1075
{
1076
        struct objhead *oh;
1077
        struct rush rush;
1078
        int r;
1079
1080 66422
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1081 66422
        TAKE_OBJ_NOTNULL(oh, poh, OBJHEAD_MAGIC);
1082
1083 66422
        Lck_AssertHeld(&oh->mtx);
1084
1085 66422
        if (oh == private_oh) {
1086 31575
                assert(VTAILQ_EMPTY(&oh->waitinglist));
1087 31575
                assert(oh->refcnt > 1);
1088 31575
                oh->refcnt--;
1089 31575
                Lck_Unlock(&oh->mtx);
1090 31575
                return (1);
1091
        }
1092
1093 34847
        INIT_OBJ(&rush, RUSH_MAGIC);
1094 34847
        if (!VTAILQ_EMPTY(&oh->waitinglist)) {
1095 144
                assert(oh->refcnt > 1);
1096 144
                hsh_rush1(wrk, oh, &rush, max);
1097 144
        }
1098
1099 34847
        if (oh->refcnt == 1)
1100 4317
                assert(VTAILQ_EMPTY(&oh->waitinglist));
1101
1102 34847
        assert(oh->refcnt > 0);
1103 34847
        r = hash->deref(wrk, oh); /* Unlocks oh->mtx */
1104 34847
        hsh_rush2(wrk, &rush);
1105 34847
        return (r);
1106 66422
}
1107
1108
static int
1109 42276
hsh_deref_objhead(struct worker *wrk, struct objhead **poh)
1110
{
1111
        struct objhead *oh;
1112
1113 42276
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
1114 42276
        TAKE_OBJ_NOTNULL(oh, poh, OBJHEAD_MAGIC);
1115
1116 42276
        Lck_Lock(&oh->mtx);
1117 42276
        return (hsh_deref_objhead_unlock(wrk, &oh, 0));
1118
}
1119
1120
void
1121 22194
HSH_Init(const struct hash_slinger *slinger)
1122
{
1123
1124 22194
        assert(DIGEST_LEN == VSHA256_LEN);      /* avoid #include pollution */
1125 22194
        hash = slinger;
1126 22194
        if (hash->start != NULL)
1127 22194
                hash->start();
1128 22194
        private_oh = hsh_newobjhead();
1129 22194
        private_oh->refcnt = 1;
1130 22194
}