diff mbox

fwts-alloc: garbage collect hash records

Message ID 20170202170200.22407-1-colin.king@canonical.com
State Accepted
Headers show

Commit Message

Colin Ian King Feb. 2, 2017, 5:02 p.m. UTC
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(+)

Comments

Alex Hung Feb. 7, 2017, 3:23 a.m. UTC | #1
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>
Ivan Hu Feb. 8, 2017, 4:32 a.m. UTC | #2
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 mbox

Patch

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();
 }