Lines 1-5
Link Here
|
1 |
/* Cache memory handling. |
1 |
/* Cache memory handling. |
2 |
Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. |
2 |
Copyright (C) 2004, 2005, 2006, 2008 Free Software Foundation, Inc. |
3 |
This file is part of the GNU C Library. |
3 |
This file is part of the GNU C Library. |
4 |
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. |
4 |
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. |
5 |
|
5 |
|
Lines 24-29
Link Here
|
24 |
#include <inttypes.h> |
24 |
#include <inttypes.h> |
25 |
#include <libintl.h> |
25 |
#include <libintl.h> |
26 |
#include <limits.h> |
26 |
#include <limits.h> |
|
|
27 |
#include <obstack.h> |
27 |
#include <stdlib.h> |
28 |
#include <stdlib.h> |
28 |
#include <string.h> |
29 |
#include <string.h> |
29 |
#include <unistd.h> |
30 |
#include <unistd.h> |
Lines 79-84
static void
Link Here
|
79 |
markrange (BITMAP_T *mark, ref_t start, size_t len) |
80 |
markrange (BITMAP_T *mark, ref_t start, size_t len) |
80 |
{ |
81 |
{ |
81 |
/* Adjust parameters for block alignment. */ |
82 |
/* Adjust parameters for block alignment. */ |
|
|
83 |
assert ((start & BLOCK_ALIGN_M1) == 0); |
82 |
start /= BLOCK_ALIGN; |
84 |
start /= BLOCK_ALIGN; |
83 |
len = (len + BLOCK_ALIGN_M1) / BLOCK_ALIGN; |
85 |
len = (len + BLOCK_ALIGN_M1) / BLOCK_ALIGN; |
84 |
|
86 |
|
Lines 93-99
markrange (BITMAP_T *mark, ref_t start, size_t len)
Link Here
|
93 |
return; |
95 |
return; |
94 |
} |
96 |
} |
95 |
|
97 |
|
96 |
mark[elem++] |= 0xff << (start % BITS); |
98 |
mark[elem++] |= ALLBITS << (start % BITS); |
97 |
len -= BITS - (start % BITS); |
99 |
len -= BITS - (start % BITS); |
98 |
} |
100 |
} |
99 |
|
101 |
|
Lines 130-143
gc (struct database_dyn *db)
Link Here
|
130 |
size_t stack_used = sizeof (bool) * db->head->module; |
132 |
size_t stack_used = sizeof (bool) * db->head->module; |
131 |
if (__builtin_expect (stack_used > MAX_STACK_USE, 0)) |
133 |
if (__builtin_expect (stack_used > MAX_STACK_USE, 0)) |
132 |
stack_used = 0; |
134 |
stack_used = 0; |
133 |
size_t memory_needed = ((db->head->first_free / BLOCK_ALIGN + BITS - 1) |
135 |
size_t nmark = (db->head->first_free / BLOCK_ALIGN + BITS - 1) / BITS; |
134 |
/ BITS) * sizeof (BITMAP_T); |
136 |
size_t memory_needed = nmark * sizeof (BITMAP_T); |
135 |
if (memory_needed <= MAX_STACK_USE) |
137 |
if (stack_used + memory_needed <= MAX_STACK_USE) |
136 |
{ |
138 |
{ |
137 |
mark = (BITMAP_T *) alloca (memory_needed); |
139 |
mark = (BITMAP_T *) alloca (memory_needed); |
138 |
mark_use_malloc = false; |
140 |
mark_use_malloc = false; |
139 |
memset (mark, '\0', memory_needed); |
141 |
memset (mark, '\0', memory_needed); |
140 |
stack_used = memory_needed; |
142 |
stack_used += memory_needed; |
141 |
} |
143 |
} |
142 |
else |
144 |
else |
143 |
{ |
145 |
{ |
Lines 156-161
gc (struct database_dyn *db)
Link Here
|
156 |
he = alloca (db->head->nentries * sizeof (struct hashentry *)); |
158 |
he = alloca (db->head->nentries * sizeof (struct hashentry *)); |
157 |
he_data = alloca (db->head->nentries * sizeof (struct hashentry *)); |
159 |
he_data = alloca (db->head->nentries * sizeof (struct hashentry *)); |
158 |
he_use_malloc = false; |
160 |
he_use_malloc = false; |
|
|
161 |
stack_used += memory_needed; |
159 |
} |
162 |
} |
160 |
else |
163 |
else |
161 |
{ |
164 |
{ |
Lines 197-202
gc (struct database_dyn *db)
Link Here
|
197 |
} |
200 |
} |
198 |
assert (cnt == db->head->nentries); |
201 |
assert (cnt == db->head->nentries); |
199 |
|
202 |
|
|
|
203 |
/* Go through the list of in-flight memory blocks. */ |
204 |
struct mem_in_flight *mrunp = mem_in_flight_list; |
205 |
while (mrunp != NULL) |
206 |
{ |
207 |
/* NB: There can be no race between this test and another thread |
208 |
setting the field to the index we are looking for because |
209 |
this would require the other thread to also have the memlock |
210 |
for the database. |
211 |
|
212 |
NB2: we do not have to look at latter blocks (higher indices) if |
213 |
earlier blocks are not in flight. They are always allocated in |
214 |
sequence. */ |
215 |
for (enum in_flight idx = IDX_result_data; |
216 |
idx < IDX_last && mrunp->block[idx].dbidx == db - dbs; ++idx) |
217 |
{ |
218 |
assert (mrunp->block[idx].blockoff >= 0); |
219 |
assert (mrunp->block[idx].blocklen < db->memsize); |
220 |
assert (mrunp->block[idx].blockoff |
221 |
+ mrunp->block[0].blocklen <= db->memsize); |
222 |
markrange (mark, mrunp->block[idx].blockoff, |
223 |
mrunp->block[idx].blocklen); |
224 |
} |
225 |
|
226 |
mrunp = mrunp->next; |
227 |
} |
228 |
|
200 |
/* Sort the entries by the addresses of the referenced data. All |
229 |
/* Sort the entries by the addresses of the referenced data. All |
201 |
the entries pointing to the same DATAHEAD object will have the |
230 |
the entries pointing to the same DATAHEAD object will have the |
202 |
same key. Stability of the sorting is unimportant. */ |
231 |
same key. Stability of the sorting is unimportant. */ |
Lines 206-213
gc (struct database_dyn *db)
Link Here
|
206 |
/* Sort the entries by their address. */ |
235 |
/* Sort the entries by their address. */ |
207 |
qsort (he, cnt, sizeof (struct hashentry *), sort_he); |
236 |
qsort (he, cnt, sizeof (struct hashentry *), sort_he); |
208 |
|
237 |
|
|
|
238 |
#define obstack_chunk_alloc xmalloc |
239 |
#define obstack_chunk_free free |
240 |
struct obstack ob; |
241 |
obstack_init (&ob); |
242 |
|
209 |
/* Determine the highest used address. */ |
243 |
/* Determine the highest used address. */ |
210 |
size_t high = sizeof (mark); |
244 |
size_t high = nmark; |
211 |
while (high > 0 && mark[high - 1] == 0) |
245 |
while (high > 0 && mark[high - 1] == 0) |
212 |
--high; |
246 |
--high; |
213 |
|
247 |
|
Lines 338-345
gc (struct database_dyn *db)
Link Here
|
338 |
displacement. */ |
372 |
displacement. */ |
339 |
ref_t disp = off_alloc - off_free; |
373 |
ref_t disp = off_alloc - off_free; |
340 |
|
374 |
|
341 |
struct moveinfo *new_move |
375 |
struct moveinfo *new_move; |
342 |
= (struct moveinfo *) alloca (sizeof (*new_move)); |
376 |
if (stack_used + sizeof (*new_move) <= MAX_STACK_USE) |
|
|
377 |
{ |
378 |
new_move = alloca (sizeof (*new_move)); |
379 |
stack_used += sizeof (*new_move); |
380 |
} |
381 |
else |
382 |
new_move = obstack_alloc (&ob, sizeof (*new_move)); |
343 |
new_move->from = db->data + off_alloc; |
383 |
new_move->from = db->data + off_alloc; |
344 |
new_move->to = db->data + off_free; |
384 |
new_move->to = db->data + off_free; |
345 |
new_move->size = off_allocend - off_alloc; |
385 |
new_move->size = off_allocend - off_alloc; |
Lines 499-509
gc (struct database_dyn *db)
Link Here
|
499 |
free (he); |
539 |
free (he); |
500 |
if (mark_use_malloc) |
540 |
if (mark_use_malloc) |
501 |
free (mark); |
541 |
free (mark); |
|
|
542 |
|
543 |
obstack_free (&ob, NULL); |
502 |
} |
544 |
} |
503 |
|
545 |
|
504 |
|
546 |
|
505 |
void * |
547 |
void * |
506 |
mempool_alloc (struct database_dyn *db, size_t len) |
548 |
mempool_alloc (struct database_dyn *db, size_t len, enum in_flight idx) |
507 |
{ |
549 |
{ |
508 |
/* Make sure LEN is a multiple of our maximum alignment so we can |
550 |
/* Make sure LEN is a multiple of our maximum alignment so we can |
509 |
keep track of used memory is multiples of this alignment value. */ |
551 |
keep track of used memory is multiples of this alignment value. */ |
Lines 564-572
mempool_alloc (struct database_dyn *db, size_t len)
Link Here
|
564 |
} |
606 |
} |
565 |
else |
607 |
else |
566 |
{ |
608 |
{ |
|
|
609 |
/* Remember that we have allocated this memory. */ |
610 |
assert (idx >= 0 && idx < IDX_last); |
611 |
mem_in_flight.block[idx].dbidx = db - dbs; |
612 |
mem_in_flight.block[idx].blocklen = len; |
613 |
mem_in_flight.block[idx].blockoff = db->head->first_free; |
614 |
|
567 |
db->head->first_free += len; |
615 |
db->head->first_free += len; |
568 |
|
616 |
|
569 |
db->last_alloc_failed = false; |
617 |
db->last_alloc_failed = false; |
|
|
618 |
|
570 |
} |
619 |
} |
571 |
|
620 |
|
572 |
pthread_mutex_unlock (&db->memlock); |
621 |
pthread_mutex_unlock (&db->memlock); |