diff options
author | Michal Schmidt <mschmidt@redhat.com> | 2014-08-13 01:00:18 +0200 |
---|---|---|
committer | Michal Schmidt <mschmidt@redhat.com> | 2014-09-15 16:08:50 +0200 |
commit | d5099efc47d4e6ac60816b5381a5f607ab03f06e (patch) | |
tree | 661308aae8a0885e90da25874e7df3e795532356 /src/shared | |
parent | f44541bc934c6e2b02155559e9eeb17a13a09558 (diff) |
hashmap: introduce hash_ops to make struct Hashmap smaller
It is redundant to store 'hash' and 'compare' function pointers in
struct Hashmap separately. The functions always comprise a pair.
Store a single pointer to struct hash_ops instead.
systemd keeps hundreds of hashmaps, so this saves a little bit of
memory.
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/cgroup-util.c | 6 | ||||
-rw-r--r-- | src/shared/conf-files.c | 2 | ||||
-rw-r--r-- | src/shared/fdset.c | 2 | ||||
-rw-r--r-- | src/shared/hashmap.c | 42 | ||||
-rw-r--r-- | src/shared/hashmap.h | 18 | ||||
-rw-r--r-- | src/shared/install.c | 8 | ||||
-rw-r--r-- | src/shared/locale-util.c | 2 | ||||
-rw-r--r-- | src/shared/logs-show.c | 2 | ||||
-rw-r--r-- | src/shared/set.c | 8 | ||||
-rw-r--r-- | src/shared/set.h | 4 | ||||
-rw-r--r-- | src/shared/util.c | 6 |
11 files changed, 65 insertions, 35 deletions
diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 00eac64236..da8e885226 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -161,7 +161,7 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo * tasks list, to properly handle forking processes */ if (!s) { - s = allocated_set = set_new(trivial_hash_func, trivial_compare_func); + s = allocated_set = set_new(NULL); if (!s) return -ENOMEM; } @@ -239,7 +239,7 @@ int cg_kill_recursive(const char *controller, const char *path, int sig, bool si assert(sig >= 0); if (!s) { - s = allocated_set = set_new(trivial_hash_func, trivial_compare_func); + s = allocated_set = set_new(NULL); if (!s) return -ENOMEM; } @@ -290,7 +290,7 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char assert(cto); assert(pto); - s = set_new(trivial_hash_func, trivial_compare_func); + s = set_new(NULL); if (!s) return -ENOMEM; diff --git a/src/shared/conf-files.c b/src/shared/conf-files.c index c72a099b5a..e6ee97a978 100644 --- a/src/shared/conf-files.c +++ b/src/shared/conf-files.c @@ -109,7 +109,7 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const if (!path_strv_resolve_uniq(dirs, root)) return -ENOMEM; - fh = hashmap_new(string_hash_func, string_compare_func); + fh = hashmap_new(&string_hash_ops); if (!fh) return -ENOMEM; diff --git a/src/shared/fdset.c b/src/shared/fdset.c index d2ea665016..37cbd8526c 100644 --- a/src/shared/fdset.c +++ b/src/shared/fdset.c @@ -38,7 +38,7 @@ #define PTR_TO_FD(p) (PTR_TO_INT(p)-1) FDSet *fdset_new(void) { - return MAKE_FDSET(set_new(trivial_hash_func, trivial_compare_func)); + return MAKE_FDSET(set_new(NULL)); } void fdset_free(FDSet *s) { diff --git a/src/shared/hashmap.c b/src/shared/hashmap.c index dbf91c439e..715484ce7c 100644 --- a/src/shared/hashmap.c +++ b/src/shared/hashmap.c @@ -39,8 +39,7 @@ struct hashmap_entry { }; struct Hashmap { - hash_func_t hash_func; - compare_func_t compare_func; + const struct hash_ops *hash_ops; struct hashmap_entry *iterate_list_head, *iterate_list_tail; @@ -141,6 +140,11 @@ int string_compare_func(const void *a, const void *b) { return strcmp(a, b); } +const struct hash_ops string_hash_ops = { + .hash = string_hash_func, + .compare = string_compare_func +}; + unsigned long trivial_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) { uint64_t u; siphash24((uint8_t*) &u, &p, sizeof(p), hash_key); @@ -151,6 +155,11 @@ int trivial_compare_func(const void *a, const void *b) { return a < b ? -1 : (a > b ? 1 : 0); } +const struct hash_ops trivial_hash_ops = { + .hash = trivial_hash_func, + .compare = trivial_compare_func +}; + unsigned long uint64_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) { uint64_t u; siphash24((uint8_t*) &u, p, sizeof(uint64_t), hash_key); @@ -164,6 +173,11 @@ int uint64_compare_func(const void *_a, const void *_b) { return a < b ? -1 : (a > b ? 1 : 0); } +const struct hash_ops uint64_hash_ops = { + .hash = uint64_hash_func, + .compare = uint64_compare_func +}; + #if SIZEOF_DEV_T != 8 unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) { uint64_t u; @@ -177,10 +191,15 @@ int devt_compare_func(const void *_a, const void *_b) { b = *(const dev_t*) _b; return a < b ? -1 : (a > b ? 1 : 0); } + +const struct hash_ops devt_hash_ops = { + .hash = devt_hash_func, + .compare = devt_compare_func +}; #endif static unsigned bucket_hash(Hashmap *h, const void *p) { - return (unsigned) (h->hash_func(p, h->hash_key) % h->n_buckets); + return (unsigned) (h->hash_ops->hash(p, h->hash_key) % h->n_buckets); } static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { @@ -202,7 +221,7 @@ static void get_hash_key(uint8_t hash_key[HASH_KEY_SIZE], bool reuse_is_ok) { memcpy(hash_key, current, sizeof(current)); } -Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { +Hashmap *hashmap_new(const struct hash_ops *hash_ops) { bool b; Hashmap *h; size_t size; @@ -224,8 +243,7 @@ Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { return NULL; } - h->hash_func = hash_func ? hash_func : trivial_hash_func; - h->compare_func = compare_func ? compare_func : trivial_compare_func; + h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops; h->n_buckets = INITIAL_N_BUCKETS; h->n_entries = 0; @@ -240,7 +258,7 @@ Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func) { return h; } -int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func) { +int hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops) { Hashmap *q; assert(h); @@ -248,7 +266,7 @@ int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t if (*h) return 0; - q = hashmap_new(hash_func, compare_func); + q = hashmap_new(hash_ops); if (!q) return -ENOMEM; @@ -406,7 +424,7 @@ static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *ke assert(hash < h->n_buckets); for (e = h->buckets[hash]; e; e = e->bucket_next) - if (h->compare_func(e->key, key) == 0) + if (h->hash_ops->compare(e->key, key) == 0) return e; return NULL; @@ -438,7 +456,7 @@ static bool resize_buckets(Hashmap *h) { for (i = h->iterate_list_head; i; i = i->iterate_next) { unsigned long old_bucket, new_bucket; - old_bucket = h->hash_func(i->key, h->hash_key) % h->n_buckets; + old_bucket = h->hash_ops->hash(i->key, h->hash_key) % h->n_buckets; /* First, drop from old bucket table */ if (i->bucket_next) @@ -450,7 +468,7 @@ static bool resize_buckets(Hashmap *h) { h->buckets[old_bucket] = i->bucket_next; /* Then, add to new backet table */ - new_bucket = h->hash_func(i->key, nkey) % m; + new_bucket = h->hash_ops->hash(i->key, nkey) % m; i->bucket_next = n[new_bucket]; i->bucket_previous = NULL; @@ -949,7 +967,7 @@ Hashmap *hashmap_copy(Hashmap *h) { assert(h); - copy = hashmap_new(h->hash_func, h->compare_func); + copy = hashmap_new(h->hash_ops); if (!copy) return NULL; diff --git a/src/shared/hashmap.h b/src/shared/hashmap.h index f89e7e8fbc..7385ebc5fa 100644 --- a/src/shared/hashmap.h +++ b/src/shared/hashmap.h @@ -43,38 +43,50 @@ typedef _IteratorStruct* Iterator; typedef unsigned long (*hash_func_t)(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]); typedef int (*compare_func_t)(const void *a, const void *b); +struct hash_ops { + hash_func_t hash; + compare_func_t compare; +}; + unsigned long string_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_; int string_compare_func(const void *a, const void *b) _pure_; +extern const struct hash_ops string_hash_ops; /* This will compare the passed pointers directly, and will not * dereference them. This is hence not useful for strings or * suchlike. */ unsigned long trivial_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_; int trivial_compare_func(const void *a, const void *b) _const_; +extern const struct hash_ops trivial_hash_ops; /* 32bit values we can always just embedd in the pointer itself, but * in order to support 32bit archs we need store 64bit values * indirectly, since they don't fit in a pointer. */ unsigned long uint64_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_; int uint64_compare_func(const void *a, const void *b) _pure_; +extern const struct hash_ops uint64_hash_ops; /* On some archs dev_t is 32bit, and on others 64bit. And sometimes * it's 64bit on 32bit archs, and sometimes 32bit on 64bit archs. Yuck! */ #if SIZEOF_DEV_T != 8 unsigned long devt_hash_func(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]) _pure_; int devt_compare_func(const void *a, const void *b) _pure_; +extern const struct hash_ops devt_hash_ops = { + .hash = devt_hash_func, + .compare = devt_compare_func +}; #else -/* No need to define a second version of this... */ #define devt_hash_func uint64_hash_func #define devt_compare_func uint64_compare_func +#define devt_hash_ops uint64_hash_ops #endif -Hashmap *hashmap_new(hash_func_t hash_func, compare_func_t compare_func); +Hashmap *hashmap_new(const struct hash_ops *hash_ops); void hashmap_free(Hashmap *h); void hashmap_free_free(Hashmap *h); void hashmap_free_free_free(Hashmap *h); Hashmap *hashmap_copy(Hashmap *h); -int hashmap_ensure_allocated(Hashmap **h, hash_func_t hash_func, compare_func_t compare_func); +int hashmap_ensure_allocated(Hashmap **h, const struct hash_ops *hash_ops); int hashmap_put(Hashmap *h, const void *key, void *value); int hashmap_update(Hashmap *h, const void *key, void *value); diff --git a/src/shared/install.c b/src/shared/install.c index 3ef995a928..5d3fcf5e32 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -179,7 +179,7 @@ static int mark_symlink_for_removal( assert(p); - r = set_ensure_allocated(remove_symlinks_to, string_hash_func, string_compare_func); + r = set_ensure_allocated(remove_symlinks_to, &string_hash_ops); if (r < 0) return r; @@ -884,7 +884,7 @@ static int install_info_add( hashmap_get(c->will_install, name)) return 0; - r = hashmap_ensure_allocated(&c->will_install, string_hash_func, string_compare_func); + r = hashmap_ensure_allocated(&c->will_install, &string_hash_ops); if (r < 0) return r; @@ -1393,7 +1393,7 @@ static int install_context_apply( while ((i = hashmap_first(c->will_install))) { - q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func); + q = hashmap_ensure_allocated(&c->have_installed, &string_hash_ops); if (q < 0) return q; @@ -1434,7 +1434,7 @@ static int install_context_mark_for_removal( while ((i = hashmap_first(c->will_install))) { - q = hashmap_ensure_allocated(&c->have_installed, string_hash_func, string_compare_func); + q = hashmap_ensure_allocated(&c->have_installed, &string_hash_ops); if (q < 0) return q; diff --git a/src/shared/locale-util.c b/src/shared/locale-util.c index 8d2c363036..68851ae13d 100644 --- a/src/shared/locale-util.c +++ b/src/shared/locale-util.c @@ -160,7 +160,7 @@ int get_locales(char ***ret) { _cleanup_strv_free_ char **l = NULL; int r; - locales = set_new(string_hash_func, string_compare_func); + locales = set_new(&string_hash_ops); if (!locales) return -ENOMEM; diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 5538dd3b9e..5a7bbaf03a 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -695,7 +695,7 @@ static int output_json( sd_id128_to_string(boot_id, sid)); } - h = hashmap_new(string_hash_func, string_compare_func); + h = hashmap_new(&string_hash_ops); if (!h) return -ENOMEM; diff --git a/src/shared/set.c b/src/shared/set.c index 02ea831593..d4ffe056d5 100644 --- a/src/shared/set.c +++ b/src/shared/set.c @@ -30,8 +30,8 @@ /* For now this is not much more than a wrapper around a hashmap */ -Set *set_new(hash_func_t hash_func, compare_func_t compare_func) { - return MAKE_SET(hashmap_new(hash_func, compare_func)); +Set *set_new(const struct hash_ops *hash_ops) { + return MAKE_SET(hashmap_new(hash_ops)); } void set_free(Set* s) { @@ -42,8 +42,8 @@ void set_free_free(Set *s) { hashmap_free_free(MAKE_HASHMAP(s)); } -int set_ensure_allocated(Set **s, hash_func_t hash_func, compare_func_t compare_func) { - return hashmap_ensure_allocated((Hashmap**) s, hash_func, compare_func); +int set_ensure_allocated(Set **s, const struct hash_ops *hash_ops) { + return hashmap_ensure_allocated((Hashmap**) s, hash_ops); } int set_put(Set *s, void *value) { diff --git a/src/shared/set.h b/src/shared/set.h index e0b9c9e0a8..e650b7e3fe 100644 --- a/src/shared/set.h +++ b/src/shared/set.h @@ -32,12 +32,12 @@ typedef struct Set Set; -Set *set_new(hash_func_t hash_func, compare_func_t compare_func); +Set *set_new(const struct hash_ops *hash_ops); void set_free(Set* s); void set_free_free(Set *s); Set* set_copy(Set *s); -int set_ensure_allocated(Set **s, hash_func_t hash_func, compare_func_t compare_func); +int set_ensure_allocated(Set **s, const struct hash_ops *hash_ops); int set_put(Set *s, void *value); int set_consume(Set *s, void *value); diff --git a/src/shared/util.c b/src/shared/util.c index 502b3675b1..61d6680ddd 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -3911,7 +3911,7 @@ void execute_directory(const char *directory, DIR *d, usec_t timeout, char *argv } } - pids = hashmap_new(NULL, NULL); + pids = hashmap_new(NULL); if (!pids) { log_oom(); _exit(EXIT_FAILURE); @@ -6694,7 +6694,7 @@ int bind_remount_recursive(const char *prefix, bool ro) { path_kill_slashes(cleaned); - done = set_new(string_hash_func, string_compare_func); + done = set_new(&string_hash_ops); if (!done) return -ENOMEM; @@ -6704,7 +6704,7 @@ int bind_remount_recursive(const char *prefix, bool ro) { bool top_autofs = false; char *x; - todo = set_new(string_hash_func, string_compare_func); + todo = set_new(&string_hash_ops); if (!todo) return -ENOMEM; |