varnish-cache/bin/varnishd/common/common_vsc.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
31
#include "config.h"
32
33
#include <stdarg.h>
34
#include <stdio.h>
35
#include <string.h>
36
#include <stdlib.h>
37
38
#include "vdef.h"
39
#include "vrt.h"
40
41
#include "miniobj.h"
42
#include "vas.h"
43
#include "vmb.h"
44
#include "vsc_priv.h"
45
#include "vqueue.h"
46
47
#include "heritage.h"
48
#include "vsmw.h"
49
50
/*--------------------------------------------------------------------*/
51
52
struct vsc_seg {
53
        unsigned                magic;
54
#define VSC_SEG_MAGIC           0x9b355991
55
56
        struct vsmw             *vsm;           // keep master/child sep.
57
        const char              *nm;
58
        VTAILQ_ENTRY(vsc_seg)   list;
59
        void                    *seg;
60
61
        /* VSC segments */
62
        struct vsc_head         *head;
63
        void                    *ptr;
64
        struct vsc_seg          *doc;
65
66
        /* DOC segments */
67
        const unsigned char     *jp;
68
        int                     refs;
69
};
70
71
static VTAILQ_HEAD(,vsc_seg)    vsc_seglist =
72
    VTAILQ_HEAD_INITIALIZER(vsc_seglist);
73
74
static void v_matchproto_(vsm_lock_f)
75 75440
vsc_dummy_lock(void)
76
{
77 75440
}
78
79
vsm_lock_f *vsc_lock = vsc_dummy_lock;
80
vsm_lock_f *vsc_unlock = vsc_dummy_lock;
81
82
static const size_t vsc_overhead = PRNDUP(sizeof(struct vsc_head));
83
84
static struct vsc_seg *
85 1515832
vrt_vsc_mksegv(struct vsmw_cluster *vc, const char *category,
86
    size_t payload, const char *prefix, const char *fmt, va_list va)
87
{
88
        struct vsc_seg *vsg;
89
90 1515832
        ALLOC_OBJ(vsg, VSC_SEG_MAGIC);
91 1515832
        AN(vsg);
92 3031664
        vsg->seg = VSMW_Allocv(heritage.proc_vsmw, vc, category,
93 1515832
            VRT_VSC_Overhead(payload), prefix, fmt, va);
94 1515832
        AN(vsg->seg);
95 1515832
        vsg->vsm = heritage.proc_vsmw;
96 1515832
        vsg->head = (void*)vsg->seg;
97 1515832
        vsg->head->body_offset = vsc_overhead;
98 1515832
        vsg->ptr = (char*)vsg->seg + vsc_overhead;
99 1515832
        return (vsg);
100
}
101
102
static struct vsc_seg *
103 254895
vrt_vsc_mksegf(const char *category, size_t payload, const char *fmt, ...)
104
{
105
        va_list ap;
106
        struct vsc_seg *vsg;
107
108 254895
        va_start(ap, fmt);
109 254895
        vsg = vrt_vsc_mksegv(NULL, category, payload, NULL, fmt, ap);
110 254895
        va_end(ap);
111 254895
        return (vsg);
112
}
113
114
size_t
115 1563232
VRT_VSC_Overhead(size_t payload)
116
{
117 1563232
        return (vsc_overhead + PRNDUP(payload));
118
}
119
120
void
121 54578
VRT_VSC_Hide(const struct vsc_seg *vsg)
122
{
123 54578
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
124 54578
        assert(vsg->head->ready > 0);
125 54578
        vsg->head->ready = 2;
126 54578
}
127
128
void
129 51600
VRT_VSC_Reveal(const struct vsc_seg *vsg)
130
{
131 51600
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
132 51600
        assert(vsg->head->ready > 0);
133 51600
        vsg->head->ready = 1;
134 51600
}
135
136
void *
137 1260937
VRT_VSC_Alloc(struct vsmw_cluster *vc, struct vsc_seg **sg,
138
    const char *nm, size_t sd,
139
    const unsigned char *jp, size_t sj, const char *fmt, va_list va)
140
{
141
        struct vsc_seg *vsg, *dvsg;
142
        uintptr_t jjp;
143
144 1260937
        vsc_lock();
145
146 1260937
        jjp = (uintptr_t)jp;
147
148 2570275
        VTAILQ_FOREACH(dvsg, &vsc_seglist, list) {
149 2495879
                if (dvsg->vsm != heritage.proc_vsmw)
150 434350
                        continue;
151 2061529
                if (dvsg->jp == NULL || dvsg->jp == jp)
152 1186541
                        break;
153 874988
        }
154 1260937
        if (dvsg == NULL || dvsg->jp == NULL) {
155
                /* Create a new documentation segment */
156 509790
                dvsg = vrt_vsc_mksegf(VSC_DOC_CLASS, sj,
157 254895
                    "%jx", (uintmax_t)jjp);
158 254895
                AN(dvsg);
159 254895
                dvsg->jp = jp;
160 254895
                dvsg->head->doc_id = jjp;
161 254895
                memcpy(dvsg->ptr, jp, sj);
162 254895
                VWMB();
163 254895
                dvsg->head->ready = 1;
164 254895
                VTAILQ_INSERT_HEAD(&vsc_seglist, dvsg, list);
165 254895
        }
166 1260937
        AN(dvsg);
167 1260937
        dvsg->refs++;
168
169 1260937
        AN(heritage.proc_vsmw);
170
171 1260937
        vsg = vrt_vsc_mksegv(vc, VSC_CLASS, sd, nm, fmt, va);
172 1260937
        AN(vsg);
173 1260937
        vsg->nm = nm;
174 1260937
        vsg->doc = dvsg;
175 1260937
        vsg->head->doc_id = jjp;
176 1260937
        VTAILQ_INSERT_TAIL(&vsc_seglist, vsg, list);
177 1260937
        VWMB();
178 1260937
        vsg->head->ready = 1;
179 1260937
        vsc_unlock();
180 1260937
        if (sg != NULL)
181 233660
                *sg = vsg;
182 1260937
        return (vsg->ptr);
183
}
184
185
void
186 3421
VRT_VSC_Destroy(const char *nm, struct vsc_seg *vsg)
187
{
188
        struct vsc_seg *dvsg;
189
190 3421
        vsc_lock();
191
192 3421
        AN(heritage.proc_vsmw);
193 3421
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
194 3421
        CAST_OBJ_NOTNULL(dvsg, vsg->doc, VSC_SEG_MAGIC);
195 3421
        AZ(vsg->jp);
196 3421
        assert(vsg->vsm == heritage.proc_vsmw);
197 3421
        assert(vsg->nm == nm);
198
199 3421
        VSMW_Free(heritage.proc_vsmw, &vsg->seg);
200 3421
        VTAILQ_REMOVE(&vsc_seglist, vsg, list);
201 3421
        FREE_OBJ(vsg);
202 3421
        if (--dvsg->refs == 0) {
203 80
                VSMW_Free(heritage.proc_vsmw, &dvsg->seg);
204 80
                VTAILQ_REMOVE(&vsc_seglist, dvsg, list);
205 80
                FREE_OBJ(dvsg);
206 80
        }
207 3421
        vsc_unlock();
208 3421
}