source: bin/varnishd/cache/cache_shmlog.c @ 58dc8e

Revision 58dc8e, 8.3 KB checked in by Poul-Henning Kamp <phk@…>, 2 years ago (diff)

Introduce a consistent wrk local variable with in all cnt_*()
steps.

A couple of minor polishishes.

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2011 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 <stdio.h>
33#include <stdlib.h>
34
35#include "cache.h"
36#include "common/heritage.h"
37
38#include "cache_backend.h"      // For w->vbc
39
40#include "vmb.h"
41#include "vtim.h"
42
43/* These cannot be struct lock, which depends on vsm/vsl working */
44static pthread_mutex_t vsl_mtx;
45static pthread_mutex_t vsm_mtx;
46
47static uint32_t                 *vsl_start;
48static const uint32_t           *vsl_end;
49static uint32_t                 *vsl_ptr;
50
51struct VSC_C_main       *VSC_C_main;
52
53static inline uint32_t
54vsl_w0(uint32_t type, uint32_t length)
55{
56
57        assert(length < 0x10000);
58        return (((type & 0xff) << 24) | length);
59}
60
61/*--------------------------------------------------------------------*/
62
63static inline void
64vsl_hdr(enum VSL_tag_e tag, uint32_t *p, unsigned len, unsigned id)
65{
66
67        assert(((uintptr_t)p & 0x3) == 0);
68
69        p[1] = id;
70        VMB();
71        p[0] = vsl_w0(tag, len);
72}
73
74/*--------------------------------------------------------------------*/
75
76static void
77vsl_wrap(void)
78{
79
80        assert(vsl_ptr >= vsl_start + 1);
81        assert(vsl_ptr < vsl_end);
82        vsl_start[1] = VSL_ENDMARKER;
83        do
84                vsl_start[0]++;
85        while (vsl_start[0] == 0);
86        VWMB();
87        if (vsl_ptr != vsl_start + 1) {
88                *vsl_ptr = VSL_WRAPMARKER;
89                vsl_ptr = vsl_start + 1;
90        }
91        VSC_C_main->shm_cycles++;
92}
93
94/*--------------------------------------------------------------------
95 * Reserve bytes for a record, wrap if necessary
96 */
97
98static uint32_t *
99vsl_get(unsigned len, unsigned records, unsigned flushes)
100{
101        uint32_t *p;
102
103        if (pthread_mutex_trylock(&vsl_mtx)) {
104                AZ(pthread_mutex_lock(&vsl_mtx));
105                VSC_C_main->shm_cont++;
106        }
107        assert(vsl_ptr < vsl_end);
108        assert(((uintptr_t)vsl_ptr & 0x3) == 0);
109
110        VSC_C_main->shm_writes++;
111        VSC_C_main->shm_flushes += flushes;
112        VSC_C_main->shm_records += records;
113
114        /* Wrap if necessary */
115        if (VSL_END(vsl_ptr, len) >= vsl_end)
116                vsl_wrap();
117
118        p = vsl_ptr;
119        vsl_ptr = VSL_END(vsl_ptr, len);
120
121        *vsl_ptr = VSL_ENDMARKER;
122
123        assert(vsl_ptr < vsl_end);
124        assert(((uintptr_t)vsl_ptr & 0x3) == 0);
125        AZ(pthread_mutex_unlock(&vsl_mtx));
126
127        return (p);
128}
129
130/*--------------------------------------------------------------------
131 * This variant copies a byte-range directly to the log, without
132 * taking the detour over sprintf()
133 */
134
135static void
136VSLR(enum VSL_tag_e tag, int id, const char *b, unsigned len)
137{
138        uint32_t *p;
139        unsigned mlen;
140
141        mlen = cache_param->shm_reclen;
142
143        /* Truncate */
144        if (len > mlen)
145                len = mlen;
146
147        p = vsl_get(len, 1, 0);
148
149        memcpy(p + 2, b, len);
150        vsl_hdr(tag, p, len, id);
151}
152
153/*--------------------------------------------------------------------*/
154
155void
156VSL(enum VSL_tag_e tag, int id, const char *fmt, ...)
157{
158        va_list ap;
159        unsigned n, mlen = cache_param->shm_reclen;
160        char buf[mlen];
161
162        /*
163         * XXX: consider formatting into a stack buffer then move into
164         * XXX: shmlog with VSLR().
165         */
166        AN(fmt);
167        va_start(ap, fmt);
168
169        if (strchr(fmt, '%') == NULL) {
170                VSLR(tag, id, fmt, strlen(fmt));
171        } else {
172                n = vsnprintf(buf, mlen, fmt, ap);
173                if (n > mlen)
174                        n = mlen;
175                VSLR(tag, id, buf, n);
176        }
177        va_end(ap);
178}
179
180/*--------------------------------------------------------------------*/
181
182void
183WSL_Flush(struct worker *w, int overflow)
184{
185        uint32_t *p;
186        unsigned l;
187
188        l = pdiff(w->wlb, w->wlp);
189        if (l == 0)
190                return;
191
192        assert(l >= 8);
193
194        p = vsl_get(l - 8, w->wlr, overflow);
195
196        memcpy(p + 1, w->wlb + 1, l - 4);
197        VWMB();
198        p[0] = w->wlb[0];
199        w->wlp = w->wlb;
200        w->wlr = 0;
201}
202
203/*--------------------------------------------------------------------*/
204
205void
206WSLR(struct worker *w, enum VSL_tag_e tag, int id, txt t)
207{
208        unsigned l, mlen;
209
210        Tcheck(t);
211        mlen = cache_param->shm_reclen;
212
213        /* Truncate */
214        l = Tlen(t);
215        if (l > mlen) {
216                l = mlen;
217                t.e = t.b + l;
218        }
219
220        assert(w->wlp < w->wle);
221
222        /* Wrap if necessary */
223        if (VSL_END(w->wlp, l) >= w->wle)
224                WSL_Flush(w, 1);
225        assert (VSL_END(w->wlp, l) < w->wle);
226        memcpy(VSL_DATA(w->wlp), t.b, l);
227        vsl_hdr(tag, w->wlp, l, id);
228        w->wlp = VSL_END(w->wlp, l);
229        assert(w->wlp < w->wle);
230        w->wlr++;
231        if (cache_param->diag_bitmap & 0x10000)
232                WSL_Flush(w, 0);
233}
234
235/*--------------------------------------------------------------------*/
236
237static void
238wsl(struct worker *w, enum VSL_tag_e tag, int id, const char *fmt, va_list ap)
239{
240        char *p;
241        unsigned n, mlen;
242        txt t;
243
244        AN(fmt);
245        mlen = cache_param->shm_reclen;
246
247        if (strchr(fmt, '%') == NULL) {
248                t.b = TRUST_ME(fmt);
249                t.e = strchr(t.b, '\0');
250                WSLR(w, tag, id, t);
251        } else {
252                assert(w->wlp < w->wle);
253
254                /* Wrap if we cannot fit a full size record */
255                if (VSL_END(w->wlp, mlen) >= w->wle)
256                        WSL_Flush(w, 1);
257
258                p = VSL_DATA(w->wlp);
259                n = vsnprintf(p, mlen, fmt, ap);
260                if (n > mlen)
261                        n = mlen;       /* we truncate long fields */
262                vsl_hdr(tag, w->wlp, n, id);
263                w->wlp = VSL_END(w->wlp, n);
264                assert(w->wlp < w->wle);
265                w->wlr++;
266        }
267        if (cache_param->diag_bitmap & 0x10000)
268                WSL_Flush(w, 0);
269}
270
271/*--------------------------------------------------------------------*/
272
273void
274WSL(struct worker *w, enum VSL_tag_e tag, int id, const char *fmt, ...)
275{
276        va_list ap;
277
278        CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
279        AN(fmt);
280        va_start(ap, fmt);
281        wsl(w, tag, id, fmt, ap);
282        va_end(ap);
283}
284
285
286/*--------------------------------------------------------------------*/
287
288void
289WSLB(struct worker *w, enum VSL_tag_e tag, const char *fmt, ...)
290{
291        va_list ap;
292
293        CHECK_OBJ_NOTNULL(w, WORKER_MAGIC);
294        CHECK_OBJ_NOTNULL(w->vbc, VBC_MAGIC);
295        AN(fmt);
296        va_start(ap, fmt);
297        wsl(w, tag, w->vbc->vsl_id, fmt, ap);
298        va_end(ap);
299}
300
301/*--------------------------------------------------------------------*/
302
303static void *
304vsm_cleaner(void *priv)
305{
306        (void)priv;
307        THR_SetName("vsm_cleaner");
308        while (1) {
309                AZ(pthread_mutex_lock(&vsm_mtx));
310                VSM_common_cleaner(heritage.vsm, VSC_C_main);
311                AZ(pthread_mutex_unlock(&vsm_mtx));
312                VTIM_sleep(1.1);
313        }
314        NEEDLESS_RETURN(NULL);
315}
316
317/*--------------------------------------------------------------------*/
318
319void
320VSM_Init(void)
321{
322        uint32_t *vsl_log_start;
323        pthread_t tp;
324
325        AZ(pthread_mutex_init(&vsl_mtx, NULL));
326        AZ(pthread_mutex_init(&vsm_mtx, NULL));
327
328        vsl_log_start = VSM_Alloc(cache_param->vsl_space, VSL_CLASS, "", "");
329        AN(vsl_log_start);
330        vsl_log_start[1] = VSL_ENDMARKER;
331        VWMB();
332        do
333                *vsl_log_start = random() & 0xffff;
334        while (*vsl_log_start == 0);
335        VWMB();
336
337        vsl_start = vsl_log_start;
338        vsl_end = vsl_start +
339            cache_param->vsl_space / (unsigned)sizeof *vsl_end;
340        vsl_ptr = vsl_start + 1;
341
342        VSC_C_main = VSM_Alloc(sizeof *VSC_C_main,
343            VSC_CLASS, VSC_TYPE_MAIN, "");
344        AN(VSC_C_main);
345
346        vsl_wrap();
347        // VSM_head->starttime = (intmax_t)VTIM_real();
348        memset(VSC_C_main, 0, sizeof *VSC_C_main);
349        // VSM_head->child_pid = getpid();
350
351        AZ(pthread_create(&tp, NULL, vsm_cleaner, NULL));
352}
353
354/*--------------------------------------------------------------------*/
355
356void *
357VSM_Alloc(unsigned size, const char *class, const char *type,
358    const char *ident)
359{
360        volatile void *p;
361
362        AZ(pthread_mutex_lock(&vsm_mtx));
363        p = VSM_common_alloc(heritage.vsm, size, class, type, ident);
364        AZ(pthread_mutex_unlock(&vsm_mtx));
365        return (TRUST_ME(p));
366}
367
368void
369VSM_Free(void *ptr)
370{
371
372        AZ(pthread_mutex_lock(&vsm_mtx));
373        VSM_common_free(heritage.vsm, ptr);
374        AZ(pthread_mutex_unlock(&vsm_mtx));
375}
Note: See TracBrowser for help on using the repository browser.