summaryrefslogtreecommitdiffstats
path: root/src/shared
diff options
context:
space:
mode:
authorMichal Schmidt <mschmidt@redhat.com>2014-08-13 01:00:18 +0200
committerMichal Schmidt <mschmidt@redhat.com>2014-09-15 16:08:50 +0200
commitd5099efc47d4e6ac60816b5381a5f607ab03f06e (patch)
tree661308aae8a0885e90da25874e7df3e795532356 /src/shared
parentbuild: colorize gcc only if on tty (diff)
downloadsystemd-d5099efc47d4e6ac60816b5381a5f607ab03f06e.tar.xz
systemd-d5099efc47d4e6ac60816b5381a5f607ab03f06e.zip
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.c6
-rw-r--r--src/shared/conf-files.c2
-rw-r--r--src/shared/fdset.c2
-rw-r--r--src/shared/hashmap.c42
-rw-r--r--src/shared/hashmap.h18
-rw-r--r--src/shared/install.c8
-rw-r--r--src/shared/locale-util.c2
-rw-r--r--src/shared/logs-show.c2
-rw-r--r--src/shared/set.c8
-rw-r--r--src/shared/set.h4
-rw-r--r--src/shared/util.c6
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;