]> git.ipfire.org Git - thirdparty/squid.git/blob - src/cbdata.cc
fix cbdataAddDbg stuff
[thirdparty/squid.git] / src / cbdata.cc
1
2 /*
3 * $Id: cbdata.cc,v 1.16 1998/02/20 21:04:05 wessels Exp $
4 *
5 * DEBUG: section 45 Callback Data Registry
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * --------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by
14 * the National Science Foundation.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 */
31
32 /*
33 * These routines manage a set of registered callback data pointers.
34 * One of the easiest ways to make Squid coredump is to issue a
35 * callback to for some data structure which has previously been
36 * freed. With these routines, we register (add) callback data
37 * pointers, lock them just before registering the callback function,
38 * validate them before issuing the callback, and then free them
39 * when finished.
40 *
41 * In terms of time, the sequence goes something like this:
42 *
43 * foo = xcalloc(sizeof(foo));
44 * cbdataAdd(foo);
45 * ...
46 * cbdataLock(foo);
47 * some_blocking_operation(..., callback_func, foo);
48 * ...
49 * some_blocking_operation_completes()
50 * if (cbdataValid(foo))
51 * callback_func(..., foo)
52 * cbdataUnlock(foo);
53 * ...
54 * cbdataFree(foo);
55 *
56 * The nice thing is that, we do not need to require that Unlock
57 * occurs before Free. If the Free happens first, then the
58 * callback data is marked invalid and the callback will never
59 * be made. When we Unlock and the lock count reaches zero,
60 * we free the memory if it is marked invalid.
61 */
62
63 #include "squid.h"
64
65 static hash_table *htable = NULL;
66
67 static int cbdataCount = 0;
68
69 typedef struct _cbdata {
70 const void *key;
71 struct _cbdata *next;
72 int valid;
73 int locks;
74 mem_type mem_type;
75 #if CBDATA_DEBUG
76 const char *file;
77 int line;
78 #endif
79 } cbdata;
80
81 static HASHCMP cbdata_cmp;
82 static HASHHASH cbdata_hash;
83
84 static int
85 cbdata_cmp(const void *p1, const void *p2)
86 {
87 return (char *) p1 - (char *) p2;
88 }
89
90 static unsigned int
91 cbdata_hash(const void *p, unsigned int mod)
92 {
93 return ((unsigned long) p >> 8) % mod;
94 }
95
96
97 void
98 cbdataInit(void)
99 {
100 debug(45, 3) ("cbdataInit\n");
101 htable = hash_create(cbdata_cmp, 1 << 8, cbdata_hash);
102 cachemgrRegister("cbdata",
103 "Callback Data Registry Contents",
104 cbdataDump, 0);
105 }
106
107 void
108 #if CBDATA_DEBUG
109 cbdataAddDbg(const void *p, mem_type mem_type, const char *file, int line)
110 #else
111 cbdataAdd(const void *p, mem_type mem_type)
112 #endif
113 {
114 cbdata *c;
115 assert(p);
116 debug(45, 3) ("cbdataAdd: %p\n", p);
117 assert(htable != NULL);
118 assert(hash_lookup(htable, p) == NULL);
119 c = xcalloc(1, sizeof(cbdata));
120 c->key = p;
121 c->valid = 1;
122 c->mem_type = mem_type;
123 #if CBDATA_DEBUG
124 c->file = file;
125 c->line = line;
126 #endif
127 hash_join(htable, (hash_link *) c);
128 cbdataCount++;
129 }
130
131 void
132 cbdataFree(void *p)
133 {
134 cbdata *c = (cbdata *) hash_lookup(htable, p);
135 mem_type mem_type;
136 assert(p);
137 debug(45, 3) ("cbdataFree: %p\n", p);
138 assert(c != NULL);
139 c->valid = 0;
140 if (c->locks) {
141 debug(45, 3) ("cbdataFree: %p has %d locks, not freeing\n",
142 p, c->locks);
143 return;
144 }
145 hash_remove_link(htable, (hash_link *) c);
146 cbdataCount--;
147 mem_type = c->mem_type;
148 xfree(c);
149 debug(45, 3) ("cbdataFree: freeing %p\n", p);
150 if (mem_type == MEM_NONE)
151 xfree(p);
152 else
153 memFree(mem_type, p);
154 }
155
156 void
157 cbdataLock(const void *p)
158 {
159 cbdata *c;
160 if (p == NULL)
161 return;
162 c = (cbdata *) hash_lookup(htable, p);
163 debug(45, 3) ("cbdataLock: %p\n", p);
164 assert(c != NULL);
165 c->locks++;
166 }
167
168 void
169 cbdataUnlock(const void *p)
170 {
171 cbdata *c;
172 if (p == NULL)
173 return;
174 c = (cbdata *) hash_lookup(htable, p);
175 debug(45, 3) ("cbdataUnlock: %p\n", p);
176 assert(c != NULL);
177 assert(c->locks > 0);
178 c->locks--;
179 if (c->valid || c->locks)
180 return;
181 hash_remove_link(htable, (hash_link *) c);
182 cbdataCount--;
183 xfree(c);
184 debug(45, 3) ("cbdataUnlock: Freeing %p\n", p);
185 xfree((void *) p);
186 }
187
188 int
189 cbdataValid(const void *p)
190 {
191 cbdata *c;
192 if (p == NULL)
193 return 0;
194 c = (cbdata *) hash_lookup(htable, p);
195 debug(45, 3) ("cbdataValid: %p\n", p);
196 assert(c != NULL);
197 assert(c->locks > 0);
198 return c->valid;
199 }
200
201
202 void
203 cbdataDump(StoreEntry * sentry)
204 {
205 hash_link *hptr;
206 cbdata *c;
207 storeAppendPrintf(sentry, "%d cbdata entries\n", cbdataCount);
208 for (hptr = hash_first(htable); hptr; hptr = hash_next(htable)) {
209 c = (cbdata *) hptr;
210 #if CBDATA_DEBUG
211 storeAppendPrintf(sentry, "%20p %10s %d locks %s:%d\n",
212 c->key,
213 c->valid ? "VALID" : "NOT VALID",
214 c->locks,
215 c->file, c->line);
216 #else
217 storeAppendPrintf(sentry, "%20p %10s %d locks\n",
218 c->key,
219 c->valid ? "VALID" : "NOT VALID",
220 c->locks);
221 #endif
222 }
223 }