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