Add a set of simple functions to handle refcounted pointers.

Signed-off-by: Martin Wilck <[email protected]>
---
 libmpathutil/libmpathutil.version |  7 +++++
 libmpathutil/util.c               | 45 ++++++++++++++++++++++++++++---
 libmpathutil/util.h               |  5 ++++
 3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/libmpathutil/libmpathutil.version 
b/libmpathutil/libmpathutil.version
index c69120d..51594ad 100644
--- a/libmpathutil/libmpathutil.version
+++ b/libmpathutil/libmpathutil.version
@@ -194,3 +194,10 @@ global:
 local:
        *;
 };
+
+LIBMPATHUTIL_6.1 {
+global:
+       alloc_shared_ptr;
+       get_shared_ptr;
+       put_shared_ptr;
+} LIBMPATHUTIL_6.0;
diff --git a/libmpathutil/util.c b/libmpathutil/util.c
index 23a9797..3c623ec 100644
--- a/libmpathutil/util.c
+++ b/libmpathutil/util.c
@@ -12,15 +12,13 @@
 #include <dirent.h>
 #include <unistd.h>
 #include <errno.h>
+#include <urcu/uatomic.h>
 #include "mt-udev-wrap.h"
 
 #include "util.h"
 #include "debug.h"
-#include "checkers.h"
 #include "vector.h"
-#include "structs.h"
-#include "config.h"
-#include "log.h"
+#include "list.h"
 
 size_t
 strchop(char *str)
@@ -384,3 +382,42 @@ void cleanup_udev_device(struct udev_device **udd)
        if (*udd)
                udev_device_unref(*udd);
 }
+
+struct shared_ptr {
+       long refcnt;
+       void (*destructor)(void *);
+       char __attribute__((aligned(sizeof(void *)))) ptr[];
+};
+
+void *alloc_shared_ptr(size_t size, void (*destructor)(void *))
+{
+       struct shared_ptr *sp = malloc(sizeof(*sp) + size);
+
+       if (!sp)
+               return NULL;
+       uatomic_set(&sp->refcnt, 1);
+       sp->destructor = destructor;
+       return sp->ptr;
+}
+
+void get_shared_ptr(void *ptr)
+{
+       struct shared_ptr *sp = container_of(ptr, struct shared_ptr, ptr);
+
+       if (uatomic_add_return(&sp->refcnt, 1) < 0)
+               condlog(0, "%s: refcount overflow", __func__);
+}
+
+void put_shared_ptr(void *ptr)
+{
+       struct shared_ptr *sp;
+
+       if (!ptr)
+               return;
+       sp = container_of(ptr, struct shared_ptr, ptr);
+       if (uatomic_sub_return(&sp->refcnt, 1) == 0) {
+               if (sp->destructor)
+                       sp->destructor(ptr);
+               free(sp);
+       }
+}
diff --git a/libmpathutil/util.h b/libmpathutil/util.h
index aed1bc1..ffbb182 100644
--- a/libmpathutil/util.h
+++ b/libmpathutil/util.h
@@ -160,4 +160,9 @@ void cleanup_charp(char **p);
 void cleanup_ucharp(unsigned char **p);
 void cleanup_udev_device(struct udev_device **udd);
 void cleanup_bitfield(union bitfield **p);
+
+void *alloc_shared_ptr(size_t size, void (*destructor)(void *));
+void get_shared_ptr(void *ptr);
+void put_shared_ptr(void *ptr);
+
 #endif /* UTIL_H_INCLUDED */
-- 
2.54.0


Reply via email to