varnish-cache/bin/varnishd/cache/cache_lck.c
0
/*-
1
 * Copyright (c) 2008-2011 Varnish Software AS
2
 * All rights reserved.
3
 *
4
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
5
 *
6
 * SPDX-License-Identifier: BSD-2-Clause
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
 * The geniuses who came up with pthreads did not think operations like
30
 * pthread_assert_mutex_held() were important enough to include them in
31
 * the API.
32
 *
33 22197
 * Build our own locks on top of pthread mutexes and hope that the next
34 22197
 * civilization is better at such crucial details than this one.
35 22197
 */
36 22197
37 22197
#include "config.h"
38 22197
39 22197
#include "cache_varnishd.h"
40 22197
41 22197
#include <stdlib.h>
42 22197
#include <stdio.h>
43 22197
44 22197
#include "vtim.h"
45 22197
46 22197
#include "VSC_lck.h"
47 22197
48 22197
struct ilck {
49 22197
        unsigned                magic;
50 22197
#define ILCK_MAGIC              0x7b86c8a5
51 22197
        int                     held;
52 22197
        pthread_mutex_t         mtx;
53 22197
        pthread_t               owner;
54
        const char              *w;
55
        struct VSC_lck          *stat;
56
};
57
58
/*--------------------------------------------------------------------*/
59
60
static void
61 5022
Lck_Witness_Lock(const struct ilck *il, const char *p, int l,
62
    const char *attempt)
63
{
64
        char *q, t[10]; //lint -e429
65
        int emit;
66
67 5022
        AN(p);
68 5022
        q = pthread_getspecific(witness_key);
69 5022
        if (q == NULL) {
70 621
                q = calloc(1, 1024);
71 621
                AN(q);
72 621
                PTOK(pthread_setspecific(witness_key, q));
73 621
        }
74 5022
        emit = *q != '\0';
75 5022
        strcat(q, " ");
76 5022
        strcat(q, il->w);
77 5022
        strcat(q, attempt);
78 5022
        strcat(q, ",");
79 5022
        strcat(q, p);
80 5022
        strcat(q, ",");
81 5022
        bprintf(t, "%d", l);
82 5022
        strcat(q, t);
83 5022
        if (emit)
84 450
                VSL(SLT_Witness, NO_VXID, "%s", q);
85 5022
}
86
87
static void
88 5118
Lck_Witness_Unlock(const struct ilck *il)
89
{
90
        char *q, *r;
91
92 5118
        q = pthread_getspecific(witness_key);
93 5118
        if (q == NULL)
94 321
                return;
95 4797
        r = strrchr(q, ' ');
96 4797
        if (r == NULL)
97 0
                r = q;
98
        else
99 4797
                *r++ = '\0';
100 4797
        if (memcmp(r, il->w, strlen(il->w)))
101 0
                VSL(SLT_Witness, NO_VXID, "Unlock %s @ %s <%s>", il->w, r, q);
102
        else
103 4797
                *r = '\0';
104 5118
}
105
106
/*--------------------------------------------------------------------*/
107
108
void v_matchproto_()
109 7354718
Lck__Lock(struct lock *lck, const char *p, int l)
110
{
111
        struct ilck *ilck;
112 7354718
        int r = EINVAL;
113
114 7354718
        AN(lck);
115 7354718
        CAST_OBJ_NOTNULL(ilck, lck->priv, ILCK_MAGIC);
116 7354718
        if (DO_DEBUG(DBG_WITNESS))
117 4890
                Lck_Witness_Lock(ilck, p, l, "");
118 7354718
        if (DO_DEBUG(DBG_LCK)) {
119 0
                r = pthread_mutex_trylock(&ilck->mtx);
120 0
                assert(r == 0 || r == EBUSY);
121 0
        }
122 7354718
        if (r)
123 7354593
                PTOK(pthread_mutex_lock(&ilck->mtx));
124 7354718
        AZ(ilck->held);
125 7354540
        if (r == EBUSY)
126 0
                ilck->stat->dbg_busy++;
127 7354540
        ilck->stat->locks++;
128 7354540
        ilck->owner = pthread_self();
129 7354540
        ilck->held = 1;
130 7354540
}
131
132
void v_matchproto_()
133 8052194
Lck__Unlock(struct lock *lck, const char *p, int l)
134
{
135
        struct ilck *ilck;
136
137 8052194
        (void)p;
138 8052194
        (void)l;
139
140 8052194
        AN(lck);
141 8052194
        CAST_OBJ_NOTNULL(ilck, lck->priv, ILCK_MAGIC);
142 8052194
        assert(pthread_equal(ilck->owner, pthread_self()));
143 8052194
        AN(ilck->held);
144 8052194
        ilck->held = 0;
145
        /*
146
         * #ifdef POSIX_STUPIDITY:
147
         * The pthread_t type has no defined assignment or comparison
148
         * operators, this is why pthread_equal() is necessary.
149
         * Unfortunately POSIX forgot to define a NULL value for pthread_t
150
         * so you can never unset a pthread_t variable.
151
         * We hack it and fill it with zero bits, hoping for sane
152
         * implementations of pthread.
153
         * #endif
154
         */
155
#ifdef PTHREAD_NULL
156
        ilck->owner = PTHREAD_NULL;
157
#else
158 8052194
        memset(&ilck->owner, 0, sizeof ilck->owner);
159
#endif
160 8052194
        PTOK(pthread_mutex_unlock(&ilck->mtx));
161 8052194
        if (DO_DEBUG(DBG_WITNESS))
162 5116
                Lck_Witness_Unlock(ilck);
163 8052194
}
164
165
int v_matchproto_()
166 1171748
Lck__Trylock(struct lock *lck, const char *p, int l)
167
{
168
        struct ilck *ilck;
169
        int r;
170
171 1171748
        AN(lck);
172 1171748
        CAST_OBJ_NOTNULL(ilck, lck->priv, ILCK_MAGIC);
173 1171748
        if (DO_DEBUG(DBG_WITNESS))
174 130
                Lck_Witness_Lock(ilck, p, l, "?");
175 1171748
        r = pthread_mutex_trylock(&ilck->mtx);
176 1171748
        assert(r == 0 || r == EBUSY);
177 1171748
        if (r == 0) {
178 1171739
                AZ(ilck->held);
179 1171739
                ilck->held = 1;
180 1171739
                ilck->stat->locks++;
181 1171739
                ilck->owner = pthread_self();
182 1171748
        } else if (DO_DEBUG(DBG_LCK))
183 0
                ilck->stat->dbg_try_fail++;
184 1171748
        return (r);
185
}
186
187
int
188 1455512
Lck__Held(const struct lock *lck)
189
{
190
        struct ilck *ilck;
191
192 1455512
        AN(lck);
193 1455512
        CAST_OBJ_NOTNULL(ilck, lck->priv, ILCK_MAGIC);
194 1455512
        return (ilck->held);
195
}
196
197
int
198 1455523
Lck__Owned(const struct lock *lck)
199
{
200
        struct ilck *ilck;
201
202 1455523
        AN(lck);
203 1455523
        CAST_OBJ_NOTNULL(ilck, lck->priv, ILCK_MAGIC);
204 1455523
        AN(ilck->held);
205 1455523
        return (pthread_equal(ilck->owner, pthread_self()));
206
}
207
208
int v_matchproto_()
209 794432
Lck_CondWait(pthread_cond_t *cond, struct lock *lck)
210
{
211 794432
       return (Lck_CondWaitUntil(cond, lck, 0));
212
}
213
214
int v_matchproto_()
215 178397
Lck_CondWaitTimeout(pthread_cond_t *cond, struct lock *lck, vtim_dur timeout)
216
{
217 178397
        assert(timeout >= 0);
218 178397
        assert(timeout < 3600);
219
220 178397
        if (timeout == 0)
221 0
                return (Lck_CondWaitUntil(cond, lck, 0));
222
        else
223 178397
                return (Lck_CondWaitUntil(cond, lck, VTIM_real() + timeout));
224 178397
}
225
226
int v_matchproto_()
227 1187376
Lck_CondWaitUntil(pthread_cond_t *cond, struct lock *lck, vtim_real when)
228
{
229
        struct ilck *ilck;
230
        struct timespec ts;
231
232 1187376
        AN(lck);
233 1187376
        CAST_OBJ_NOTNULL(ilck, lck->priv, ILCK_MAGIC);
234 1187376
        AN(ilck->held);
235 1187376
        assert(pthread_equal(ilck->owner, pthread_self()));
236 1187376
        ilck->held = 0;
237 1187376
        if (when == 0) {
238 934342
                errno = pthread_cond_wait(cond, &ilck->mtx);
239 934342
                AZ(errno);
240 934342
        } else {
241 253034
                assert(when > 1e9);
242 253034
                ts = VTIM_timespec(when);
243 253034
                assert(ts.tv_nsec >= 0 && ts.tv_nsec <= 999999999);
244 253034
                errno = pthread_cond_timedwait(cond, &ilck->mtx, &ts);
245
#if defined (__APPLE__)
246
                /*
247
                 * I hate woo-doo programming in all it's forms and all it's
248
                 * manifestations, but for reasons I utterly fail to isolate,
249
                 * OSX sometimes throws an EINVAL.
250
                 *
251
                 * I have tried very hard to determine if any of the three
252
                 * arguments are in fact invalid, and found nothing which
253
                 * even hints that it might be the case.
254
                 *
255
                 * So far I have yet to see a failure if the exact same
256
                 * call is repeated after a very short sleep.
257
                 *
258
                 * Calling pthread_yield_np() instead of sleaping /mostly/
259
                 * works as well, but still fails sometimes.
260
                 *
261
                 * Env:
262
                 *      Darwin Kernel Version 20.5.0:
263
                 *      Sat May  8 05:10:31 PDT 2021;
264
                 *      root:xnu-7195.121.3~9/RELEASE_ARM64_T8101 arm64
265
                 *
266
                 * 20220329 /phk
267
                 */
268
                if (errno == EINVAL) {
269
                        usleep(100);
270
                        errno = pthread_cond_timedwait(cond, &ilck->mtx, &ts);
271
                }
272
#endif
273
                /* We should never observe EINTR, but we have in the past. For
274
                 * example when sanitizers are enabled.
275
                 */
276 253034
                assert(errno == 0 ||
277
                    errno == ETIMEDOUT ||
278
                    errno == EINTR);
279
        }
280 1187376
        AZ(ilck->held);
281 1187376
        ilck->held = 1;
282 1187376
        ilck->owner = pthread_self();
283 1187376
        return (errno);
284
}
285
286
void
287 825666
Lck__New(struct lock *lck, struct VSC_lck *st, const char *w)
288
{
289
        struct ilck *ilck;
290
291 825666
        AN(st);
292 825666
        AN(w);
293 825666
        AN(lck);
294 825666
        AZ(lck->priv);
295 825666
        ALLOC_OBJ(ilck, ILCK_MAGIC);
296 825666
        AN(ilck);
297 825666
        ilck->w = w;
298 825666
        ilck->stat = st;
299 825666
        ilck->stat->creat++;
300 825666
        PTOK(pthread_mutex_init(&ilck->mtx, &mtxattr_errorcheck));
301 825666
        lck->priv = ilck;
302 825666
}
303
304
void
305 128374
Lck_Delete(struct lock *lck)
306
{
307
        struct ilck *ilck;
308
309 128374
        AN(lck);
310 128374
        TAKE_OBJ_NOTNULL(ilck, &lck->priv, ILCK_MAGIC);
311 128374
        ilck->stat->destroy++;
312 128374
        PTOK(pthread_mutex_destroy(&ilck->mtx));
313 128374
        FREE_OBJ(ilck);
314 128374
}
315
316
struct VSC_lck *
317 489156
Lck_CreateClass(struct vsc_seg **sg, const char *name)
318
{
319 489156
        return (VSC_lck_New(NULL, sg, name));
320
}
321
322
void
323 0
Lck_DestroyClass(struct vsc_seg **sg)
324
{
325 0
        VSC_lck_Destroy(sg);
326 0
}
327
328
#define LOCK(nam) struct VSC_lck *lck_##nam;
329
#include "tbl/locks.h"
330
331
void
332 22197
LCK_Init(void)
333
{
334
335
#define LOCK(nam)       lck_##nam = Lck_CreateClass(NULL, #nam);
336
#include "tbl/locks.h"
337 22197
}