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 16974
vsc_dummy_lock(void)
76
{
77 16974
}
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 341014
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 341014
        ALLOC_OBJ(vsg, VSC_SEG_MAGIC);
91 341014
        AN(vsg);
92 682028
        vsg->seg = VSMW_Allocv(heritage.proc_vsmw, vc, category,
93 341014
            VRT_VSC_Overhead(payload), prefix, fmt, va);
94 341014
        AN(vsg->seg);
95 341014
        vsg->vsm = heritage.proc_vsmw;
96 341014
        vsg->head = (void*)vsg->seg;
97 341014
        vsg->head->body_offset = vsc_overhead;
98 341014
        vsg->ptr = (char*)vsg->seg + vsc_overhead;
99 341014
        return (vsg);
100
}
101
102
static struct vsc_seg *
103 57344
vrt_vsc_mksegf(const char *category, size_t payload, const char *fmt, ...)
104
{
105
        va_list ap;
106
        struct vsc_seg *vsg;
107
108 57344
        va_start(ap, fmt);
109 57344
        vsg = vrt_vsc_mksegv(NULL, category, payload, NULL, fmt, ap);
110 57344
        va_end(ap);
111 57344
        return (vsg);
112
}
113
114
size_t
115 351678
VRT_VSC_Overhead(size_t payload)
116
{
117 351678
        return (vsc_overhead + PRNDUP(payload));
118
}
119
120
void
121 12275
VRT_VSC_Hide(const struct vsc_seg *vsg)
122
{
123 12275
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
124 12275
        assert(vsg->head->ready > 0);
125 12275
        vsg->head->ready = 2;
126 12275
}
127
128
void
129 11610
VRT_VSC_Reveal(const struct vsc_seg *vsg)
130
{
131 11610
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
132 11610
        assert(vsg->head->ready > 0);
133 11610
        vsg->head->ready = 1;
134 11610
}
135
136
void *
137 283670
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 283670
        vsc_lock();
145
146 283670
        jjp = (uintptr_t)jp;
147
148 578373
        VTAILQ_FOREACH(dvsg, &vsc_seglist, list) {
149 561635
                if (dvsg->vsm != heritage.proc_vsmw)
150 97714
                        continue;
151 463921
                if (dvsg->jp == NULL || dvsg->jp == jp)
152 266932
                        break;
153 196989
        }
154 283670
        if (dvsg == NULL || dvsg->jp == NULL) {
155
                /* Create a new documentation segment */
156 114688
                dvsg = vrt_vsc_mksegf(VSC_DOC_CLASS, sj,
157 57344
                    "%jx", (uintmax_t)jjp);
158 57344
                AN(dvsg);
159 57344
                dvsg->jp = jp;
160 57344
                dvsg->head->doc_id = jjp;
161 57344
                memcpy(dvsg->ptr, jp, sj);
162 57344
                VWMB();
163 57344
                dvsg->head->ready = 1;
164 57344
                VTAILQ_INSERT_HEAD(&vsc_seglist, dvsg, list);
165 57344
        }
166 283670
        AN(dvsg);
167 283670
        dvsg->refs++;
168
169 283670
        AN(heritage.proc_vsmw);
170
171 283670
        vsg = vrt_vsc_mksegv(vc, VSC_CLASS, sd, nm, fmt, va);
172 283670
        AN(vsg);
173 283670
        vsg->nm = nm;
174 283670
        vsg->doc = dvsg;
175 283670
        vsg->head->doc_id = jjp;
176 283670
        VTAILQ_INSERT_TAIL(&vsc_seglist, vsg, list);
177 283670
        VWMB();
178 283670
        vsg->head->ready = 1;
179 283670
        vsc_unlock();
180 283670
        if (sg != NULL)
181 52568
                *sg = vsg;
182 283670
        return (vsg->ptr);
183
}
184
185
void
186 767
VRT_VSC_Destroy(const char *nm, struct vsc_seg *vsg)
187
{
188
        struct vsc_seg *dvsg;
189
190 767
        vsc_lock();
191
192 767
        AN(heritage.proc_vsmw);
193 767
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
194 767
        CAST_OBJ_NOTNULL(dvsg, vsg->doc, VSC_SEG_MAGIC);
195 767
        AZ(vsg->jp);
196 767
        assert(vsg->vsm == heritage.proc_vsmw);
197 767
        assert(vsg->nm == nm);
198
199 767
        VSMW_Free(heritage.proc_vsmw, &vsg->seg);
200 767
        VTAILQ_REMOVE(&vsc_seglist, vsg, list);
201 767
        FREE_OBJ(vsg);
202 767
        if (--dvsg->refs == 0) {
203 18
                VSMW_Free(heritage.proc_vsmw, &dvsg->seg);
204 18
                VTAILQ_REMOVE(&vsc_seglist, dvsg, list);
205 18
                FREE_OBJ(dvsg);
206 18
        }
207 767
        vsc_unlock();
208 767
}