varnish-cache/bin/varnishd/common/common_vsc.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2015 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 <errno.h>
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 5720
vsc_dummy_lock(void)
76
{
77 5720
}
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 100744
vrt_vsc_mksegv(struct vsmw_cluster *vc, const char *class,
86
    size_t payload, const char *fmt, va_list va)
87
{
88
        struct vsc_seg *vsg;
89
90 100744
        ALLOC_OBJ(vsg, VSC_SEG_MAGIC);
91 100744
        AN(vsg);
92 100744
        vsg->seg = VSMW_Allocv(heritage.proc_vsmw, vc, class,
93
            VRT_VSC_Overhead(payload), fmt, va);
94 100744
        AN(vsg->seg);
95 100744
        vsg->vsm = heritage.proc_vsmw;
96 100744
        vsg->head = (void*)vsg->seg;
97 100744
        vsg->head->body_offset = vsc_overhead;
98 100744
        vsg->ptr = (char*)vsg->seg + vsc_overhead;
99 100744
        return (vsg);
100
}
101
102
static struct vsc_seg *
103 16628
vrt_vsc_mksegf(const char *class, size_t payload, const char *fmt, ...)
104
{
105
        va_list ap;
106
        struct vsc_seg *vsg;
107
108 16628
        va_start(ap, fmt);
109 16628
        vsg = vrt_vsc_mksegv(NULL, class, payload, fmt, ap);
110 16628
        va_end(ap);
111 16628
        return (vsg);
112
}
113
114
size_t
115 104167
VRT_VSC_Overhead(size_t payload)
116
{
117 104167
        return (vsc_overhead + PRNDUP(payload));
118
}
119
120
void
121 144
VRT_VSC_Hide(const struct vsc_seg *vsg)
122
{
123 144
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
124 144
        assert(vsg->head->ready > 0);
125 144
        vsg->head->ready = 2;
126 144
}
127
128
void
129 4112
VRT_VSC_Reveal(const struct vsc_seg *vsg)
130
{
131 4112
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
132 4112
        assert(vsg->head->ready > 0);
133 4112
        vsg->head->ready = 1;
134 4112
}
135
136
void *
137 84116
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 84116
        vsc_lock();
146
147 84116
        jjp = (uintptr_t)jp;
148
149 147404
        VTAILQ_FOREACH(dvsg, &vsc_seglist, list) {
150 141792
                if (dvsg->vsm != heritage.proc_vsmw)
151 27536
                        continue;
152 114256
                if (dvsg->jp == NULL || dvsg->jp == jp)
153
                        break;
154
        }
155 84116
        if (dvsg == NULL || dvsg->jp == NULL) {
156
                /* Create a new documentation segment */
157 16628
                dvsg = vrt_vsc_mksegf(VSC_DOC_CLASS, sj,
158
                    "%jx", (uintmax_t)jjp);
159 16628
                AN(dvsg);
160 16628
                dvsg->jp = jp;
161 16628
                dvsg->head->doc_id = jjp;
162 16628
                memcpy(dvsg->ptr, jp, sj);
163 16628
                VWMB();
164 16628
                dvsg->head->ready = 1;
165 16628
                VTAILQ_INSERT_HEAD(&vsc_seglist, dvsg, list);
166
        }
167 84116
        AN(dvsg);
168 84116
        dvsg->refs++;
169
170 84116
        if (*fmt == '\0')
171 5616
                bprintf(buf, "%s", nm);
172
        else
173 78500
                bprintf(buf, "%s.%s", nm, fmt);
174
175 84116
        AN(heritage.proc_vsmw);
176
177 84116
        vsg = vrt_vsc_mksegv(vc, VSC_CLASS, sd, buf, va);
178 84116
        AN(vsg);
179 84116
        vsg->nm = nm;
180 84116
        vsg->doc = dvsg;
181 84116
        vsg->head->doc_id = jjp;
182 84116
        VTAILQ_INSERT_TAIL(&vsc_seglist, vsg, list);
183 84116
        VWMB();
184 84116
        vsg->head->ready = 1;
185 84116
        vsc_unlock();
186 84116
        if (sg != NULL)
187 17936
                *sg = vsg;
188 84116
        return (vsg->ptr);
189
}
190
191
void
192 276
VRT_VSC_Destroy(const char *nm, struct vsc_seg *vsg)
193
{
194
        struct vsc_seg *dvsg;
195
196 276
        vsc_lock();
197
198 276
        AN(heritage.proc_vsmw);
199 276
        CHECK_OBJ_NOTNULL(vsg, VSC_SEG_MAGIC);
200 276
        AZ(vsg->jp);
201 276
        CHECK_OBJ_NOTNULL(vsg->doc, VSC_SEG_MAGIC);
202 276
        assert(vsg->vsm == heritage.proc_vsmw);
203 276
        assert(vsg->nm == nm);
204
205 276
        dvsg = vsg->doc;
206 276
        VSMW_Free(heritage.proc_vsmw, &vsg->seg);
207 276
        VTAILQ_REMOVE(&vsc_seglist, vsg, list);
208 276
        FREE_OBJ(vsg);
209 276
        if (--dvsg->refs == 0) {
210 4
                VSMW_Free(heritage.proc_vsmw, &dvsg->seg);
211 4
                VTAILQ_REMOVE(&vsc_seglist, dvsg, list);
212 4
                FREE_OBJ(dvsg);
213
        }
214 276
        vsc_unlock();
215 276
}