--- /dev/null
+/* -*- linux-c -*-
+ * map API generator
+ * Copyright (C) 2005 Red Hat Inc.
+ *
+ * This file is part of systemtap, and is free software. You can
+ * redistribute it and/or modify it under the terms of the GNU General
+ * Public License (GPL); either version 2, or (at your option) any
+ * later version.
+ */
+
+/** @file map-gen.c
+ * @brief Map function generator
+ * This file is a template designed to be included as many times as
+ * needed to generate the necessary map functions.
+ */
+
+#define JOIN(x,y) JOINx(x,y)
+#define JOINx(x,y) x##_##y
+#define JOIN2(x,y,z) JOIN2x(x,y,z)
+#define JOIN2x(x,y,z) x##_##y##z
+#define JOIN3(a,b,c,d) JOIN3x(a,b,c,d)
+#define JOIN3x(a,b,c,d) a##_##b##c##d
+#define JOIN4(a,b,c,d,e) JOIN4x(a,b,c,d,e)
+#define JOIN4x(a,b,c,d,e) a##_##b##c##d##e
+#define JOIN5(a,b,c,d,e,f) JOIN5x(a,b,c,d,e,f)
+#define JOIN5x(a,b,c,d,e,f) a##_##b##c##d##e##f
+#define JOIN6(a,b,c,d,e,f,g) JOIN6x(a,b,c,d,e,f,g)
+#define JOIN6x(a,b,c,d,e,f,g) a##_##b##c##d##e##f##g
+
+#include "map.h"
+
+#if !defined(VALUE_TYPE)
+#error Need to define VALUE_TYPE as STRING, STAT, or INT64
+#endif
+
+#if VALUE_TYPE == STRING
+#define VALTYPE char*
+#define VSTYPE char*
+#define VALNAME str
+#define VALN s
+#define MAP_SET_VAL(a,b,c,d) _new_map_set_str(a,b,c,d)
+#define MAP_GET_VAL(a,b) _new_map_get_str(a,b)
+#elif VALUE_TYPE == INT64
+#define VALTYPE int64_t
+#define VSTYPE int64_t
+#define VALNAME int64
+#define VALN i
+#define MAP_SET_VAL(a,b,c,d) _new_map_set_int64(a,b,c,d)
+#define MAP_GET_VAL(a,b) _new_map_get_int64(a,b)
+#elif VALUE_TYPE == STAT
+#define VALTYPE stat*
+#define VSTYPE int64_t
+#define VALNAME stat
+#define VALN x
+#define MAP_SET_VAL(a,b,c,d) _new_map_set_stat(a,b,c,d)
+#define MAP_GET_VAL(a,b) _new_map_get_stat(a,b)
+#else
+#error Need to define VALUE_TYPE as STRING, STAT, or INT64
+#endif /* VALUE_TYPE */
+
+//#define MAP_SET_VAL(a,b,c,d) _new_map_set_##VALNAME(a,b,c,d)
+
+#if defined (KEY1_TYPE)
+#define KEY_ARITY 1
+#if KEY1_TYPE == STRING
+#define KEY1TYPE char*
+#define KEY1NAME str
+#define KEY1N s
+#define KEY1STOR char key1[MAP_STRING_LENGTH]
+#define KEY1CPY(m) str_copy(m->key1, key1)
+#else
+#define KEY1TYPE int64_t
+#define KEY1NAME int64
+#define KEY1N i
+#define KEY1STOR int64_t key1
+#define KEY1CPY(m) m->key1=key1
+#endif
+#define KEY1_EQ_P JOIN(KEY1NAME,eq_p)
+#define KEY1_HASH JOIN(KEY1NAME,hash)
+#endif /* defined(KEY1_TYPE) */
+
+#if defined (KEY2_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 2
+#if KEY2_TYPE == STRING
+#define KEY2TYPE char*
+#define KEY2NAME str
+#define KEY2N s
+#define KEY2STOR char key2[MAP_STRING_LENGTH]
+#define KEY2CPY(m) str_copy(m->key2, key2)
+#else
+#define KEY2TYPE int64_t
+#define KEY2NAME int64
+#define KEY2N i
+#define KEY2STOR int64_t key2
+#define KEY2CPY(m) m->key2=key2
+#endif
+#define KEY2_EQ_P JOIN(KEY2NAME,eq_p)
+#define KEY2_HASH JOIN(KEY2NAME,hash)
+#endif /* defined(KEY2_TYPE) */
+
+#if defined (KEY3_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 3
+#if KEY3_TYPE == STRING
+#define KEY3TYPE char*
+#define KEY3NAME str
+#define KEY3N s
+#define KEY3STOR char key3[MAP_STRING_LENGTH]
+#define KEY3CPY(m) str_copy(m->key3, key3)
+#else
+#define KEY3TYPE int64_t
+#define KEY3NAME int64
+#define KEY3N i
+#define KEY3STOR int64_t key3
+#define KEY3CPY(m) m->key3=key3
+#endif
+#define KEY3_EQ_P JOIN(KEY3NAME,eq_p)
+#define KEY3_HASH JOIN(KEY3NAME,hash)
+#endif /* defined(KEY3_TYPE) */
+
+#if defined (KEY4_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 4
+#if KEY4_TYPE == STRING
+#define KEY4TYPE char*
+#define KEY4NAME str
+#define KEY4N s
+#define KEY4STOR char key4[MAP_STRING_LENGTH]
+#define KEY4CPY(m) str_copy(m->key4, key4)
+#else
+#define KEY4TYPE int64_t
+#define KEY4NAME int64
+#define KEY4N i
+#define KEY4STOR int64_t key4
+#define KEY4CPY(4) m->key4=key4
+#endif
+#define KEY4_EQ_P JOIN(KEY4NAME,eq_p)
+#define KEY4_HASH JOIN(KEY4NAME,hash)
+#endif /* defined(KEY4_TYPE) */
+
+#if defined (KEY5_TYPE)
+#undef KEY_ARITY
+#define KEY_ARITY 5
+#if KEY5_TYPE == STRING
+#define KEY5TYPE char*
+#define KEY5NAME str
+#define KEY5N s
+#define KEY5STOR char key5[MAP_STRING_LENGTH]
+#define KEY5CPY(m) str_copy(m->key5, key5)
+#else
+#define KEY5TYPE int64_t
+#define KEY5NAME int64
+#define KEY5N i
+#define KEY5STOR int64_t key5
+#define KEY5CPY(m) m->key5=key5
+#endif
+#define KEY5_EQ_P JOIN(KEY5NAME,eq_p)
+#define KEY5_HASH JOIN(KEY5NAME,hash)
+#endif /* defined(KEY5_TYPE) */
+
+#if KEY_ARITY == 1
+#define KEYSYM(x) JOIN2(x,KEY1N,VALN)
+#define ALLKEYS(x) x##1
+#define ALLKEYSD(x) KEY1TYPE x##1
+#define KEYCPY(m) {KEY1CPY(m);}
+#elif KEY_ARITY == 2
+#define KEYSYM(x) JOIN3(x,KEY1N,KEY2N,VALN)
+#define ALLKEYS(x) x##1, x##2
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);}
+#elif KEY_ARITY == 3
+#define KEYSYM(x) JOIN4(x,KEY1N,KEY2N,KEY3N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);}
+#elif KEY_ARITY == 4
+#define KEYSYM(x) JOIN5(x,KEY1N,KEY2N,KEY3N,KEY4N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m)}
+#elif KEY_ARITY == 5
+#define KEYSYM(x) JOIN6(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,VALN)
+#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5
+#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5
+#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);}
+#endif
+
+/* */
+
+struct KEYSYM(map_node) {
+ /* list of other nodes in the map */
+ struct list_head lnode;
+ /* list of nodes with the same hash value */
+ struct hlist_node hnode;
+ /* pointer back to the map struct */
+ struct map_root *map;
+
+ KEY1STOR;
+#if KEY_ARITY > 1
+ KEY2STOR;
+#if KEY_ARITY > 2
+ KEY3STOR;
+#if KEY_ARITY > 3
+ KEY4STOR;
+#if KEY_ARITY > 4
+ KEY5STOR;
+#endif
+#endif
+#endif
+#endif
+};
+
+#define type_to_enum(type) \
+ ({ \
+ int ret; \
+ if (__builtin_types_compatible_p (type, char*)) \
+ ret = STRING; \
+ else \
+ ret = INT64; \
+ ret; \
+ })
+
+static key_data KEYSYM(map_get_key) (struct map_node *mn, int n, int *type)
+{
+ key_data ptr;
+ struct KEYSYM(map_node) *m = (struct KEYSYM(map_node) *)mn;
+
+ // dbug ("m=%lx\n", (long)m);
+ if (n > KEY_ARITY || n < 1) {
+ if (type)
+ *type = END;
+ return (key_data)(int64_t)0;
+ }
+
+ switch (n) {
+ case 1:
+ ptr = (key_data)m->key1;
+ if (type)
+ *type = type_to_enum(KEY1TYPE);
+ break;
+#if KEY_ARITY > 1
+ case 2:
+ ptr = (key_data)m->key2;
+ if (type)
+ *type = type_to_enum(KEY2TYPE);
+
+ break;
+#if KEY_ARITY > 2
+ case 3:
+ ptr = (key_data)m->key3;
+ if (type)
+ *type = type_to_enum(KEY3TYPE);
+ break;
+#if KEY_ARITY > 3
+ case 4:
+ ptr = (key_data)m->key4;
+ if (type)
+ *type = type_to_enum(KEY4TYPE);
+ break;
+#if KEY_ARITY > 4
+ case 5:
+ ptr = (key_data)m->key5;
+ if (type)
+ *type = type_to_enum(KEY5TYPE);
+ break;
+#endif
+#endif
+#endif
+#endif
+ default:
+ ptr = (key_data)(int64_t)0;
+ if (type)
+ *type = END;
+ }
+ return ptr;
+}
+
+
+static unsigned int KEYSYM(keycheck) (ALLKEYSD(key))
+{
+#if KEY1_TYPE == STRING
+ if (key1 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 1
+#if KEY2_TYPE == STRING
+ if (key2 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 2
+#if KEY3_TYPE == STRING
+ if (key3 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 3
+#if KEY4_TYPE == STRING
+ if (key4 == NULL)
+ return 0;
+#endif
+
+#if KEY_ARITY > 4
+#if KEY5_TYPE == STRING
+ if (key5 == NULL)
+ return 0;
+#endif
+#endif
+#endif
+#endif
+#endif
+ return 1;
+}
+
+static unsigned int KEYSYM(hash) (ALLKEYSD(key))
+{
+ unsigned int hash = KEY1_HASH(key1);
+#if KEY_ARITY > 1
+ hash ^= KEY2_HASH(key2);
+#if KEY_ARITY > 2
+ hash ^= KEY3_HASH(key3);
+#if KEY_ARITY > 3
+ hash ^= KEY4_HASH(key4);
+#if KEY_ARITY > 4
+ hash ^= KEY5_HASH(key5);
+#endif
+#endif
+#endif
+#endif
+ return (unsigned int) hash;
+}
+
+
+#if VALUE_TYPE == INT64
+MAP KEYSYM(_stp_map_new) (unsigned max_entries)
+{
+ MAP m = _stp_map_new (max_entries, INT64, sizeof(struct KEYSYM(map_node)), 0);
+ if (m)
+ m->get_key = KEYSYM(map_get_key);
+ return m;
+}
+#elif VALUE_TYPE == STRING
+MAP KEYSYM(_stp_map_new) (unsigned max_entries)
+{
+ MAP m = _stp_map_new (max_entries, STRING, sizeof(struct KEYSYM(map_node)), 0);
+ if (m)
+ m->get_key = KEYSYM(map_get_key);
+ return m;
+}
+#else
+/* _stp_map_new_key1_key2...val (num, HSTAT_LINEAR, start, end, interval) */
+/* _stp_map_new_key1_key2...val (num, HSTAT_LOG, buckets) */
+
+MAP KEYSYM(_stp_map_new) (unsigned max_entries, int htype, ...)
+{
+ int buckets=0, start=0, stop=0, interval=0;
+ MAP m;
+ va_list ap;
+
+ if (htype != HIST_NONE) {
+ va_start (ap, htype);
+ if (htype == HIST_LOG) {
+ buckets = va_arg(ap, int);
+ // dbug ("buckets=%d\n", buckets);
+ } else {
+ start = va_arg(ap, int);
+ stop = va_arg(ap, int);
+ interval = va_arg(ap, int);
+ // dbug ("start=%d stop=%d interval=%d\n", start, stop, interval);
+ }
+ va_end (ap);
+ }
+
+ switch (htype) {
+ case HIST_NONE:
+ m = _stp_map_new (max_entries, STAT, sizeof(struct KEYSYM(map_node)), 0);
+ break;
+ case HIST_LOG:
+ m = _stp_map_new_hstat_log (max_entries, sizeof(struct KEYSYM(map_node)),
+ buckets);
+ break;
+ case HIST_LINEAR:
+ m = _stp_map_new_hstat_linear (max_entries, sizeof(struct KEYSYM(map_node)),
+ start, stop, interval);
+ break;
+ default:
+ _stp_warn ("Unknown histogram type %d\n", htype);
+ m = NULL;
+ }
+
+ if (m)
+ m->get_key = KEYSYM(map_get_key);
+
+ return m;
+}
+
+#endif /* VALUE_TYPE */
+int KEYSYM(__stp_map_set) (MAP map, ALLKEYSD(key), VSTYPE val, int add)
+{
+ unsigned int hv;
+ struct hlist_head *head;
+ struct hlist_node *e;
+ struct KEYSYM(map_node) *n;
+ int res;
+
+ if (map == NULL)
+ return -2;
+
+ if (KEYSYM(keycheck) (ALLKEYS(key)) == 0)
+ return -2;
+
+ hv = KEYSYM(hash) (ALLKEYS(key));
+ head = &map->hashes[hv];
+
+ hlist_for_each(e, head) {
+ n = (struct KEYSYM(map_node) *)((long)e - sizeof(struct hlist_node));
+ dbug ("n=%lx key1=%ld n->key1=%ld\n", (long)n, key1, n->key1);
+ if (KEY1_EQ_P(n->key1, key1)
+#if KEY_ARITY > 1
+ && KEY2_EQ_P(n->key2, key2)
+#if KEY_ARITY > 2
+ && KEY3_EQ_P(n->key3, key3)
+#if KEY_ARITY > 3
+ && KEY4_EQ_P(n->key4, key4)
+#if KEY_ARITY > 4
+ && KEY5_EQ_P(n->key5, key5)
+#endif
+#endif
+#endif
+#endif
+ ) {
+#if VALUE_TYPE == STAT
+ return _new_map_set_stat(map,(struct map_node *)n, val, add, 0);
+#else
+ return MAP_SET_VAL(map,(struct map_node *)n, val, add);
+#endif
+ }
+ }
+ /* key not found */
+ dbug("key not found\n");
+ if (val == 0 && !add)
+ return 0;
+ n = (struct KEYSYM(map_node)*)_new_map_create (map, head);
+ if (n == NULL)
+ return -1;
+ dbug("keycpy\n");
+ KEYCPY(n);
+ dbug("done\n");
+#if VALUE_TYPE == STAT
+ return _new_map_set_stat(map,(struct map_node *)n, val, add, 1);
+#else
+ return MAP_SET_VAL(map,(struct map_node *)n, val, 0);
+#endif
+}
+
+int KEYSYM(_stp_map_set) (MAP map, ALLKEYSD(key), VSTYPE val)
+{
+ return KEYSYM(__stp_map_set) (map, ALLKEYS(key), val, 0);
+}
+
+int KEYSYM(_stp_map_add) (MAP map, ALLKEYSD(key), VSTYPE val)
+{
+ return KEYSYM(__stp_map_set) (map, ALLKEYS(key), val, 1);
+}
+
+
+VALTYPE KEYSYM(_stp_map_get) (MAP map, ALLKEYSD(key))
+{
+ unsigned int hv;
+ struct hlist_head *head;
+ struct hlist_node *e;
+ struct KEYSYM(map_node) *n;
+
+ if (map == NULL)
+ return (VALTYPE)0;
+
+ hv = KEYSYM(hash) (ALLKEYS(key));
+ head = &map->hashes[hv];
+
+ hlist_for_each(e, head) {
+ n = (struct KEYSYM(map_node) *)((long)e - sizeof(struct hlist_node));
+// dbug ("n =%lx key=" EACHKEY(%ld) "\n", (long)n, n->key1.val, n->key2.val);
+ if (KEY1_EQ_P(n->key1, key1)
+#if KEY_ARITY > 1
+ && KEY2_EQ_P(n->key2, key2)
+#if KEY_ARITY > 2
+ && KEY3_EQ_P(n->key3, key3)
+#if KEY_ARITY > 3
+ && KEY4_EQ_P(n->key4, key4)
+#if KEY_ARITY > 4
+ && KEY5_EQ_P(n->key5, key5)
+#endif
+#endif
+#endif
+#endif
+ ) {
+ return MAP_GET_VAL(map,(struct map_node *)n);
+ }
+ }
+ /* key not found */
+ return (VALTYPE)0;
+}
+
+
+#undef KEY1NAME
+#undef KEY1N
+#undef KEY1TYPE
+#undef KEY1_TYPE
+#undef KEY1STOR
+#undef KEY1CPY
+
+#undef KEY2NAME
+#undef KEY2N
+#undef KEY2TYPE
+#undef KEY2_TYPE
+#undef KEY2STOR
+#undef KEY2CPY
+
+#undef KEY3NAME
+#undef KEY3N
+#undef KEY3TYPE
+#undef KEY3_TYPE
+#undef KEY3STOR
+#undef KEY3CPY
+
+#undef KEY4NAME
+#undef KEY4N
+#undef KEY4TYPE
+#undef KEY4_TYPE
+#undef KEY4STOR
+#undef KEY4CPY
+
+#undef KEY5NAME
+#undef KEY5N
+#undef KEY5TYPE
+#undef KEY5_TYPE
+#undef KEY5STOR
+#undef KEY5CPY
+
+#undef KEY_ARITY
+#undef ALLKEYS
+#undef ALLKEYSD
+#undef KEYCPY
+#undef KEYSYM
+
+#undef VALUE_TYPE
+#undef VALNAME
+#undef VALTYPE
+#undef VSTYPE
+#undef VALN
+
+#undef MAP_SET_VAL
+#undef MAP_GET_VAL
+
+
* @brief Implements maps (associative arrays) and lists
*/
+#include "map-values.c"
#include "alloc.c"
#include "sym.c"
0
};
-#ifdef NEED_INT64_KEYS
unsigned int int64_hash (const int64_t v)
{
return (unsigned int)hash_long ((unsigned long)v, HASH_TABLE_BITS);
{
return key1 == key2;
}
-#endif /* NEED_INT64_KEYS */
-
-
-#if defined (NEED_STRING_KEYS) || defined (NEED_STRING_VALS)
void str_copy(char *dest, char *src)
{
int len = strlen(src);
strncpy (dest, src, len);
dest[len] = 0;
}
-#endif
-#ifdef NEED_STRING_KEYS
int str_eq_p (char *key1, char *key2)
{
return strncmp(key1, key2, MAP_STRING_LENGTH - 1) == 0;
}
return (unsigned int)hash_long((unsigned long)hash, HASH_TABLE_BITS);
}
-#endif /* NEED_STRING_KEYS */
/** @addtogroup maps
* Implements maps (associative arrays) and lists
for (i = max_entries - 1; i >= 0; i--) {
e = i * size + tmp;
- //dbug ("e=%lx\n", (long)e);
+ dbug ("e=%lx\n", (long)e);
list_add(e, &m->pool);
((struct map_node *)e)->map = m;
}
_stp_symbol_print ((unsigned long)val);
break;
}
-#ifdef NEED_STAT_VALS
case STAT:
{
Stat st = (Stat)((long)map + offsetof(struct map_root, hist_type));
_stp_stat_print_valtype (fmt, st, sd, 0);
break;
}
-#endif
default:
break;
}
{
struct map_node *m;
if (list_empty(&map->pool)) {
- if (map->no_wrap) {
- /* ERROR. FIXME */
+ if (!map->wrap) {
+ /* ERROR. no space left */
return NULL;
}
m = (struct map_node *)map->head.next;
map->num++;
return m;
}
-#endif
+
+static struct map_node *_new_map_create (MAP map, struct hlist_head *head)
+{
+ struct map_node *m;
+ dbug("map=%lx\n", map);
+ if (list_empty(&map->pool)) {
+ if (!map->wrap) {
+ /* ERROR. no space left */
+ return NULL;
+ }
+ m = (struct map_node *)map->head.next;
+ dbug ("got %lx off head\n", (long)m);
+ hlist_del_init(&m->hnode);
+ } else {
+ m = (struct map_node *)map->pool.next;
+ dbug ("got %lx off pool\n", (long)m);
+ }
+ list_move_tail(&m->lnode, &map->head);
+
+ /* add node to new hash list */
+ hlist_add_head(&m->hnode, head);
+
+ map->num++;
+ return m;
+}
+
+static void _new_map_del_node (MAP map, struct map_node *n)
+{
+ /* remove node from old hash list */
+ hlist_del_init(&n->hnode);
+
+ /* remove from entry list */
+ list_del(&n->lnode);
+
+ /* add it back to the pool */
+ list_add(&n->lnode, &map->pool);
+
+ map->num--;
+}
+
+static int _new_map_set_int64 (MAP map, struct map_node *n, int64_t val, int add)
+{
+ if (map == NULL || n == NULL)
+ return -2;
+
+ if (val || map->list) {
+ if (add)
+ *(int64_t *)((long)n + map->data_offset) += val;
+ else
+ *(int64_t *)((long)n + map->data_offset) = val;
+ } else if (!add) {
+ /* setting value to 0 is the same as deleting */
+ _new_map_del_node (map, n);
+ }
+ return 0;
+}
+
+static int _new_map_set_str (MAP map, struct map_node *n, char *val, int add)
+{
+ if (map == NULL || n == NULL)
+ return -2;
+
+ if (val || map->list) {
+ if (add)
+ str_add((void *)((long)n + map->data_offset), val);
+ else
+ str_copy((void *)((long)n + map->data_offset), val);
+ } else if (!add) {
+ /* setting value to 0 is the same as deleting */
+ _new_map_del_node (map, n);
+ }
+ return 0;
+}
+
+static int64_t _new_map_get_int64 (MAP map, struct map_node *n)
+{
+ if (map == NULL || n == NULL)
+ return 0;
+ return *(int64_t *)((long)n + map->data_offset);
+}
+
+static char *_new_map_get_str (MAP map, struct map_node *n)
+{
+ if (map == NULL || n == NULL)
+ return 0;
+ return (char *)((long)n + map->data_offset);
+}
+
+static stat *_new_map_get_stat (MAP map, struct map_node *n)
+{
+ if (map == NULL || n == NULL)
+ return 0;
+ return (stat *)((long)n + map->data_offset);
+}
+
+static int _new_map_set_stat (MAP map, struct map_node *n, int64_t val, int add, int new)
+{
+ stat *sd;
+ Stat st;
+
+ if (map == NULL || n == NULL)
+ return -2;
+
+ if (val == 0 && !add) {
+ _new_map_del_node (map, n);
+ return 0;
+ }
+
+ sd = (stat *)((long)n + map->data_offset);
+ st = (Stat)((long)map + offsetof(struct map_root, hist_type));
+
+ if (new || !add) {
+ int j;
+ sd->count = sd->sum = sd->min = sd->max = 0;
+ if (st->hist_type != HIST_NONE) {
+ for (j = 0; j < st->hist_buckets; j++)
+ sd->histogram[j] = 0;
+ }
+ }
+
+ __stp_stat_add (st, sd, val);
+
+ return 0;
+}
+
+
+#endif /* _MAP_C_ */