]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/cbdata.cc
3 * $Id: cbdata.cc,v 1.48 2002/10/24 22:59:29 adrian Exp $
5 * DEBUG: section 45 Callback Data Registry
6 * ORIGINAL AUTHOR: Duane Wessels
7 * Modified by Moez Mahfoudh (08/12/2000)
9 * SQUID Web Proxy Cache http://www.squid-cache.org/
10 * ----------------------------------------------------------
12 * Squid is the result of efforts by numerous individuals from
13 * the Internet community; see the CONTRIBUTORS file for full
14 * details. Many organizations have provided support for Squid's
15 * development; see the SPONSORS file for full details. Squid is
16 * Copyrighted (C) 2001 by the Regents of the University of
17 * California; see the COPYRIGHT file for full details. Squid
18 * incorporates software developed and/or copyrighted by other
19 * sources; see the CREDITS file for full details.
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation; either version 2 of the License, or
24 * (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
38 * These routines manage a set of registered callback data pointers.
39 * One of the easiest ways to make Squid coredump is to issue a
40 * callback to for some data structure which has previously been
41 * freed. With these routines, we register (add) callback data
42 * pointers, lock them just before registering the callback function,
43 * validate them before issuing the callback, and then free them
50 static int cbdataCount
= 0;
52 dlink_list cbdataEntries
;
55 typedef struct _cbdata
{
64 long y
; /* cookie used while debugging */
72 static OBJH cbdataDump
;
77 } *cbdata_index
= NULL
;
80 #define OFFSET_OF(type, member) ((int)(char *)&((type *)0L)->member)
81 #define CBDATA_COOKIE (long)0xDEADBEEF
82 #define CBDATA_CHECK(c) assert(c->y == ((long)c ^ CBDATA_COOKIE))
85 cbdataInternalInitType(cbdata_type type
, const char *name
, int size
, FREE
* free_func
)
88 if (type
>= cbdata_types
) {
89 cbdata_index
= (CBDataIndex
*)xrealloc(cbdata_index
, (type
+ 1) * sizeof(*cbdata_index
));
90 memset(&cbdata_index
[cbdata_types
], 0,
91 (type
+ 1 - cbdata_types
) * sizeof(*cbdata_index
));
92 cbdata_types
= type
+ 1;
94 if (cbdata_index
[type
].pool
)
96 label
= (char *)xmalloc(strlen(name
) + 20);
97 snprintf(label
, strlen(name
) + 20, "cbdata %s (%d)", name
, (int) type
);
98 assert(OFFSET_OF(cbdata
, data
) == (sizeof(cbdata
) - sizeof(((cbdata
*) NULL
)->data
)));
99 cbdata_index
[type
].pool
= memPoolCreate(label
, size
+ OFFSET_OF(cbdata
, data
));
100 cbdata_index
[type
].free_func
= free_func
;
104 cbdataInternalAddType(cbdata_type type
, const char *name
, int size
, FREE
* free_func
)
108 type
= (cbdata_type
)cbdata_types
;
109 cbdataInternalInitType(type
, name
, size
, free_func
);
116 debug(45, 3) ("cbdataInit\n");
117 cachemgrRegister("cbdata",
118 "Callback Data Registry Contents",
120 #define CREATE_CBDATA(type) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), NULL)
121 #define CREATE_CBDATA_FREE(type, free_func) cbdataInternalInitType(CBDATA_##type, #type, sizeof(type), free_func)
123 * most of these should be moved out to their respective module.
125 CREATE_CBDATA(acl_access
);
126 CREATE_CBDATA(aclCheck_t
);
127 CREATE_CBDATA(clientHttpRequest
);
128 CREATE_CBDATA(ConnStateData
);
129 CREATE_CBDATA(ErrorState
);
130 CREATE_CBDATA(FwdState
);
131 CREATE_CBDATA(generic_cbdata
);
132 CREATE_CBDATA(helper
);
133 CREATE_CBDATA(helper_server
);
134 CREATE_CBDATA(statefulhelper
);
135 CREATE_CBDATA(helper_stateful_server
);
136 CREATE_CBDATA_FREE(peer
, peerDestroy
);
137 CREATE_CBDATA(ps_state
);
138 CREATE_CBDATA(RemovalPolicy
);
139 CREATE_CBDATA(RemovalPolicyWalker
);
140 CREATE_CBDATA(RemovalPurgeWalker
);
145 cbdataInternalAllocDbg(cbdata_type type
, const char *file
, int line
)
147 cbdataInternalAlloc(cbdata_type type
)
151 assert(type
> 0 && type
< cbdata_types
);
152 p
= (cbdata
*)memPoolAlloc(cbdata_index
[type
].pool
);
160 p
->y
= (long) p
^ CBDATA_COOKIE
;
164 dlinkAdd(p
, &p
->link
, &cbdataEntries
);
165 debug(45, 3) ("cbdataAlloc: %p %s:%d\n", &p
->data
, file
, line
);
167 return (void *) &p
->data
;
172 cbdataInternalFreeDbg(void *p
, const char *file
, int line
)
174 cbdataInternalFree(void *p
)
179 c
= (cbdata
*) (((char *) p
) - OFFSET_OF(cbdata
, data
));
181 debug(45, 3) ("cbdataFree: %p %s:%d\n", p
, file
, line
);
183 debug(45, 3) ("cbdataFree: %p\n", p
);
188 debug(45, 3) ("cbdataFree: %p has %d locks, not freeing\n",
193 debug(45, 3) ("cbdataFree: Freeing %p\n", p
);
195 dlinkDelete(&c
->link
, &cbdataEntries
);
197 free_func
= cbdata_index
[c
->type
].free_func
;
199 free_func((void *) p
);
200 memPoolFree(cbdata_index
[c
->type
].pool
, c
);
206 cbdataInternalLockDbg(const void *p
, const char *file
, int line
)
208 cbdataInternalLock(const void *p
)
214 c
= (cbdata
*) (((char *) p
) - OFFSET_OF(cbdata
, data
));
216 debug(45, 3) ("cbdataLock: %p=%d %s:%d\n", p
, c
? c
->locks
+ 1 : -1, file
, line
);
218 debug(45, 3) ("cbdataLock: %p=%d\n", p
, c
? c
->locks
+ 1 : -1);
221 assert(c
->locks
< 65535);
227 cbdataInternalUnlockDbg(const void *p
, const char *file
, int line
)
229 cbdataInternalUnlock(const void *p
)
236 c
= (cbdata
*) (((char *) p
) - OFFSET_OF(cbdata
, data
));
238 debug(45, 3) ("cbdataUnlock: %p=%d %s:%d\n", p
, c
? c
->locks
- 1 : -1, file
, line
);
240 debug(45, 3) ("cbdataUnlock: %p=%d\n", p
, c
? c
->locks
- 1 : -1);
244 assert(c
->locks
> 0);
246 if (c
->valid
|| c
->locks
)
249 debug(45, 3) ("cbdataUnlock: Freeing %p\n", p
);
251 dlinkDelete(&c
->link
, &cbdataEntries
);
253 free_func
= cbdata_index
[c
->type
].free_func
;
255 free_func((void *) p
);
256 memPoolFree(cbdata_index
[c
->type
].pool
, c
);
260 cbdataReferenceValid(const void *p
)
264 return 1; /* A NULL pointer cannot become invalid */
265 debug(45, 3) ("cbdataReferenceValid: %p\n", p
);
266 c
= (cbdata
*) (((char *) p
) - OFFSET_OF(cbdata
, data
));
268 assert(c
->locks
> 0);
274 cbdataInternalReferenceDoneValidDbg(void **pp
, void **tp
, const char *file
, int line
)
276 cbdataInternalReferenceDoneValid(void **pp
, void **tp
)
279 void *p
= (void *) *pp
;
280 int valid
= cbdataReferenceValid(p
);
283 cbdataInternalUnlockDbg(p
, file
, line
);
285 cbdataInternalUnlock(p
);
298 cbdataDump(StoreEntry
* sentry
)
305 storeAppendPrintf(sentry
, "%d cbdata entries\n", cbdataCount
);
307 storeAppendPrintf(sentry
, "Pointer\tType\tLocks\tAllocated by\n");
308 for (n
= cbdataEntries
.head
; n
; n
= n
->next
) {
309 p
= (cbdata
*)n
->data
;
310 storeAppendPrintf(sentry
, "%c%p\t%d\t%d\t%20s:%-5d\n", p
->valid
? ' ' : '!', &p
->data
, p
->type
, p
->locks
, p
->file
, p
->line
);
312 storeAppendPrintf(sentry
, "\n");
313 storeAppendPrintf(sentry
, "types\tsize\tallocated\ttotal\n");
314 for (i
= 1; i
< cbdata_types
; i
++) {
315 MemPool
*pool
= cbdata_index
[i
].pool
;
317 int obj_size
= pool
->obj_size
- OFFSET_OF(cbdata
, data
);
318 storeAppendPrintf(sentry
, "%s\t%d\t%d\t%d\n", pool
->label
+ 7, obj_size
, pool
->meter
.inuse
.level
, obj_size
* pool
->meter
.inuse
.level
);
322 storeAppendPrintf(sentry
, "detailed allocation information only available when compiled with CBDATA_DEBUG\n");
324 storeAppendPrintf(sentry
, "\nsee also \"Memory utilization\" for detailed per type statistics\n");