commit 40c93e66a2a29dd3d3e737101640a8014e53d836
parent 4893a030a6819078d246646f50bfd46650d00620
Author: Joris Vink <joris@coders.se>
Date:   Wed, 30 Aug 2017 11:47:26 +0200
Add memory tagging.
This allows modules that have global pointers to upon reload repopulate
those with the addresses of when they were first created.
Meaning it now is easier to write modules that can be reloaded if those
modules kept global state one way or the other.
This should only be used at module init/reload time and is very simple:
if ((ptr = kore_mem_lookup(MY_ID_VALUE)) == NULL) {
	ptr = kore_malloc_tagged(length, MY_ID_VALUE);
	/* initialize for the first time. */
}
If we were in a reload the kore_mem_lookup() will return the original address
returned by the initial kore_malloc_tagged() call for MY_ID_VALUE.
Diffstat:
2 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/includes/kore.h b/includes/kore.h
@@ -558,6 +558,10 @@ void		*kore_realloc(void *, size_t);
 void		kore_free(void *);
 void		kore_mem_init(void);
 void		kore_mem_cleanup(void);
+void		kore_mem_untag(void *);
+void		*kore_mem_lookup(u_int32_t);
+void		kore_mem_tag(void *, u_int32_t);
+void		*kore_malloc_tagged(size_t, u_int32_t);
 
 void		*kore_pool_get(struct kore_pool *);
 void		kore_pool_put(struct kore_pool *, void *);
diff --git a/src/mem.c b/src/mem.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 Joris Vink <joris@coders.se>
+ * Copyright (c) 2013-2017 Joris Vink <joris@coders.se>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -32,7 +32,10 @@
 #define KORE_MEMINFO(x)		\
 	(struct meminfo *)((u_int8_t *)x + KORE_MEMSIZE(x))
 
+#define KORE_MEM_TAGGED		0x0001
+
 struct meminfo {
+	u_int16_t		flags;
 	u_int16_t		magic;
 };
 
@@ -40,8 +43,16 @@ struct memblock {
 	struct kore_pool	pool;
 };
 
+struct tag {
+	void			*ptr;
+	u_int32_t		id;
+	TAILQ_ENTRY(tag)	list;
+};
+
 static size_t			memblock_index(size_t);
 
+static TAILQ_HEAD(, tag)	tags;
+static struct kore_pool		tag_pool;
 static struct memblock		blocks[KORE_MEM_BLOCKS];
 
 void
@@ -52,6 +63,8 @@ kore_mem_init(void)
 	u_int32_t	size, elm, mlen;
 
 	size = 8;
+	TAILQ_INIT(&tags);
+	kore_pool_init(&tag_pool, "tag_pool", sizeof(struct tag), 100);
 
 	for (i = 0; i < KORE_MEM_BLOCKS; i++) {
 		len = snprintf(name, sizeof(name), "block-%u", size);
@@ -104,6 +117,7 @@ kore_malloc(size_t len)
 	addr = (u_int8_t *)ptr + sizeof(size_t);
 
 	mem = KORE_MEMINFO(addr);
+	mem->flags = 0;
 	mem->magic = KORE_MEM_MAGIC;
 
 	return (addr);
@@ -162,6 +176,11 @@ kore_free(void *ptr)
 	if (mem->magic != KORE_MEM_MAGIC)
 		fatal("kore_free(): magic boundary not found");
 
+	if (mem->flags & KORE_MEM_TAGGED) {
+		kore_mem_untag(ptr);
+		mem->flags &= ~KORE_MEM_TAGGED;
+	}
+
 	len = KORE_MEMSIZE(ptr);
 	addr = (u_int8_t *)ptr - sizeof(size_t);
 
@@ -186,6 +205,65 @@ kore_strdup(const char *str)
 	return (nstr);
 }
 
+void *
+kore_malloc_tagged(size_t len, u_int32_t tag)
+{
+	void		*ptr;
+
+	ptr = kore_malloc(len);
+	kore_mem_tag(ptr, tag);
+
+	return (ptr);
+}
+
+void
+kore_mem_tag(void *ptr, u_int32_t id)
+{
+	struct tag		*tag;
+	struct meminfo		*mem;
+
+	if (kore_mem_lookup(id) != NULL)
+		fatal("kore_mem_tag: tag %u taken", id);
+
+	mem = KORE_MEMINFO(ptr);
+	if (mem->magic != KORE_MEM_MAGIC)
+		fatal("kore_mem_tag: magic boundary not found");
+	mem->flags |= KORE_MEM_TAGGED;
+
+	tag = kore_pool_get(&tag_pool);
+	tag->id = id;
+	tag->ptr = ptr;
+
+	TAILQ_INSERT_TAIL(&tags, tag, list);
+}
+
+void
+kore_mem_untag(void *ptr)
+{
+	struct tag		*tag;
+
+	TAILQ_FOREACH(tag, &tags, list) {
+		if (tag->ptr == ptr) {
+			TAILQ_REMOVE(&tags, tag, list);
+			kore_pool_put(&tag_pool, tag);
+			break;
+		}
+	}
+}
+
+void *
+kore_mem_lookup(u_int32_t id)
+{
+	struct tag		*tag;
+
+	TAILQ_FOREACH(tag, &tags, list) {
+		if (tag->id == id)
+			return (tag->ptr);
+	}
+
+	return (NULL);
+}
+
 static size_t
 memblock_index(size_t len)
 {