]>
Commit | Line | Data |
---|---|---|
df92bd2a | 1 | |
30a4f2a8 | 2 | /* |
a3d5953d | 3 | * $Id: stmem.cc,v 1.43 1997/06/04 06:16:10 wessels Exp $ |
30a4f2a8 | 4 | * |
5 | * DEBUG: section 19 Memory Primitives | |
6 | * AUTHOR: Harvest Derived | |
7 | * | |
42c04c16 | 8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ |
30a4f2a8 | 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 | */ | |
019dd986 | 31 | |
30a4f2a8 | 32 | /* |
33 | * Copyright (c) 1994, 1995. All rights reserved. | |
34 | * | |
35 | * The Harvest software was developed by the Internet Research Task | |
36 | * Force Research Group on Resource Discovery (IRTF-RD): | |
37 | * | |
38 | * Mic Bowman of Transarc Corporation. | |
39 | * Peter Danzig of the University of Southern California. | |
40 | * Darren R. Hardy of the University of Colorado at Boulder. | |
41 | * Udi Manber of the University of Arizona. | |
42 | * Michael F. Schwartz of the University of Colorado at Boulder. | |
43 | * Duane Wessels of the University of Colorado at Boulder. | |
44 | * | |
45 | * This copyright notice applies to software in the Harvest | |
46 | * ``src/'' directory only. Users should consult the individual | |
47 | * copyright notices in the ``components/'' subdirectories for | |
48 | * copyright information about other software bundled with the | |
49 | * Harvest source code distribution. | |
50 | * | |
51 | * TERMS OF USE | |
52 | * | |
53 | * The Harvest software may be used and re-distributed without | |
54 | * charge, provided that the software origin and research team are | |
55 | * cited in any use of the system. Most commonly this is | |
56 | * accomplished by including a link to the Harvest Home Page | |
57 | * (http://harvest.cs.colorado.edu/) from the query page of any | |
58 | * Broker you deploy, as well as in the query result pages. These | |
59 | * links are generated automatically by the standard Broker | |
60 | * software distribution. | |
61 | * | |
62 | * The Harvest software is provided ``as is'', without express or | |
63 | * implied warranty, and with no support nor obligation to assist | |
64 | * in its use, correction, modification or enhancement. We assume | |
65 | * no liability with respect to the infringement of copyrights, | |
66 | * trade secrets, or any patents, and are not responsible for | |
67 | * consequential damages. Proper use of the Harvest software is | |
68 | * entirely the responsibility of the user. | |
69 | * | |
70 | * DERIVATIVE WORKS | |
71 | * | |
72 | * Users may make derivative works from the Harvest software, subject | |
73 | * to the following constraints: | |
74 | * | |
75 | * - You must include the above copyright notice and these | |
76 | * accompanying paragraphs in all forms of derivative works, | |
77 | * and any documentation and other materials related to such | |
78 | * distribution and use acknowledge that the software was | |
79 | * developed at the above institutions. | |
80 | * | |
81 | * - You must notify IRTF-RD regarding your distribution of | |
82 | * the derivative work. | |
83 | * | |
84 | * - You must clearly notify users that your are distributing | |
85 | * a modified version and not the original Harvest software. | |
86 | * | |
87 | * - Any derivative product is also subject to these copyright | |
88 | * and use restrictions. | |
89 | * | |
90 | * Note that the Harvest software is NOT in the public domain. We | |
91 | * retain copyright, as specified above. | |
92 | * | |
93 | * HISTORY OF FREE SOFTWARE STATUS | |
94 | * | |
95 | * Originally we required sites to license the software in cases | |
96 | * where they were going to build commercial products/services | |
97 | * around Harvest. In June 1995 we changed this policy. We now | |
98 | * allow people to use the core Harvest software (the code found in | |
99 | * the Harvest ``src/'' directory) for free. We made this change | |
100 | * in the interest of encouraging the widest possible deployment of | |
101 | * the technology. The Harvest software is really a reference | |
102 | * implementation of a set of protocols and formats, some of which | |
103 | * we intend to standardize. We encourage commercial | |
104 | * re-implementations of code complying to this set of standards. | |
019dd986 | 105 | */ |
ed43818f | 106 | |
44a47c6e | 107 | #include "squid.h" |
090089c4 | 108 | |
1750e760 | 109 | stmem_stats sm_stats; |
110 | stmem_stats disk_stats; | |
30a4f2a8 | 111 | stmem_stats request_pool; |
112 | stmem_stats mem_obj_pool; | |
090089c4 | 113 | |
114 | #define min(x,y) ((x)<(y)? (x) : (y)) | |
115 | ||
116 | #ifndef USE_MEMALIGN | |
117 | #define USE_MEMALIGN 0 | |
118 | #endif | |
119 | ||
24382924 | 120 | static void *get_free_thing _PARAMS((stmem_stats *)); |
121 | static void put_free_thing _PARAMS((stmem_stats *, void *)); | |
122 | static void stmemFreeThingMemory _PARAMS((stmem_stats *)); | |
7ecd0a2f | 123 | |
d89d1fb6 | 124 | void |
b8d8561b | 125 | memFree(mem_ptr mem) |
090089c4 | 126 | { |
127 | mem_node lastp, p = mem->head; | |
128 | ||
129 | if (p) { | |
130 | while (p && (p != mem->tail)) { | |
131 | lastp = p; | |
132 | p = p->next; | |
133 | if (lastp) { | |
2daae136 | 134 | put_free_4k_page(lastp->data); |
090089c4 | 135 | safe_free(lastp); |
136 | } | |
137 | } | |
138 | ||
139 | if (p) { | |
2daae136 | 140 | put_free_4k_page(p->data); |
090089c4 | 141 | safe_free(p); |
142 | } | |
143 | } | |
144 | memset(mem, '\0', sizeof(mem_ptr)); /* nuke in case ref'ed again */ | |
145 | safe_free(mem); | |
146 | } | |
147 | ||
38f0f5d4 | 148 | #ifdef UNUSED_CODE |
d89d1fb6 | 149 | void |
b8d8561b | 150 | memFreeData(mem_ptr mem) |
090089c4 | 151 | { |
152 | mem_node lastp, p = mem->head; | |
090089c4 | 153 | while (p != mem->tail) { |
154 | lastp = p; | |
155 | p = p->next; | |
2daae136 | 156 | put_free_4k_page(lastp->data); |
090089c4 | 157 | safe_free(lastp); |
158 | } | |
090089c4 | 159 | if (p != NULL) { |
2daae136 | 160 | put_free_4k_page(p->data); |
090089c4 | 161 | safe_free(p); |
162 | p = NULL; | |
163 | } | |
164 | mem->head = mem->tail = NULL; /* detach in case ref'd */ | |
165 | mem->origin_offset = 0; | |
166 | } | |
38f0f5d4 | 167 | #endif |
090089c4 | 168 | |
d89d1fb6 | 169 | int |
b8d8561b | 170 | memFreeDataUpto(mem_ptr mem, int target_offset) |
090089c4 | 171 | { |
172 | int current_offset = mem->origin_offset; | |
173 | mem_node lastp, p = mem->head; | |
174 | ||
175 | while (p && ((current_offset + p->len) <= target_offset)) { | |
176 | if (p == mem->tail) { | |
177 | /* keep the last one to avoid change to other part of code */ | |
178 | mem->head = mem->tail; | |
179 | mem->origin_offset = current_offset; | |
180 | return current_offset; | |
181 | } else { | |
182 | lastp = p; | |
183 | p = p->next; | |
184 | current_offset += lastp->len; | |
2daae136 | 185 | put_free_4k_page(lastp->data); |
090089c4 | 186 | safe_free(lastp); |
187 | } | |
188 | } | |
189 | ||
190 | mem->head = p; | |
191 | mem->origin_offset = current_offset; | |
192 | if (current_offset < target_offset) { | |
193 | /* there are still some data left. */ | |
194 | return current_offset; | |
195 | } | |
196 | if (current_offset != target_offset) { | |
a3d5953d | 197 | debug(19, 1) ("memFreeDataUpto: This shouldn't happen. Some odd condition.\n"); |
198 | debug(19, 1) (" Current offset: %d Target offset: %d p: %p\n", | |
090089c4 | 199 | current_offset, target_offset, p); |
200 | } | |
201 | return current_offset; | |
090089c4 | 202 | } |
203 | ||
204 | ||
205 | /* Append incoming data. */ | |
e6e5d90d | 206 | void |
0ee4272b | 207 | memAppend(mem_ptr mem, const char *data, int len) |
090089c4 | 208 | { |
209 | mem_node p; | |
210 | int avail_len; | |
211 | int len_to_copy; | |
212 | ||
a3d5953d | 213 | debug(19, 6) ("memAppend: len %d\n", len); |
090089c4 | 214 | |
215 | /* Does the last block still contain empty space? | |
216 | * If so, fill out the block before dropping into the | |
217 | * allocation loop */ | |
218 | ||
219 | if (mem->head && mem->tail && (mem->tail->len < SM_PAGE_SIZE)) { | |
220 | avail_len = SM_PAGE_SIZE - (mem->tail->len); | |
221 | len_to_copy = min(avail_len, len); | |
30a4f2a8 | 222 | xmemcpy((mem->tail->data + mem->tail->len), data, len_to_copy); |
090089c4 | 223 | /* Adjust the ptr and len according to what was deposited in the page */ |
224 | data += len_to_copy; | |
225 | len -= len_to_copy; | |
226 | mem->tail->len += len_to_copy; | |
227 | } | |
228 | while (len > 0) { | |
229 | len_to_copy = min(len, SM_PAGE_SIZE); | |
30a4f2a8 | 230 | p = xcalloc(1, sizeof(Mem_Node)); |
090089c4 | 231 | p->next = NULL; |
232 | p->len = len_to_copy; | |
2daae136 | 233 | p->data = get_free_4k_page(); |
30a4f2a8 | 234 | xmemcpy(p->data, data, len_to_copy); |
090089c4 | 235 | |
236 | if (!mem->head) { | |
237 | /* The chain is empty */ | |
238 | mem->head = mem->tail = p; | |
239 | } else { | |
240 | /* Append it to existing chain */ | |
241 | mem->tail->next = p; | |
242 | mem->tail = p; | |
243 | } | |
244 | len -= len_to_copy; | |
245 | data += len_to_copy; | |
246 | } | |
090089c4 | 247 | } |
248 | ||
d89d1fb6 | 249 | size_t |
250 | memCopy(const mem_ptr mem, off_t offset, char *buf, size_t size) | |
090089c4 | 251 | { |
252 | mem_node p = mem->head; | |
d89d1fb6 | 253 | off_t t_off = mem->origin_offset; |
254 | size_t bytes_to_go = size; | |
30a4f2a8 | 255 | char *ptr_to_buf = NULL; |
090089c4 | 256 | int bytes_from_this_packet = 0; |
257 | int bytes_into_this_packet = 0; | |
a3d5953d | 258 | debug(19, 6) ("memCopy: offset %d: size %d\n", offset, size); |
30a4f2a8 | 259 | if (p == NULL) |
0a0bf5db | 260 | return -1; |
261 | /* fatal_dump("memCopy: NULL mem_node"); *//* Can happen on async */ | |
97a88399 | 262 | assert(size > 0); |
090089c4 | 263 | /* Seek our way into store */ |
264 | while ((t_off + p->len) < offset) { | |
265 | t_off += p->len; | |
d89d1fb6 | 266 | assert(p->next); |
267 | p = p->next; | |
090089c4 | 268 | } |
090089c4 | 269 | /* Start copying begining with this block until |
270 | * we're satiated */ | |
090089c4 | 271 | bytes_into_this_packet = offset - t_off; |
d89d1fb6 | 272 | bytes_from_this_packet = min(bytes_to_go, p->len - bytes_into_this_packet); |
30a4f2a8 | 273 | xmemcpy(buf, p->data + bytes_into_this_packet, bytes_from_this_packet); |
090089c4 | 274 | bytes_to_go -= bytes_from_this_packet; |
275 | ptr_to_buf = buf + bytes_from_this_packet; | |
276 | p = p->next; | |
090089c4 | 277 | while (p && bytes_to_go > 0) { |
278 | if (bytes_to_go > p->len) { | |
30a4f2a8 | 279 | xmemcpy(ptr_to_buf, p->data, p->len); |
090089c4 | 280 | ptr_to_buf += p->len; |
281 | bytes_to_go -= p->len; | |
282 | } else { | |
30a4f2a8 | 283 | xmemcpy(ptr_to_buf, p->data, bytes_to_go); |
090089c4 | 284 | bytes_to_go -= bytes_to_go; |
285 | } | |
286 | p = p->next; | |
287 | } | |
d89d1fb6 | 288 | return size - bytes_to_go; |
090089c4 | 289 | } |
290 | ||
291 | ||
292 | /* Do whatever is necessary to begin storage of new object */ | |
b8d8561b | 293 | mem_ptr |
0673c0ba | 294 | memInit(void) |
090089c4 | 295 | { |
30a4f2a8 | 296 | mem_ptr new = xcalloc(1, sizeof(Mem_Hdr)); |
090089c4 | 297 | new->tail = new->head = NULL; |
090089c4 | 298 | return new; |
299 | } | |
300 | ||
b8d8561b | 301 | static void * |
302 | get_free_thing(stmem_stats * thing) | |
30a4f2a8 | 303 | { |
7ecd0a2f | 304 | void *p = NULL; |
305 | if (!empty_stack(&thing->free_page_stack)) { | |
55bb9c51 | 306 | p = pop(&thing->free_page_stack); |
307 | if (p == NULL) | |
7ecd0a2f | 308 | fatal_dump("get_free_thing: NULL pointer?"); |
30a4f2a8 | 309 | } else { |
55bb9c51 | 310 | p = xmalloc(thing->page_size); |
7ecd0a2f | 311 | thing->total_pages_allocated++; |
30a4f2a8 | 312 | } |
7ecd0a2f | 313 | thing->n_pages_in_use++; |
314 | memset(p, '\0', thing->page_size); | |
315 | return p; | |
30a4f2a8 | 316 | } |
317 | ||
b8d8561b | 318 | void * |
0673c0ba | 319 | get_free_request_t(void) |
30a4f2a8 | 320 | { |
7ecd0a2f | 321 | return get_free_thing(&request_pool); |
30a4f2a8 | 322 | } |
323 | ||
b8d8561b | 324 | void * |
0673c0ba | 325 | get_free_mem_obj(void) |
30a4f2a8 | 326 | { |
7ecd0a2f | 327 | return get_free_thing(&mem_obj_pool); |
30a4f2a8 | 328 | } |
329 | ||
b8d8561b | 330 | char * |
0673c0ba | 331 | get_free_4k_page(void) |
30a4f2a8 | 332 | { |
f7a5493b | 333 | return (char *) get_free_thing(&sm_stats); |
30a4f2a8 | 334 | } |
335 | ||
b8d8561b | 336 | char * |
0673c0ba | 337 | get_free_8k_page(void) |
7ecd0a2f | 338 | { |
f7a5493b | 339 | return (char *) get_free_thing(&disk_stats); |
7ecd0a2f | 340 | } |
090089c4 | 341 | |
b8d8561b | 342 | static void |
343 | put_free_thing(stmem_stats * thing, void *p) | |
090089c4 | 344 | { |
cadbacbd | 345 | if (p == NULL) |
346 | fatal_dump("Somebody is putting a NULL pointer!"); | |
7ecd0a2f | 347 | thing->n_pages_in_use--; |
348 | if (thing->total_pages_allocated > thing->max_pages) { | |
349 | xfree(p); | |
350 | thing->total_pages_allocated--; | |
351 | } else if (full_stack(&thing->free_page_stack)) { | |
352 | xfree(p); | |
353 | thing->total_pages_allocated--; | |
090089c4 | 354 | } else { |
55bb9c51 | 355 | push(&thing->free_page_stack, p); |
090089c4 | 356 | } |
090089c4 | 357 | } |
358 | ||
ea6f43cd | 359 | void |
67508012 | 360 | put_free_request_t(void *req) |
090089c4 | 361 | { |
7ecd0a2f | 362 | put_free_thing(&request_pool, req); |
090089c4 | 363 | } |
364 | ||
b8d8561b | 365 | void |
366 | put_free_mem_obj(void *mem) | |
090089c4 | 367 | { |
7ecd0a2f | 368 | put_free_thing(&mem_obj_pool, mem); |
369 | } | |
370 | ||
b8d8561b | 371 | void |
372 | put_free_4k_page(void *page) | |
7ecd0a2f | 373 | { |
374 | put_free_thing(&sm_stats, page); | |
090089c4 | 375 | } |
376 | ||
b8d8561b | 377 | void |
378 | put_free_8k_page(void *page) | |
090089c4 | 379 | { |
7ecd0a2f | 380 | put_free_thing(&disk_stats, page); |
090089c4 | 381 | } |
382 | ||
b8d8561b | 383 | void |
0673c0ba | 384 | stmemInit(void) |
090089c4 | 385 | { |
386 | sm_stats.page_size = SM_PAGE_SIZE; | |
387 | sm_stats.total_pages_allocated = 0; | |
090089c4 | 388 | sm_stats.n_pages_in_use = 0; |
e954773d | 389 | sm_stats.max_pages = Config.Mem.maxSize / SM_PAGE_SIZE; |
090089c4 | 390 | |
391 | disk_stats.page_size = DISK_PAGE_SIZE; | |
392 | disk_stats.total_pages_allocated = 0; | |
090089c4 | 393 | disk_stats.n_pages_in_use = 0; |
7ecd0a2f | 394 | disk_stats.max_pages = 200; |
090089c4 | 395 | |
30a4f2a8 | 396 | request_pool.page_size = sizeof(request_t); |
397 | request_pool.total_pages_allocated = 0; | |
30a4f2a8 | 398 | request_pool.n_pages_in_use = 0; |
e83892e9 | 399 | request_pool.max_pages = Squid_MaxFD >> 3; |
30a4f2a8 | 400 | |
401 | mem_obj_pool.page_size = sizeof(MemObject); | |
402 | mem_obj_pool.total_pages_allocated = 0; | |
30a4f2a8 | 403 | mem_obj_pool.n_pages_in_use = 0; |
e83892e9 | 404 | mem_obj_pool.max_pages = Squid_MaxFD >> 3; |
30a4f2a8 | 405 | |
9864ee44 | 406 | #if PURIFY |
a3d5953d | 407 | debug(19, 0) ("Disabling stacks under purify\n"); |
9864ee44 | 408 | sm_stats.max_pages = 0; |
409 | disk_stats.max_pages = 0; | |
410 | request_pool.max_pages = 0; | |
411 | mem_obj_pool.max_pages = 0; | |
412 | #endif | |
caebbe00 | 413 | if (!opt_mem_pools) { |
414 | sm_stats.max_pages = 0; | |
415 | disk_stats.max_pages = 0; | |
416 | request_pool.max_pages = 0; | |
417 | mem_obj_pool.max_pages = 0; | |
418 | } | |
7ecd0a2f | 419 | init_stack(&sm_stats.free_page_stack, sm_stats.max_pages); |
420 | init_stack(&disk_stats.free_page_stack, disk_stats.max_pages); | |
421 | init_stack(&request_pool.free_page_stack, request_pool.max_pages); | |
422 | init_stack(&mem_obj_pool.free_page_stack, mem_obj_pool.max_pages); | |
090089c4 | 423 | } |
0a21bd84 | 424 | |
425 | static void | |
426 | stmemFreeThingMemory(stmem_stats * thing) | |
427 | { | |
428 | void *p; | |
429 | while (!empty_stack(&thing->free_page_stack)) { | |
430 | p = pop(&thing->free_page_stack); | |
431 | safe_free(p); | |
432 | } | |
df92bd2a | 433 | stackFreeMemory(&thing->free_page_stack); |
0a21bd84 | 434 | } |
435 | ||
436 | void | |
437 | stmemFreeMemory(void) | |
438 | { | |
439 | stmemFreeThingMemory(&sm_stats); | |
440 | stmemFreeThingMemory(&disk_stats); | |
441 | stmemFreeThingMemory(&request_pool); | |
442 | stmemFreeThingMemory(&mem_obj_pool); | |
443 | } |