Message ID | 20170202170200.22407-1-colin.king@canonical.com |
---|---|
State | Accepted |
Headers | show |
On 2017-02-03 01:02 AM, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > The hash table that tracks low memory allocations does not > automatically free records when they are not used (instead > it marks them as re-usable which is faster). This patch > adds garbage collection to the hash table when the number > of free'd items drops down to zero. This lazy deferral > allows us to efficiently reap the hash when it is no longer > in use. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/lib/src/fwts_alloc.c | 29 +++++++++++++++++++++++++++++ > 1 file changed, 29 insertions(+) > > diff --git a/src/lib/src/fwts_alloc.c b/src/lib/src/fwts_alloc.c > index 1901a53..2e9b60b 100644 > --- a/src/lib/src/fwts_alloc.c > +++ b/src/lib/src/fwts_alloc.c > @@ -39,6 +39,7 @@ typedef struct hash_alloc { > } hash_alloc_t; > > static hash_alloc_t *hash_allocs[HASH_ALLOC_SIZE]; > +static int hash_count; > > /* > * hash_addr() > @@ -87,6 +88,7 @@ static bool hash_alloc_add(void *addr) > new->addr = addr; > new->next = hash_allocs[h]; > hash_allocs[h] = new; > + hash_count++; > > return true; > } > @@ -104,6 +106,7 @@ static bool hash_alloc_remove(const void *addr) > while (ha) { > if (ha->addr == addr) { > /* Just nullify it */ > + hash_count--; > ha->addr = NULL; > return true; > } > @@ -113,6 +116,30 @@ static bool hash_alloc_remove(const void *addr) > } > > /* > + * hash_alloc_garbage_collect() > + * free all hash records when the hash > + * is empty. > + */ > +static void hash_alloc_garbage_collect(void) > +{ > + size_t i; > + > + if (hash_count) > + return; > + > + for (i = 0; i < HASH_ALLOC_SIZE; i++) { > + hash_alloc_t *ha = hash_allocs[i]; > + > + while (ha) { > + hash_alloc_t *next = ha->next; > + > + free(ha); > + ha = next; > + } > + } > +} > + > +/* > * We implement a low memory allocator to allow us to allocate > * memory < 2G limit for the ACPICA table handling. On 64 bit > * machines we have to ensure that cached copies of ACPI tables > @@ -406,4 +433,6 @@ void fwts_low_free(const void *ptr) > /* Be doubly sure by checking magic before we munmap */ > if (hdr->magic == FWTS_ALLOC_MAGIC) > munmap(hdr, hdr->size); > + > + hash_alloc_garbage_collect(); > } > Acked-by: Alex Hung <alex.hung@canonical.com>
On 2017年02月03日 01:02, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > The hash table that tracks low memory allocations does not > automatically free records when they are not used (instead > it marks them as re-usable which is faster). This patch > adds garbage collection to the hash table when the number > of free'd items drops down to zero. This lazy deferral > allows us to efficiently reap the hash when it is no longer > in use. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/lib/src/fwts_alloc.c | 29 +++++++++++++++++++++++++++++ > 1 file changed, 29 insertions(+) > > diff --git a/src/lib/src/fwts_alloc.c b/src/lib/src/fwts_alloc.c > index 1901a53..2e9b60b 100644 > --- a/src/lib/src/fwts_alloc.c > +++ b/src/lib/src/fwts_alloc.c > @@ -39,6 +39,7 @@ typedef struct hash_alloc { > } hash_alloc_t; > > static hash_alloc_t *hash_allocs[HASH_ALLOC_SIZE]; > +static int hash_count; > > /* > * hash_addr() > @@ -87,6 +88,7 @@ static bool hash_alloc_add(void *addr) > new->addr = addr; > new->next = hash_allocs[h]; > hash_allocs[h] = new; > + hash_count++; > > return true; > } > @@ -104,6 +106,7 @@ static bool hash_alloc_remove(const void *addr) > while (ha) { > if (ha->addr == addr) { > /* Just nullify it */ > + hash_count--; > ha->addr = NULL; > return true; > } > @@ -113,6 +116,30 @@ static bool hash_alloc_remove(const void *addr) > } > > /* > + * hash_alloc_garbage_collect() > + * free all hash records when the hash > + * is empty. > + */ > +static void hash_alloc_garbage_collect(void) > +{ > + size_t i; > + > + if (hash_count) > + return; > + > + for (i = 0; i < HASH_ALLOC_SIZE; i++) { > + hash_alloc_t *ha = hash_allocs[i]; > + > + while (ha) { > + hash_alloc_t *next = ha->next; > + > + free(ha); > + ha = next; > + } > + } > +} > + > +/* > * We implement a low memory allocator to allow us to allocate > * memory < 2G limit for the ACPICA table handling. On 64 bit > * machines we have to ensure that cached copies of ACPI tables > @@ -406,4 +433,6 @@ void fwts_low_free(const void *ptr) > /* Be doubly sure by checking magic before we munmap */ > if (hdr->magic == FWTS_ALLOC_MAGIC) > munmap(hdr, hdr->size); > + > + hash_alloc_garbage_collect(); > } > Acked-by: Ivan Hu <ivan.hu@canonical.com>
diff --git a/src/lib/src/fwts_alloc.c b/src/lib/src/fwts_alloc.c index 1901a53..2e9b60b 100644 --- a/src/lib/src/fwts_alloc.c +++ b/src/lib/src/fwts_alloc.c @@ -39,6 +39,7 @@ typedef struct hash_alloc { } hash_alloc_t; static hash_alloc_t *hash_allocs[HASH_ALLOC_SIZE]; +static int hash_count; /* * hash_addr() @@ -87,6 +88,7 @@ static bool hash_alloc_add(void *addr) new->addr = addr; new->next = hash_allocs[h]; hash_allocs[h] = new; + hash_count++; return true; } @@ -104,6 +106,7 @@ static bool hash_alloc_remove(const void *addr) while (ha) { if (ha->addr == addr) { /* Just nullify it */ + hash_count--; ha->addr = NULL; return true; } @@ -113,6 +116,30 @@ static bool hash_alloc_remove(const void *addr) } /* + * hash_alloc_garbage_collect() + * free all hash records when the hash + * is empty. + */ +static void hash_alloc_garbage_collect(void) +{ + size_t i; + + if (hash_count) + return; + + for (i = 0; i < HASH_ALLOC_SIZE; i++) { + hash_alloc_t *ha = hash_allocs[i]; + + while (ha) { + hash_alloc_t *next = ha->next; + + free(ha); + ha = next; + } + } +} + +/* * We implement a low memory allocator to allow us to allocate * memory < 2G limit for the ACPICA table handling. On 64 bit * machines we have to ensure that cached copies of ACPI tables @@ -406,4 +433,6 @@ void fwts_low_free(const void *ptr) /* Be doubly sure by checking magic before we munmap */ if (hdr->magic == FWTS_ALLOC_MAGIC) munmap(hdr, hdr->size); + + hash_alloc_garbage_collect(); }