All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bartosz Golaszewski <brgl@bgdev.pl>
To: Kent Gibson <warthog618@gmail.com>,
	Linus Walleij <linus.walleij@linaro.org>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: linux-gpio@vger.kernel.org, Bartosz Golaszewski <brgl@bgdev.pl>
Subject: [libgpiod][RFC 2/6] core: add refcounting helpers
Date: Sat, 10 Apr 2021 16:51:53 +0200	[thread overview]
Message-ID: <20210410145157.30718-3-brgl@bgdev.pl> (raw)
In-Reply-To: <20210410145157.30718-1-brgl@bgdev.pl>

In v2.0 all objects will be opaque and refcounted. Add a set of helper
functions and data structures for refcounting.

Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
---
 lib/Makefile.am |  2 +-
 lib/core.c      | 52 ++++++++++++++++++++++++++-----------------------
 lib/internal.c  | 22 +++++++++++++++++++++
 lib/internal.h  | 19 ++++++++++++++++++
 4 files changed, 70 insertions(+), 25 deletions(-)
 create mode 100644 lib/internal.c

diff --git a/lib/Makefile.am b/lib/Makefile.am
index 8441584..5c7f353 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2,7 +2,7 @@
 # SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
 
 lib_LTLIBRARIES = libgpiod.la
-libgpiod_la_SOURCES = core.c helpers.c internal.h misc.c uapi/gpio.h
+libgpiod_la_SOURCES = core.c helpers.c internal.c internal.h misc.c uapi/gpio.h
 libgpiod_la_CFLAGS = -Wall -Wextra -g -std=gnu89
 libgpiod_la_CFLAGS += -fvisibility=hidden -I$(top_srcdir)/include/
 libgpiod_la_CFLAGS += -include $(top_builddir)/config.h
diff --git a/lib/core.c b/lib/core.c
index 2e7ee4b..0f3937b 100644
--- a/lib/core.c
+++ b/lib/core.c
@@ -65,7 +65,7 @@ struct gpiod_line {
 };
 
 struct gpiod_chip {
-	int refcount;
+	struct gpiod_refcount refcount;
 
 	struct gpiod_line **lines;
 	unsigned int num_lines;
@@ -246,6 +246,30 @@ out:
 	return ret;
 }
 
+static void chip_release(struct gpiod_refcount *refcount)
+{
+	struct gpiod_chip *chip;
+	struct gpiod_line *line;
+	unsigned int i;
+
+	chip = gpiod_container_of(refcount, struct gpiod_chip, refcount);
+
+	if (chip->lines) {
+		for (i = 0; i < chip->num_lines; i++) {
+			line = chip->lines[i];
+			if (line) {
+				gpiod_line_release(line);
+				free(line);
+			}
+		}
+
+		free(chip->lines);
+	}
+
+	close(chip->fd);
+	free(chip);
+}
+
 GPIOD_API struct gpiod_chip *gpiod_chip_open(const char *path)
 {
 	struct gpiochip_info info;
@@ -276,7 +300,7 @@ GPIOD_API struct gpiod_chip *gpiod_chip_open(const char *path)
 
 	chip->fd = fd;
 	chip->num_lines = info.lines;
-	chip->refcount = 1;
+	gpiod_refcount_init(&chip->refcount, chip_release);
 
 	/*
 	 * GPIO device must have a name - don't bother checking this field. In
@@ -306,33 +330,13 @@ err_close_fd:
 
 GPIOD_API struct gpiod_chip *gpiod_chip_ref(struct gpiod_chip *chip)
 {
-	chip->refcount++;
+	gpiod_refcount_ref(&chip->refcount);
 	return chip;
 }
 
 GPIOD_API void gpiod_chip_unref(struct gpiod_chip *chip)
 {
-	struct gpiod_line *line;
-	unsigned int i;
-
-	chip->refcount--;
-	if (chip->refcount > 0)
-		return;
-
-	if (chip->lines) {
-		for (i = 0; i < chip->num_lines; i++) {
-			line = chip->lines[i];
-			if (line) {
-				gpiod_line_release(line);
-				free(line);
-			}
-		}
-
-		free(chip->lines);
-	}
-
-	close(chip->fd);
-	free(chip);
+	gpiod_refcount_unref(&chip->refcount);
 }
 
 GPIOD_API const char *gpiod_chip_get_name(struct gpiod_chip *chip)
diff --git a/lib/internal.c b/lib/internal.c
new file mode 100644
index 0000000..52b9461
--- /dev/null
+++ b/lib/internal.c
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// SPDX-FileCopyrightText: 2021 Bartosz Golaszewski <brgl@bgdev.pl>
+
+#include "internal.h"
+
+void gpiod_refcount_init(struct gpiod_refcount *refcount,
+			 gpiod_refcount_release release)
+{
+	refcount->refcnt = 1;
+	refcount->release = release;
+}
+
+void gpiod_refcount_ref(struct gpiod_refcount *refcount)
+{
+	refcount->refcnt++;
+}
+
+void gpiod_refcount_unref(struct gpiod_refcount *refcount)
+{
+	if (--refcount->refcnt == 0)
+		refcount->release(refcount);
+}
diff --git a/lib/internal.h b/lib/internal.h
index 8b3f69a..a652879 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -4,8 +4,27 @@
 #ifndef __LIBGPIOD_GPIOD_INTERNAL_H__
 #define __LIBGPIOD_GPIOD_INTERNAL_H__
 
+#include <stddef.h>
+
 /* For internal library use only. */
 
 #define GPIOD_API __attribute__((visibility("default")))
 
+#define gpiod_container_of(ptr, type, member) ({			\
+	void *__mptr = (void *)(ptr);					\
+	((type *)(__mptr - offsetof(type, member))); })
+
+struct gpiod_refcount;
+typedef void (*gpiod_refcount_release)(struct gpiod_refcount *);
+
+struct gpiod_refcount {
+	unsigned int refcnt;
+	gpiod_refcount_release release;
+};
+
+void gpiod_refcount_init(struct gpiod_refcount *refcount,
+			 gpiod_refcount_release release);
+void gpiod_refcount_ref(struct gpiod_refcount *refcount);
+void gpiod_refcount_unref(struct gpiod_refcount *refcount);
+
 #endif /* __LIBGPIOD_GPIOD_INTERNAL_H__ */
-- 
2.30.1


  parent reply	other threads:[~2021-04-10 14:52 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-10 14:51 [libgpiod][RFC 0/6] first draft of libgpiod v2.0 API Bartosz Golaszewski
2021-04-10 14:51 ` [libgpiod][RFC 1/6] treewide: rename chip property accessors Bartosz Golaszewski
2021-04-10 14:51 ` Bartosz Golaszewski [this message]
2021-04-10 14:51 ` [libgpiod][RFC 3/6] core: implement line_info objects Bartosz Golaszewski
2021-04-10 14:51 ` [libgpiod][RFC 4/6] core: rework line events Bartosz Golaszewski
2021-04-10 14:51 ` [libgpiod][RFC 5/6] core: rework line requests Bartosz Golaszewski
2021-04-10 14:51 ` [libgpiod][RFC 6/6] core: implement line watch events Bartosz Golaszewski
2021-04-14 14:15 ` [libgpiod][RFC 0/6] first draft of libgpiod v2.0 API Kent Gibson
2021-04-16  9:36   ` Bartosz Golaszewski
2021-04-17  7:23     ` Kent Gibson
2021-04-17 11:31       ` Bartosz Golaszewski
2021-04-18  3:48         ` Kent Gibson
2021-04-18 21:12           ` Bartosz Golaszewski
2021-04-19  1:17             ` Kent Gibson
2021-04-21 20:04               ` Bartosz Golaszewski
2021-04-22  2:32                 ` Kent Gibson
2021-04-22  9:24                   ` Bartosz Golaszewski
2021-04-23  1:38                     ` Kent Gibson
2021-04-28  9:19                       ` Bartosz Golaszewski
2021-04-28 10:34                         ` Kent Gibson
2021-04-30 17:52                           ` Bartosz Golaszewski
2021-05-01  0:15                             ` Kent Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210410145157.30718-3-brgl@bgdev.pl \
    --to=brgl@bgdev.pl \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=warthog618@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.