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 45850
vsc_dummy_lock(void)
76
{
77 45850
}
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 852011
vrt_vsc_mksegv(struct vsmw_cluster *vc, const char *category,
86
    size_t payload, const char *fmt, va_list va)
87
{
88
        struct vsc_seg *vsg;
89
90 852011
        ALLOC_OBJ(vsg, VSC_SEG_MAGIC);
91 852011
        AN(vsg);
92 1704022
        vsg->seg = VSMW_Allocv(heritage.proc_vsmw, vc, category,
93 852011
            VRT_VSC_Overhead(payload), fmt, va);
94 852011
        AN(vsg->seg);
95 852011
        vsg->vsm = heritage.proc_vsmw;
96 852011
        vsg->head = (void*)vsg->seg;
97 852011
        vsg->head->body_offset = vsc_overhead;
98 852011
        vsg->ptr = (char*)vsg->seg + vsc_overhead;
99 852011
        return (vsg);
100
}
101
102
static struct vsc_seg *
103 132360
vrt_vsc_mksegf(const char *category, size_t payload, const char *fmt, ...)
104
{
105
        va_list ap;
106
        struct vsc_seg *vsg;
107
108 132360
        va_start(ap, fmt);
109 132360
        vsg = vrt_vsc_mksegv(NULL, category, payload, fmt, ap);
110 132360
        va_end(ap);
111 132360
        return (vsg);
112
}
113
114
size_t
115 880527
VRT_VSC_Overhead(size_t payload)
116
{
117 880527
        return (vsc_overhead + PRNDUP(payload));
118
}
119
120
void
121 33243
VRT_VSC_Hide(const struct vsc_seg *vsg)
122
{
123 33243
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
124 33243
        assert(vsg->head->ready > 0);
125 33243
        vsg->head->ready = 2;
126 33243
}
127
128
void
129 31475
VRT_VSC_Reveal(const struct vsc_seg *vsg)
130
{
131 31475
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
132 31475
        assert(vsg->head->ready > 0);
133 31475
        vsg->head->ready = 1;
134 31475
}
135
136
void *
137 719651
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
        char buf[1024];
143
        uintptr_t jjp;
144
145 719651
        vsc_lock();
146
147 719651
        jjp = (uintptr_t)jp;
148
149 1246277
        VTAILQ_FOREACH(dvsg, &vsc_seglist, list) {
150 1201155
                if (dvsg->vsm != heritage.proc_vsmw)
151 218870
                        continue;
152 982285
                if (dvsg->jp == NULL || dvsg->jp == jp)
153 674529
                        break;
154 307756
        }
155 719651
        if (dvsg == NULL || dvsg->jp == NULL) {
156
                /* Create a new documentation segment */
157 264720
                dvsg = vrt_vsc_mksegf(VSC_DOC_CLASS, sj,
158 132360
                    "%jx", (uintmax_t)jjp);
159 132360
                AN(dvsg);
160 132360
                dvsg->jp = jp;
161 132360
                dvsg->head->doc_id = jjp;
162 132360
                memcpy(dvsg->ptr, jp, sj);
163 132360
                VWMB();
164 132360
                dvsg->head->ready = 1;
165 132360
                VTAILQ_INSERT_HEAD(&vsc_seglist, dvsg, list);
166 132360
        }
167 719651
        AN(dvsg);
168 719651
        dvsg->refs++;
169
170 719651
        if (*fmt == '\0')
171 45147
                bprintf(buf, "%s", nm);
172
        else
173 674504
                bprintf(buf, "%s.%s", nm, fmt);
174
175 719651
        AN(heritage.proc_vsmw);
176
177 719651
        vsg = vrt_vsc_mksegv(vc, VSC_CLASS, sd, buf, va);
178 719651
        AN(vsg);
179 719651
        vsg->nm = nm;
180 719651
        vsg->doc = dvsg;
181 719651
        vsg->head->doc_id = jjp;
182 719651
        VTAILQ_INSERT_TAIL(&vsc_seglist, vsg, list);
183 719651
        VWMB();
184 719651
        vsg->head->ready = 1;
185 719651
        vsc_unlock();
186 719651
        if (sg != NULL)
187 141735
                *sg = vsg;
188 719651
        return (vsg->ptr);
189
}
190
191
void
192 2071
VRT_VSC_Destroy(const char *nm, struct vsc_seg *vsg)
193
{
194
        struct vsc_seg *dvsg;
195
196 2071
        vsc_lock();
197
198 2071
        AN(heritage.proc_vsmw);
199 2071
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
200 2071
        CAST_OBJ_NOTNULL(dvsg, vsg->doc, VSC_SEG_MAGIC);
201 2071
        AZ(vsg->jp);
202 2071
        assert(vsg->vsm == heritage.proc_vsmw);
203 2071
        assert(vsg->nm == nm);
204
205 2071
        VSMW_Free(heritage.proc_vsmw, &vsg->seg);
206 2071
        VTAILQ_REMOVE(&vsc_seglist, vsg, list);
207 2071
        FREE_OBJ(vsg);
208 2071
        if (--dvsg->refs == 0) {
209 50
                VSMW_Free(heritage.proc_vsmw, &dvsg->seg);
210 50
                VTAILQ_REMOVE(&vsc_seglist, dvsg, list);
211 50
                FREE_OBJ(dvsg);
212 50
        }
213 2071
        vsc_unlock();
214 2071
}