From 0fb2ddfbd9706f7473c454524ef6d52fd7b93df8 Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Fri, 16 May 2014 12:18:40 +0200 Subject: [PATCH 10/20] libihash: make the locp offset mechanism more flexible libihash allows one to store a location pointer inside the value being stored. This location pointer points to the hash table bucket a value occupies. This allows one to quickly remove the item. Previously, it was only possible to store the location pointer within the value directly. Make it possible to store the location pointer within an object referenced by a pointer stored in the value. This allows one to store e.g. struct node objects as values, while putting the location pointer inside the related struct netnode objects in trans/fakeroot. * libihash/ihash.c (update_locp): New function to update the location pointer. (add_one, hurd_ihash_locp_add): Use the new function. (hurd_ihash_init_indirect, hurd_ihash_create_indirect): New functions. * libihash/ihash.h (struct hurd_ihash): New field locp_indirection_offset. (HURD_IHASH_NO_INDIRECTION, HURD_IHASH_INITIALIZER_INDIRECT): New macros. (hurd_ihash_init_indirect, hurd_ihash_create_indirect): New declarations. --- libihash/ihash.c | 60 ++++++++++++++++++++++++++++++++++++++++++++------------ libihash/ihash.h | 53 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 13 deletions(-) diff --git a/libihash/ihash.c b/libihash/ihash.c index 167c872..c362c8c 100644 --- a/libihash/ihash.c +++ b/libihash/ihash.c @@ -107,6 +107,24 @@ locp_remove (hurd_ihash_t ht, hurd_ihash_locp_t locp) ht->nr_items--; } + +/* If HT uses location pointers, update the location pointer of VALUE + to LOCP. */ +static inline void +update_locp (hurd_ihash_t ht, hurd_ihash_value_t value, + hurd_ihash_locp_t locp) +{ + if (ht->locp_offset != HURD_IHASH_NO_LOCP) + { + char *base; + if (ht->locp_indirection_offset != HURD_IHASH_NO_INDIRECTION) + base = *((char **) ((char *) value + ht->locp_indirection_offset)); + else + base = (char *) value; + *((hurd_ihash_locp_t *) (base + ht->locp_offset)) = locp; + } +} + /* Construction and destruction of hash tables. */ @@ -114,9 +132,21 @@ locp_remove (hurd_ihash_t ht, hurd_ihash_locp_t locp) void hurd_ihash_init (hurd_ihash_t ht, intptr_t locp_offs) { + hurd_ihash_init_indirect (ht, HURD_IHASH_NO_INDIRECTION, locp_offs); +} + + +/* Initialize the hash table at address HT, indirect location pointer + version. */ +void +hurd_ihash_init_indirect (hurd_ihash_t ht, + intptr_t locp_indirection_offset, + intptr_t locp_offset) +{ ht->nr_items = 0; ht->size = 0; - ht->locp_offset = locp_offs; + ht->locp_offset = locp_offset; + ht->locp_indirection_offset = locp_indirection_offset; ht->max_load = HURD_IHASH_MAX_LOAD_DEFAULT; ht->cleanup = 0; } @@ -147,11 +177,25 @@ hurd_ihash_destroy (hurd_ihash_t ht) error_t hurd_ihash_create (hurd_ihash_t *ht, intptr_t locp_offs) { + return hurd_ihash_create_indirect (ht, + HURD_IHASH_NO_INDIRECTION, + locp_offs); +} + + +/* Create a hash table, initialize it and return it in HT, indirect + location pointer version. If a memory allocation error occurs, + ENOMEM is returned, otherwise 0. */ +error_t +hurd_ihash_create_indirect (hurd_ihash_t *ht, + intptr_t locp_indirection_offset, + intptr_t locp_offset) +{ *ht = malloc (sizeof (struct hurd_ihash)); if (*ht == NULL) return ENOMEM; - hurd_ihash_init (*ht, locp_offs); + hurd_ihash_init_indirect (*ht, locp_indirection_offset, locp_offset); return 0; } @@ -247,11 +291,7 @@ add_one (hurd_ihash_t ht, hurd_ihash_key_t key, hurd_ihash_value_t value) ht->nr_items++; ht->items[first_free].value = value; ht->items[first_free].key = key; - - if (ht->locp_offset != HURD_IHASH_NO_LOCP) - *((hurd_ihash_locp_t *) (((char *) value) + ht->locp_offset)) - = &ht->items[first_free].value; - + update_locp (ht, value, &ht->items[first_free].value); return 1; } @@ -297,11 +337,7 @@ hurd_ihash_locp_add (hurd_ihash_t ht, hurd_ihash_locp_t locp, } item->value = value; - - if (ht->locp_offset != HURD_IHASH_NO_LOCP) - *((hurd_ihash_locp_t *) (((char *) value) + ht->locp_offset)) - = locp; - + update_locp (ht, value, locp); return 0; } diff --git a/libihash/ihash.h b/libihash/ihash.h index f7ecf1b..ca253a9 100644 --- a/libihash/ihash.h +++ b/libihash/ihash.h @@ -87,6 +87,11 @@ struct hurd_ihash /* The offset of the location pointer from the hash value. */ intptr_t locp_offset; + /* If the location pointer is not in hash value, but in an object + pointed to by a pointer in hash value, this is the offset of said + pointer in hash value. */ + intptr_t locp_indirection_offset; + /* The maximum load factor in binary percent. */ unsigned int max_load; @@ -112,11 +117,20 @@ typedef struct hurd_ihash *hurd_ihash_t; /* The LOCP_OFFS to use if no location pointer is available. */ #define HURD_IHASH_NO_LOCP INTPTR_MIN +/* The LOCP_INDIRECTION_OFFSET to use if the location pointer is in + the hash value. */ +#define HURD_IHASH_NO_INDIRECTION INTPTR_MIN + /* The static initializer for a struct hurd_ihash. */ #define HURD_IHASH_INITIALIZER(locp_offs) \ + HURD_IHASH_INITIALIZER_INDIRECT (HURD_IHASH_NO_INDIRECTION, (locp_offs)) + +/* The static initializer for a struct hurd_ihash, indirect location + pointer version. */ +#define HURD_IHASH_INITIALIZER_INDIRECT(ind_offs, locp_offs) \ { .nr_items = 0, .size = 0, .cleanup = (hurd_ihash_cleanup_t) 0, \ .max_load = HURD_IHASH_MAX_LOAD_DEFAULT, \ - .locp_offset = (locp_offs)} + .locp_offset = (locp_offs), .locp_indirection_offset = (ind_offs)} /* Initialize the hash table at address HT. If LOCP_OFFSET is not HURD_IHASH_NO_LOCP, then this is an offset (in bytes) from the @@ -125,6 +139,24 @@ typedef struct hurd_ihash *hurd_ihash_t; for fast removal with hurd_ihash_locp_remove(). */ void hurd_ihash_init (hurd_ihash_t ht, intptr_t locp_offs); +/* Initialize the hash table at address HT, indirect location pointer + version. + + If LOCP_OFFSET is not HURD_IHASH_NO_LOCP, then this is an offset + (in bytes) from the address of a hash value where a location + pointer can be found. + + If furthermore LOCP_INDIRECTION_OFFSET is not + HURD_IHASH_NO_INDIRECTION, then this is an offset (in bytes) from + the address of a hash value where a pointer can be found that + points to the object containing the location pointer. + + The location pointer must be of type hurd_ihash_locp_t and can be + used for fast removal with hurd_ihash_locp_remove(). */ +void hurd_ihash_init_indirect (hurd_ihash_t ht, + intptr_t locp_indirection_offset, + intptr_t locp_offset); + /* Destroy the hash table at address HT. This first removes all elements which are still in the hash table, and calling the cleanup function for them (if any). */ @@ -139,6 +171,25 @@ void hurd_ihash_destroy (hurd_ihash_t ht); ENOMEM is returned, otherwise 0. */ error_t hurd_ihash_create (hurd_ihash_t *ht, intptr_t locp_offs); +/* Create a hash table, initialize it and return it in HT, indirect + location pointer version. + + If LOCP_OFFSET is not HURD_IHASH_NO_LOCP, then this is an offset + (in bytes) from the address of a hash value where a location + pointer can be found. + + If furthermore LOCP_INDIRECTION_OFFSET is not + HURD_IHASH_NO_INDIRECTION, then this is an offset (in bytes) from + the address of a hash value where a pointer can be found that + points to the object containing the location pointer. + + The location pointer must be of type hurd_ihash_locp_t and can be + used for fast removal with hurd_ihash_locp_remove(). If a memory + allocation error occurs, ENOMEM is returned, otherwise 0. */ +error_t hurd_ihash_create_indirect (hurd_ihash_t *ht, + intptr_t locp_indirection_offset, + intptr_t locp_offset); + /* Destroy the hash table HT and release the memory allocated for it by hurd_ihash_create(). */ void hurd_ihash_free (hurd_ihash_t ht); -- 2.0.0.rc0