const struct hashmap_entry *e1, const struct hashmap_entry *e2,
                const void *keydata)
 {
-       return (e1 == e2) || (e1->hash == e2->hash && !map->cmpfn(e1, e2, keydata));
+       return (e1 == e2) ||
+              (e1->hash == e2->hash &&
+               !map->cmpfn(map->cmpfn_data, e1, e2, keydata));
 }
 
 static inline unsigned int bucket(const struct hashmap *map,
        return e;
 }
 
-static int always_equal(const void *unused1, const void *unused2, const void *unused3)
+static int always_equal(const void *unused_cmp_data,
+                       const void *unused1,
+                       const void *unused2,
+                       const void *unused_keydata)
 {
        return 0;
 }
 
 void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
-               size_t initial_size)
+               const void *cmpfn_data, size_t initial_size)
 {
        unsigned int size = HASHMAP_INITIAL_SIZE;
 
        memset(map, 0, sizeof(*map));
 
        map->cmpfn = equals_function ? equals_function : always_equal;
+       map->cmpfn_data = cmpfn_data;
 
        /* calculate initial table size and allocate the table */
        initial_size = (unsigned int) ((uint64_t) initial_size * 100
        unsigned char data[FLEX_ARRAY];
 };
 
-static int pool_entry_cmp(const struct pool_entry *e1,
+static int pool_entry_cmp(const void *unused_cmp_data,
+                         const struct pool_entry *e1,
                          const struct pool_entry *e2,
                          const unsigned char *keydata)
 {
 
        /* initialize string pool hashmap */
        if (!map.tablesize)
-               hashmap_init(&map, (hashmap_cmp_fn) pool_entry_cmp, 0);
+               hashmap_init(&map, (hashmap_cmp_fn) pool_entry_cmp, NULL, 0);
 
        /* lookup interned string in pool */
        hashmap_entry_init(&key, memhash(data, len));