cbdata.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 45 Callback Data Registry */
10
11#include "squid.h"
12#include "cbdata.h"
13#include "Generic.h"
14#include "mem/Allocator.h"
15#include "mem/Pool.h"
16#include "mgr/Registration.h"
17#include "Store.h"
18
19#include <climits>
20#include <cstddef>
21
22#if WITH_VALGRIND
23#include <map>
24#endif
25
26static int cbdataCount = 0;
27
37class cbdata
38{
39#if !WITH_VALGRIND
40public:
41 void *operator new(size_t, void *where) {return where;}
46 void operator delete(void *, void *) {}
47#else
49#endif
50
51 /* TODO: examine making cbdata templated on this - so we get type
52 * safe access to data - RBC 20030902 */
53public:
55 valid(0),
56 locks(0),
58 cookie(0),
59 data(nullptr)
60 {}
61 ~cbdata();
62
63 static cbdata *FromUserData(const void *);
64
65 int valid;
66 int32_t locks;
68
69 /* cookie used while debugging */
70 long cookie;
71 void check(int) const {assert(cookie == ((long)this ^ Cookie));}
72 static const long Cookie;
73
74#if !WITH_VALGRIND
75 size_t dataSize() const { return sizeof(data);}
76#endif
77 /* MUST be the last per-instance member */
78 void *data;
79};
80
81static_assert(std::is_standard_layout<cbdata>::value, "the behavior of offsetof(cbdata) is defined");
82
83const long cbdata::Cookie((long)0xDEADBEEF);
84
87}
88*cbdata_index = nullptr;
89
91
92#if WITH_VALGRIND
93static std::map<const void *, cbdata *> cbdata_htable;
94#endif
95
97{
98#if WITH_VALGRIND
99 void *p = data;
100#else
101 void *p = this;
102#endif
104}
105
106cbdata *
107cbdata::FromUserData(const void *p) {
108#if WITH_VALGRIND
109 return cbdata_htable.at(p);
110#else
111 const auto t = static_cast<const char *>(p) - offsetof(cbdata, data);
112 return reinterpret_cast<cbdata *>(const_cast<char *>(t));
113#endif
114}
115
117cbdataInternalAddType(cbdata_type type, const char *name, int size)
118{
119 if (type)
120 return type;
121
122 type = (cbdata_type)(cbdata_types + 1);
123
124 char *label;
125 assert (type == cbdata_types + 1);
126
127 cbdata_index = (CBDataIndex *)xrealloc(cbdata_index, (type + 1) * sizeof(*cbdata_index));
128 memset(&cbdata_index[type], 0, sizeof(*cbdata_index));
129 cbdata_types = type;
130
131 label = (char *)xmalloc(strlen(name) + 20);
132
133 snprintf(label, strlen(name) + 20, "cbdata %s (%d)", name, (int) type);
134
135#if !WITH_VALGRIND
136 size += offsetof(cbdata, data);
137#endif
138
139 cbdata_index[type].pool = memPoolCreate(label, size);
140
141 return type;
142}
143
144void *
146{
147 cbdata *c;
148 void *p;
149 assert(type > 0 && type <= cbdata_types);
150 /* placement new: the pool alloc gives us cbdata + user type memory space
151 * and we init it with cbdata at the start of it
152 */
153#if WITH_VALGRIND
154 c = new cbdata;
155 p = cbdata_index[type].pool->alloc();
156 c->data = p;
157 cbdata_htable.emplace(p,c);
158#else
159 c = new (cbdata_index[type].pool->alloc()) cbdata;
160 p = (void *)&c->data;
161#endif
162
163 c->type = type;
164 c->valid = 1;
165 c->locks = 0;
166 c->cookie = (long) c ^ cbdata::Cookie;
167 ++cbdataCount;
168 debugs(45, 9, "Allocating " << p);
169 return p;
170}
171
172static void
174{
175#if WITH_VALGRIND
176 void *p = c->data;
177#else
178 void *p = (void *)&c->data;
179#endif
180
181 --cbdataCount;
182 debugs(45, 9, "Freeing " << p);
183
184#if WITH_VALGRIND
185 cbdata_htable.erase(p);
186 delete c;
187#else
188 /* This is ugly. But: operator delete doesn't get
189 * the type parameter, so we can't use that
190 * to free the memory.
191 * So, we free it ourselves.
192 * Note that this means a non-placement
193 * new would be a seriously bad idea.
194 * Lastly, if we where a templated class,
195 * we could use the normal delete operator
196 * and it would Just Work. RBC 20030902
197 */
198 c->cbdata::~cbdata();
199#endif
200}
201
202void *
204{
205 auto *c = cbdata::FromUserData(p);
206
207 c->check(__LINE__);
208 assert(c->valid);
209 c->valid = 0;
210
211 if (c->locks) {
212 debugs(45, 9, p << " has " << c->locks << " locks, not freeing");
213 return nullptr;
214 }
215
217 return nullptr;
218}
219
220void
221cbdataInternalLock(const void *p)
222{
223 if (p == nullptr)
224 return;
225
226 auto *c = cbdata::FromUserData(p);
227
228 debugs(45, 9, p << "=" << (c ? c->locks + 1 : -1));
229
230 c->check(__LINE__);
231
232 assert(c->locks < INT_MAX);
233
234 ++ c->locks;
235}
236
237void
239{
240 if (p == nullptr)
241 return;
242
243 auto *c = cbdata::FromUserData(p);
244
245 debugs(45, 9, p << "=" << (c ? c->locks - 1 : -1));
246
247 c->check(__LINE__);
248
249 assert(c != nullptr);
250
251 assert(c->locks > 0);
252
253 -- c->locks;
254
255 if (c->locks)
256 return;
257
258 if (c->valid)
259 return;
260
262}
263
264int
266{
267 if (p == nullptr)
268 return 1; /* A NULL pointer cannot become invalid */
269
270 debugs(45, 9, p);
271
272 const auto c = cbdata::FromUserData(p);
273
274 c->check(__LINE__);
275
276 assert(c->locks > 0);
277
278 return c->valid;
279}
280
281int
283{
284 void *p = (void *) *pp;
285 int valid = cbdataReferenceValid(p);
286 *pp = nullptr;
287
289
290 if (valid) {
291 *tp = p;
292 return 1;
293 } else {
294 *tp = nullptr;
295 return 0;
296 }
297}
298
301{
302 if (data_ != other.data_) { // assignment to self and no-op assignments
303 auto old = data_;
304 data_ = cbdataReference(other.data_);
306 }
307 return *this;
308}
309
311
int size
Definition: ModDevPoll.cc:75
#define memPoolCreate
Creates a named MemPool of elements with the given size.
Definition: Pool.h:123
#define assert(EX)
Definition: assert.h:17
void * cbdataInternalFree(void *p)
Definition: cbdata.cc:203
void cbdataInternalUnlock(const void *p)
Definition: cbdata.cc:238
int cbdata_types
Definition: cbdata.cc:90
cbdata_type cbdataInternalAddType(cbdata_type type, const char *name, int size)
Definition: cbdata.cc:117
static int cbdataCount
Definition: cbdata.cc:26
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:265
void * cbdataInternalAlloc(cbdata_type type)
Definition: cbdata.cc:145
static std::map< const void *, cbdata * > cbdata_htable
Definition: cbdata.cc:93
struct CBDataIndex * cbdata_index
int cbdataInternalReferenceDoneValid(void **pp, void **tp)
Definition: cbdata.cc:282
static void cbdataRealFree(cbdata *c)
Definition: cbdata.cc:173
void cbdataInternalLock(const void *p)
Definition: cbdata.cc:221
#define cbdataReferenceDone(var)
Definition: cbdata.h:352
#define cbdataReference(var)
Definition: cbdata.h:343
static const cbdata_type CBDATA_UNKNOWN
Definition: cbdata.h:196
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:320
int cbdata_type
Definition: cbdata.h:195
an old-style void* callback parameter
Definition: cbdata.h:379
CallbackData & operator=(const CallbackData &other)
Definition: cbdata.cc:300
void * data_
raw callback data, maybe invalid
Definition: cbdata.h:394
void freeOne(void *obj)
return memory reserved by alloc()
Definition: Allocator.h:47
void * alloc()
provide (and reserve) memory suitable for storing one object
Definition: Allocator.h:40
Definition: cbdata.cc:38
static const long Cookie
Definition: cbdata.cc:72
MEMPROXY_CLASS(cbdata)
void check(int) const
Definition: cbdata.cc:71
int valid
Definition: cbdata.cc:65
int32_t locks
Definition: cbdata.cc:66
~cbdata()
Definition: cbdata.cc:96
static cbdata * FromUserData(const void *)
Definition: cbdata.cc:107
long cookie
Definition: cbdata.cc:70
cbdata_type type
Definition: cbdata.cc:67
void * data
Definition: cbdata.cc:78
cbdata()
Definition: cbdata.cc:54
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:193
static size_t dataSize(DB_ENTRY *data)
#define xmalloc
Mem::Allocator * pool
Definition: cbdata.cc:86
int const char size_t
Definition: stub_liblog.cc:86
#define INT_MAX
Definition: types.h:70
void * xrealloc(void *s, size_t sz)
Definition: xalloc.cc:126

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors