Updated to fedora-glibc-20071014T1847
[glibc.git] / nscd / mem.c
blobd7c59244aa06f3f366f48f4a072c7c6127edd50b
1 /* Cache memory handling.
2 Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software Foundation,
18 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 #include <assert.h>
21 #include <errno.h>
22 #include <error.h>
23 #include <fcntl.h>
24 #include <inttypes.h>
25 #include <libintl.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/mman.h>
31 #include <sys/param.h>
33 #include "dbg_log.h"
34 #include "nscd.h"
37 static int
38 sort_he (const void *p1, const void *p2)
40 struct hashentry *h1 = *(struct hashentry **) p1;
41 struct hashentry *h2 = *(struct hashentry **) p2;
43 if (h1 < h2)
44 return -1;
45 if (h1 > h2)
46 return 1;
47 return 0;
51 static int
52 sort_he_data (const void *p1, const void *p2)
54 struct hashentry *h1 = *(struct hashentry **) p1;
55 struct hashentry *h2 = *(struct hashentry **) p2;
57 if (h1->packet < h2->packet)
58 return -1;
59 if (h1->packet > h2->packet)
60 return 1;
61 return 0;
65 /* Basic definitions for the bitmap implementation. Only BITMAP_T
66 needs to be changed to choose a different word size. */
67 #define BITMAP_T uint8_t
68 #define BITS (CHAR_BIT * sizeof (BITMAP_T))
69 #define ALLBITS ((((BITMAP_T) 1) << BITS) - 1)
70 #define HIGHBIT (((BITMAP_T) 1) << (BITS - 1))
73 static void
74 markrange (BITMAP_T *mark, ref_t start, size_t len)
76 /* Adjust parameters for block alignment. */
77 start /= BLOCK_ALIGN;
78 len = (len + BLOCK_ALIGN_M1) / BLOCK_ALIGN;
80 size_t elem = start / BITS;
82 if (start % BITS != 0)
84 if (start % BITS + len <= BITS)
86 /* All fits in the partial byte. */
87 mark[elem] |= (ALLBITS >> (BITS - len)) << (start % BITS);
88 return;
91 mark[elem++] |= 0xff << (start % BITS);
92 len -= BITS - (start % BITS);
95 while (len >= BITS)
97 mark[elem++] = ALLBITS;
98 len -= BITS;
101 if (len > 0)
102 mark[elem] |= ALLBITS >> (BITS - len);
106 void
107 gc (struct database_dyn *db)
109 /* We need write access. */
110 pthread_rwlock_wrlock (&db->lock);
112 /* And the memory handling lock. */
113 pthread_mutex_lock (&db->memlock);
115 /* We need an array representing the data area. All memory
116 allocation is BLOCK_ALIGN aligned so this is the level at which
117 we have to look at the memory. We use a mark and sweep algorithm
118 where the marks are placed in this array. */
119 assert (db->head->first_free % BLOCK_ALIGN == 0);
120 BITMAP_T mark[(db->head->first_free / BLOCK_ALIGN + BITS - 1) / BITS];
121 memset (mark, '\0', sizeof (mark));
123 /* Create an array which can hold pointer to all the entries in hash
124 entries. */
125 struct hashentry *he[db->head->nentries];
126 struct hashentry *he_data[db->head->nentries];
128 size_t cnt = 0;
129 for (size_t idx = 0; idx < db->head->module; ++idx)
131 ref_t *prevp = &db->head->array[idx];
132 ref_t run = *prevp;
134 while (run != ENDREF)
136 assert (cnt < db->head->nentries);
137 he[cnt] = (struct hashentry *) (db->data + run);
139 he[cnt]->prevp = prevp;
140 prevp = &he[cnt]->next;
142 /* This is the hash entry itself. */
143 markrange (mark, run, sizeof (struct hashentry));
145 /* Add the information for the data itself. We do this
146 only for the one special entry marked with FIRST. */
147 if (he[cnt]->first)
149 struct datahead *dh
150 = (struct datahead *) (db->data + he[cnt]->packet);
151 markrange (mark, he[cnt]->packet, dh->allocsize);
154 run = he[cnt]->next;
156 ++cnt;
159 assert (cnt == db->head->nentries);
161 /* Sort the entries by the addresses of the referenced data. All
162 the entries pointing to the same DATAHEAD object will have the
163 same key. Stability of the sorting is unimportant. */
164 memcpy (he_data, he, cnt * sizeof (struct hashentry *));
165 qsort (he_data, cnt, sizeof (struct hashentry *), sort_he_data);
167 /* Sort the entries by their address. */
168 qsort (he, cnt, sizeof (struct hashentry *), sort_he);
170 /* Determine the highest used address. */
171 size_t high = sizeof (mark);
172 while (high > 0 && mark[high - 1] == 0)
173 --high;
175 /* No memory used. */
176 if (high == 0)
178 db->head->first_free = 0;
179 goto out;
182 /* Determine the highest offset. */
183 BITMAP_T mask = HIGHBIT;
184 ref_t highref = (high * BITS - 1) * BLOCK_ALIGN;
185 while ((mark[high - 1] & mask) == 0)
187 mask >>= 1;
188 highref -= BLOCK_ALIGN;
191 /* Now we can iterate over the MARK array and find bits which are not
192 set. These represent memory which can be recovered. */
193 size_t byte = 0;
194 /* Find the first gap. */
195 while (byte < high && mark[byte] == ALLBITS)
196 ++byte;
198 if (byte == high
199 || (byte == high - 1 && (mark[byte] & ~(mask | (mask - 1))) == 0))
200 /* No gap. */
201 goto out;
203 mask = 1;
204 cnt = 0;
205 while ((mark[byte] & mask) != 0)
207 ++cnt;
208 mask <<= 1;
210 ref_t off_free = (byte * BITS + cnt) * BLOCK_ALIGN;
211 assert (off_free <= db->head->first_free);
213 struct hashentry **next_hash = he;
214 struct hashentry **next_data = he_data;
216 /* Skip over the hash entries in the first block which does not get
217 moved. */
218 while (next_hash < &he[db->head->nentries]
219 && *next_hash < (struct hashentry *) (db->data + off_free))
220 ++next_hash;
222 while (next_data < &he_data[db->head->nentries]
223 && (*next_data)->packet < off_free)
224 ++next_data;
227 /* Now we start modifying the data. Make sure all readers of the
228 data are aware of this and temporarily don't use the data. */
229 ++db->head->gc_cycle;
230 assert ((db->head->gc_cycle & 1) == 1);
233 /* We do not perform the move operations right away since the
234 he_data array is not sorted by the address of the data. */
235 struct moveinfo
237 void *from;
238 void *to;
239 size_t size;
240 struct moveinfo *next;
241 } *moves = NULL;
243 while (byte < high)
245 /* Search for the next filled block. BYTE is the index of the
246 entry in MARK, MASK is the bit, and CNT is the bit number.
247 OFF_FILLED is the corresponding offset. */
248 if ((mark[byte] & ~(mask - 1)) == 0)
250 /* No other bit set in the same element of MARK. Search in the
251 following memory. */
253 ++byte;
254 while (byte < high && mark[byte] == 0);
256 if (byte == high)
257 /* That was it. */
258 break;
260 mask = 1;
261 cnt = 0;
263 /* Find the exact bit. */
264 while ((mark[byte] & mask) == 0)
266 ++cnt;
267 mask <<= 1;
270 ref_t off_alloc = (byte * BITS + cnt) * BLOCK_ALIGN;
271 assert (off_alloc <= db->head->first_free);
273 /* Find the end of the used area. */
274 if ((mark[byte] & ~(mask - 1)) == (BITMAP_T) ~(mask - 1))
276 /* All other bits set. Search the next bytes in MARK. */
278 ++byte;
279 while (byte < high && mark[byte] == ALLBITS);
281 mask = 1;
282 cnt = 0;
284 if (byte < high)
286 /* Find the exact bit. */
287 while ((mark[byte] & mask) != 0)
289 ++cnt;
290 mask <<= 1;
294 ref_t off_allocend = (byte * BITS + cnt) * BLOCK_ALIGN;
295 assert (off_allocend <= db->head->first_free);
296 /* Now we know that we can copy the area from OFF_ALLOC to
297 OFF_ALLOCEND (not included) to the memory starting at
298 OFF_FREE. First fix up all the entries for the
299 displacement. */
300 ref_t disp = off_alloc - off_free;
302 struct moveinfo *new_move
303 = (struct moveinfo *) alloca (sizeof (*new_move));
304 new_move->from = db->data + off_alloc;
305 new_move->to = db->data + off_free;
306 new_move->size = off_allocend - off_alloc;
307 /* Create a circular list to be always able to append at the end. */
308 if (moves == NULL)
309 moves = new_move->next = new_move;
310 else
312 new_move->next = moves->next;
313 moves = moves->next = new_move;
316 /* The following loop will prepare to move this much data. */
317 off_free += off_allocend - off_alloc;
319 while (off_alloc < off_allocend)
321 /* Determine whether the next entry is for a hash entry or
322 the data. */
323 if ((struct hashentry *) (db->data + off_alloc) == *next_hash)
325 /* Just correct the forward reference. */
326 *(*next_hash++)->prevp -= disp;
328 off_alloc += ((sizeof (struct hashentry) + BLOCK_ALIGN_M1)
329 & ~BLOCK_ALIGN_M1);
331 else
333 assert (next_data < &he_data[db->head->nentries]);
334 assert ((*next_data)->packet == off_alloc);
336 struct datahead *dh = (struct datahead *) (db->data + off_alloc);
339 assert ((*next_data)->key >= (*next_data)->packet);
340 assert ((*next_data)->key + (*next_data)->len
341 <= (*next_data)->packet + dh->allocsize);
343 (*next_data)->packet -= disp;
344 (*next_data)->key -= disp;
345 ++next_data;
347 while (next_data < &he_data[db->head->nentries]
348 && (*next_data)->packet == off_alloc);
350 off_alloc += (dh->allocsize + BLOCK_ALIGN_M1) & ~BLOCK_ALIGN_M1;
353 assert (off_alloc == off_allocend);
355 assert (off_alloc <= db->head->first_free);
356 if (off_alloc == db->head->first_free)
357 /* We are done, that was the last block. */
358 break;
360 assert (next_hash == &he[db->head->nentries]);
361 assert (next_data == &he_data[db->head->nentries]);
363 /* Now perform the actual moves. */
364 if (moves != NULL)
366 struct moveinfo *runp = moves->next;
369 assert ((char *) runp->to >= db->data);
370 assert ((char *) runp->to + runp->size
371 <= db->data + db->head->first_free);
372 assert ((char *) runp->from >= db->data);
373 assert ((char *) runp->from + runp->size
374 <= db->data + db->head->first_free);
376 /* The regions may overlap. */
377 memmove (runp->to, runp->from, runp->size);
378 runp = runp->next;
380 while (runp != moves->next);
382 if (__builtin_expect (debug_level >= 3, 0))
383 dbg_log (_("freed %zu bytes in %s cache"),
384 db->head->first_free
385 - ((char *) moves->to + moves->size - db->data),
386 dbnames[db - dbs]);
388 /* The byte past the end of the last copied block is the next
389 available byte. */
390 db->head->first_free = (char *) moves->to + moves->size - db->data;
392 /* Consistency check. */
393 if (__builtin_expect (debug_level >= 3, 0))
395 for (size_t idx = 0; idx < db->head->module; ++idx)
397 ref_t run = db->head->array[idx];
398 size_t cnt = 0;
400 while (run != ENDREF)
402 if (run + sizeof (struct hashentry) > db->head->first_free)
404 dbg_log ("entry %zu in hash bucket %zu out of bounds: "
405 "%" PRIu32 "+%zu > %zu\n",
406 cnt, idx, run, sizeof (struct hashentry),
407 (size_t) db->head->first_free);
408 break;
411 struct hashentry *he = (struct hashentry *) (db->data + run);
413 if (he->key + he->len > db->head->first_free)
414 dbg_log ("key of entry %zu in hash bucket %zu out of "
415 "bounds: %" PRIu32 "+%zu > %zu\n",
416 cnt, idx, he->key, (size_t) he->len,
417 (size_t) db->head->first_free);
419 if (he->packet + sizeof (struct datahead)
420 > db->head->first_free)
421 dbg_log ("packet of entry %zu in hash bucket %zu out of "
422 "bounds: %" PRIu32 "+%zu > %zu\n",
423 cnt, idx, he->packet, sizeof (struct datahead),
424 (size_t) db->head->first_free);
425 else
427 struct datahead *dh = (struct datahead *) (db->data
428 + he->packet);
429 if (he->packet + dh->allocsize
430 > db->head->first_free)
431 dbg_log ("full key of entry %zu in hash bucket %zu "
432 "out of bounds: %" PRIu32 "+%zu > %zu",
433 cnt, idx, he->packet, (size_t) dh->allocsize,
434 (size_t) db->head->first_free);
437 run = he->next;
438 ++cnt;
444 /* Make sure the data on disk is updated. */
445 if (db->persistent)
446 msync (db->head, db->data + db->head->first_free - (char *) db->head,
447 MS_ASYNC);
450 /* Now we are done modifying the data. */
451 ++db->head->gc_cycle;
452 assert ((db->head->gc_cycle & 1) == 0);
454 /* We are done. */
455 out:
456 pthread_mutex_unlock (&db->memlock);
457 pthread_rwlock_unlock (&db->lock);
461 void *
462 mempool_alloc (struct database_dyn *db, size_t len)
464 /* Make sure LEN is a multiple of our maximum alignment so we can
465 keep track of used memory is multiples of this alignment value. */
466 if ((len & BLOCK_ALIGN_M1) != 0)
467 len += BLOCK_ALIGN - (len & BLOCK_ALIGN_M1);
469 pthread_mutex_lock (&db->memlock);
471 assert ((db->head->first_free & BLOCK_ALIGN_M1) == 0);
473 bool tried_resize = false;
474 void *res;
475 retry:
476 res = db->data + db->head->first_free;
478 if (__builtin_expect (db->head->first_free + len > db->head->data_size, 0))
480 if (! tried_resize)
482 /* Try to resize the database. Grow size of 1/8th. */
483 size_t oldtotal = (sizeof (struct database_pers_head)
484 + roundup (db->head->module * sizeof (ref_t), ALIGN)
485 + db->head->data_size);
486 size_t new_data_size = (db->head->data_size
487 + MAX (2 * len, db->head->data_size / 8));
488 size_t newtotal = (sizeof (struct database_pers_head)
489 + roundup (db->head->module * sizeof (ref_t), ALIGN)
490 + new_data_size);
491 if (newtotal > db->max_db_size)
493 new_data_size -= newtotal - db->max_db_size;
494 newtotal = db->max_db_size;
497 if (db->mmap_used && newtotal > oldtotal
498 /* We only have to adjust the file size. The new pages
499 become magically available. */
500 && TEMP_FAILURE_RETRY_VAL (posix_fallocate (db->wr_fd, oldtotal,
501 newtotal
502 - oldtotal)) == 0)
504 db->head->data_size = new_data_size;
505 tried_resize = true;
506 goto retry;
510 if (! db->last_alloc_failed)
512 dbg_log (_("no more memory for database '%s'"), dbnames[db - dbs]);
514 db->last_alloc_failed = true;
517 /* No luck. */
518 res = NULL;
520 else
522 db->head->first_free += len;
524 db->last_alloc_failed = false;
527 pthread_mutex_unlock (&db->memlock);
529 return res;