All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH BlueZ] shared/io-ell: Add reference count to io structure
@ 2020-09-25 22:38 Inga Stotland
  2020-09-25 22:52 ` [BlueZ] " bluez.test.bot
       [not found] ` <28971312d4000cf290ed1868dc7835aa8e063283.camel@intel.com>
  0 siblings, 2 replies; 3+ messages in thread
From: Inga Stotland @ 2020-09-25 22:38 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: Inga Stotland

This adds reference count to io wrapper structure.
Also, correctly handles IO destroy case by unsetting
read/write/disconnect halers and freeing the corresponding
resources.
---
 src/shared/io-ell.c | 193 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 155 insertions(+), 38 deletions(-)

diff --git a/src/shared/io-ell.c b/src/shared/io-ell.c
index 485c613e0..dee9a95c9 100644
--- a/src/shared/io-ell.c
+++ b/src/shared/io-ell.c
@@ -20,48 +20,96 @@
 
 #include "src/shared/io.h"
 
+struct io_watch {
+	struct io *io;
+	io_callback_func_t cb;
+	io_destroy_func_t destroy;
+	void *user_data;
+};
+
 struct io {
+	int ref_count;
 	struct l_io *l_io;
-	io_callback_func_t read_cb;
-	io_destroy_func_t read_destroy;
-	void *read_data;
-	io_callback_func_t write_cb;
-	io_destroy_func_t write_destroy;
-	void *write_data;
+	struct io_watch *read_watch;
+	struct io_watch *write_watch;
+	struct io_watch *disc_watch;
 };
 
-static bool read_callback(struct l_io *l_io, void *user_data)
+static struct io *io_ref(struct io *io)
 {
-	struct io *io = user_data;
-	bool result = false;
+	if (!io)
+		return NULL;
+
+	__sync_fetch_and_add(&io->ref_count, 1);
+
+	return io;
+}
 
+static void io_unref(struct io *io)
+{
 	if (!io)
-		return false;
+		return;
 
-	if (io->read_cb)
-		result = io->read_cb(io, io->read_data);
+	if (__sync_sub_and_fetch(&io->ref_count, 1))
+		return;
 
-	if (io->read_destroy)
-		io->read_destroy(io->read_data);
+	l_free(io);
+}
 
-	return result;
+static void watch_destroy(void *user_data)
+{
+	struct io_watch *watch = user_data;
+	struct io *io;
+
+	if (!watch)
+		return;
+
+	io = watch->io;
+
+	if (watch == io->read_watch)
+		io->read_watch = NULL;
+	else if (watch == io->write_watch)
+		io->write_watch = NULL;
+	else if (watch == io->disc_watch)
+		io->disc_watch = NULL;
+
+	if (watch->destroy)
+		watch->destroy(watch->user_data);
+
+	io_unref(watch->io);
+	l_free(watch);
 }
 
-static bool write_callback(struct l_io *l_io, void *user_data)
+static struct io_watch *watch_new(struct io *io, io_callback_func_t cb,
+				void *user_data, io_destroy_func_t destroy)
 {
-	struct io *io = user_data;
-	bool result = false;
+	struct io_watch *watch;
 
-	if (!io)
+	watch = l_new(struct io_watch, 1);
+	watch->io = io_ref(io);
+	watch->cb = cb;
+	watch->user_data = user_data;
+	watch->destroy = destroy;
+
+	return watch;
+}
+
+static bool watch_callback(struct l_io *l_io, void *user_data)
+{
+	struct io_watch *watch = user_data;
+
+	if (!watch->cb)
 		return false;
 
-	if (io->write_cb)
-		result = io->write_cb(io, io->write_data);
+	return watch->cb(watch->io, watch->user_data);
+}
 
-	if (io->write_destroy)
-		io->write_destroy(io->write_data);
+static void disc_callback(struct l_io *l_io, void *user_data)
+{
+	struct io_watch *watch = user_data;
 
-	return result;
+	if (watch->cb)
+		watch->cb(watch->io, watch->user_data);
 }
 
 struct io *io_new(int fd)
@@ -84,7 +132,7 @@ struct io *io_new(int fd)
 
 	io->l_io = l_io;
 
-	return io;
+	return io_ref(io);
 }
 
 void io_destroy(struct io *io)
@@ -92,10 +140,22 @@ void io_destroy(struct io *io)
 	if (!io)
 		return;
 
-	if (io->l_io)
-		l_io_destroy(io->l_io);
+	l_io_set_read_handler(io->l_io, NULL, NULL, NULL);
+	watch_destroy(io->read_watch);
+	io->read_watch = NULL;
 
-	l_free(io);
+	l_io_set_write_handler(io->l_io, NULL, NULL, NULL);
+	watch_destroy(io->write_watch);
+	io->write_watch = NULL;
+
+	l_io_set_disconnect_handler(io->l_io, NULL, NULL, NULL);
+	watch_destroy(io->disc_watch);
+	io->disc_watch = NULL;
+
+	l_io_destroy(io->l_io);
+	io->l_io = NULL;
+
+	io_unref(io);
 }
 
 int io_get_fd(struct io *io)
@@ -117,37 +177,94 @@ bool io_set_close_on_destroy(struct io *io, bool do_close)
 bool io_set_read_handler(struct io *io, io_callback_func_t callback,
 				void *user_data, io_destroy_func_t destroy)
 {
+	bool result;
+
 	if (!io || !io->l_io)
 		return false;
 
-	io->read_cb = callback;
-	io->read_data = user_data;
-	io->read_destroy = destroy;
+	if (io->read_watch) {
+		l_io_set_read_handler(io->l_io, NULL, NULL, NULL);
 
-	return l_io_set_read_handler(io->l_io, read_callback, io, NULL);
+		if (!callback) {
+			watch_destroy(io->read_watch);
+			io->read_watch = NULL;
+			return true;
+		}
+	}
+
+	io->read_watch = watch_new(io, callback, user_data, destroy);
+
+	result = l_io_set_read_handler(io->l_io, watch_callback, io->read_watch,
+								watch_destroy);
+
+	if (!result) {
+		watch_destroy(io->read_watch);
+		io->read_watch = NULL;
+	}
+
+	return result;
 }
 
 bool io_set_write_handler(struct io *io, io_callback_func_t callback,
 				void *user_data, io_destroy_func_t destroy)
 {
+	bool result;
+
 	if (!io || !io->l_io)
 		return false;
 
-	io->write_cb = callback;
-	io->write_data = user_data;
-	io->write_destroy = destroy;
+	if (io->write_watch) {
+		l_io_set_write_handler(io->l_io, NULL, NULL, NULL);
 
-	return l_io_set_write_handler(io->l_io, write_callback, io, NULL);
+		if (!callback) {
+			watch_destroy(io->write_watch);
+			io->write_watch = NULL;
+			return true;
+		}
+	}
+
+	io->write_watch = watch_new(io, callback, user_data, destroy);
+
+	result = l_io_set_write_handler(io->l_io, watch_callback,
+						io->write_watch, watch_destroy);
+
+	if (!result) {
+		watch_destroy(io->write_watch);
+		io->write_watch = NULL;
+	}
+
+	return result;
 }
 
 bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
 				void *user_data, io_destroy_func_t destroy)
 {
+	bool result;
+
 	if (!io || !io->l_io)
 		return false;
 
-	return l_io_set_disconnect_handler(io->l_io, (void *) callback,
-							user_data, destroy);
+	if (io->disc_watch) {
+		l_io_set_disconnect_handler(io->l_io, NULL, NULL, NULL);
+
+		if (!callback) {
+			watch_destroy(io->disc_watch);
+			io->disc_watch = NULL;
+			return true;
+		}
+	}
+
+	io->disc_watch = watch_new(io, callback, user_data, destroy);
+
+	result = l_io_set_disconnect_handler(io->l_io, disc_callback,
+						io->disc_watch, watch_destroy);
+
+	if (!result) {
+		watch_destroy(io->disc_watch);
+		io->disc_watch = NULL;
+	}
+
+	return result;
 }
 
 ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt)
-- 
2.26.2


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* RE: [BlueZ] shared/io-ell: Add reference count to io structure
  2020-09-25 22:38 [PATCH BlueZ] shared/io-ell: Add reference count to io structure Inga Stotland
@ 2020-09-25 22:52 ` bluez.test.bot
       [not found] ` <28971312d4000cf290ed1868dc7835aa8e063283.camel@intel.com>
  1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2020-09-25 22:52 UTC (permalink / raw)
  To: linux-bluetooth, inga.stotland

[-- Attachment #1: Type: text/plain, Size: 557 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=355719

---Test result---

##############################
Test: CheckPatch - PASS

##############################
Test: CheckGitLint - PASS

##############################
Test: CheckBuild - PASS

##############################
Test: MakeCheck - PASS



---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH BlueZ] shared/io-ell: Add reference count to io structure
       [not found]     ` <34b8fe82558fa3467a99181bc5a4a4f1e185b756.camel@intel.com>
@ 2020-10-19 20:17       ` Luiz Augusto von Dentz
  0 siblings, 0 replies; 3+ messages in thread
From: Luiz Augusto von Dentz @ 2020-10-19 20:17 UTC (permalink / raw)
  To: Stotland, Inga; +Cc: linux-bluetooth

Hi Inga,

On Mon, Oct 19, 2020 at 1:00 PM Stotland, Inga <inga.stotland@intel.com> wrote:
>
> Another ping
>
> On Fri, 2020-10-09 at 21:06 -0700, Inga Stotland wrote:
>
>  Ping
> On Sun, 2020-10-04 at 21:20 -0700, Inga Stotland wrote:
>
> Ping
>
> On Fri, 2020-09-25 at 15:38 -0700, Inga Stotland wrote:
>
> This adds reference count to io wrapper structure.
>
> Also, correctly handles IO destroy case by unsetting
>
> read/write/disconnect halers and freeing the corresponding
>
> resources.
>
> ---
>
>  src/shared/io-ell.c | 193 +++++++++++++++++++++++++++++++++++---------
>
>  1 file changed, 155 insertions(+), 38 deletions(-)
>
>
> diff --git a/src/shared/io-ell.c b/src/shared/io-ell.c
>
> index 485c613e0..dee9a95c9 100644
>
> --- a/src/shared/io-ell.c
>
> +++ b/src/shared/io-ell.c
>
> @@ -20,48 +20,96 @@
>
>
>
>  #include "src/shared/io.h"
>
>
>
> +struct io_watch {
>
> + struct io *io;
>
> + io_callback_func_t cb;
>
> + io_destroy_func_t destroy;
>
> + void *user_data;
>
> +};
>
> +
>
>  struct io {
>
> + int ref_count;
>
>   struct l_io *l_io;
>
> - io_callback_func_t read_cb;
>
> - io_destroy_func_t read_destroy;
>
> - void *read_data;
>
> - io_callback_func_t write_cb;
>
> - io_destroy_func_t write_destroy;
>
> - void *write_data;
>
> + struct io_watch *read_watch;
>
> + struct io_watch *write_watch;
>
> + struct io_watch *disc_watch;
>
>  };
>
>
>
> -static bool read_callback(struct l_io *l_io, void *user_data)
>
> +static struct io *io_ref(struct io *io)
>
>  {
>
> - struct io *io = user_data;
>
> - bool result = false;
>
> + if (!io)
>
> + return NULL;
>
> +
>
> + __sync_fetch_and_add(&io->ref_count, 1);
>
> +
>
> + return io;
>
> +}
>
>
>
> +static void io_unref(struct io *io)
>
> +{
>
>   if (!io)
>
> - return false;
>
> + return;
>
>
>
> - if (io->read_cb)
>
> - result = io->read_cb(io, io->read_data);
>
> + if (__sync_sub_and_fetch(&io->ref_count, 1))
>
> + return;
>
>
>
> - if (io->read_destroy)
>
> - io->read_destroy(io->read_data);
>
> + l_free(io);
>
> +}
>
>
>
> - return result;
>
> +static void watch_destroy(void *user_data)
>
> +{
>
> + struct io_watch *watch = user_data;
>
> + struct io *io;
>
> +
>
> + if (!watch)
>
> + return;
>
> +
>
> + io = watch->io;
>
> +
>
> + if (watch == io->read_watch)
>
> + io->read_watch = NULL;
>
> + else if (watch == io->write_watch)
>
> + io->write_watch = NULL;
>
> + else if (watch == io->disc_watch)
>
> + io->disc_watch = NULL;
>
> +
>
> + if (watch->destroy)
>
> + watch->destroy(watch->user_data);
>
> +
>
> + io_unref(watch->io);
>
> + l_free(watch);
>
>  }
>
>
>
> -static bool write_callback(struct l_io *l_io, void *user_data)
>
> +static struct io_watch *watch_new(struct io *io, io_callback_func_t cb,
>
> + void *user_data, io_destroy_func_t destroy)
>
>  {
>
> - struct io *io = user_data;
>
> - bool result = false;
>
> + struct io_watch *watch;
>
>
>
> - if (!io)
>
> + watch = l_new(struct io_watch, 1);
>
> + watch->io = io_ref(io);
>
> + watch->cb = cb;
>
> + watch->user_data = user_data;
>
> + watch->destroy = destroy;
>
> +
>
> + return watch;
>
> +}
>
> +
>
> +static bool watch_callback(struct l_io *l_io, void *user_data)
>
> +{
>
> + struct io_watch *watch = user_data;
>
> +
>
> + if (!watch->cb)
>
>   return false;
>
>
>
> - if (io->write_cb)
>
> - result = io->write_cb(io, io->write_data);
>
> + return watch->cb(watch->io, watch->user_data);
>
> +}
>
>
>
> - if (io->write_destroy)
>
> - io->write_destroy(io->write_data);
>
> +static void disc_callback(struct l_io *l_io, void *user_data)
>
> +{
>
> + struct io_watch *watch = user_data;
>
>
>
> - return result;
>
> + if (watch->cb)
>
> + watch->cb(watch->io, watch->user_data);
>
>  }
>
>
>
>  struct io *io_new(int fd)
>
> @@ -84,7 +132,7 @@ struct io *io_new(int fd)
>
>
>
>   io->l_io = l_io;
>
>
>
> - return io;
>
> + return io_ref(io);
>
>  }
>
>
>
>  void io_destroy(struct io *io)
>
> @@ -92,10 +140,22 @@ void io_destroy(struct io *io)
>
>   if (!io)
>
>   return;
>
>
>
> - if (io->l_io)
>
> - l_io_destroy(io->l_io);
>
> + l_io_set_read_handler(io->l_io, NULL, NULL, NULL);
>
> + watch_destroy(io->read_watch);
>
> + io->read_watch = NULL;
>
>
>
> - l_free(io);
>
> + l_io_set_write_handler(io->l_io, NULL, NULL, NULL);
>
> + watch_destroy(io->write_watch);
>
> + io->write_watch = NULL;
>
> +
>
> + l_io_set_disconnect_handler(io->l_io, NULL, NULL, NULL);
>
> + watch_destroy(io->disc_watch);
>
> + io->disc_watch = NULL;
>
> +
>
> + l_io_destroy(io->l_io);
>
> + io->l_io = NULL;
>
> +
>
> + io_unref(io);
>
>  }
>
>
>
>  int io_get_fd(struct io *io)
>
> @@ -117,37 +177,94 @@ bool io_set_close_on_destroy(struct io *io, bool do_close)
>
>  bool io_set_read_handler(struct io *io, io_callback_func_t callback,
>
>   void *user_data, io_destroy_func_t destroy)
>
>  {
>
> + bool result;
>
> +
>
>   if (!io || !io->l_io)
>
>   return false;
>
>
>
> - io->read_cb = callback;
>
> - io->read_data = user_data;
>
> - io->read_destroy = destroy;
>
> + if (io->read_watch) {
>
> + l_io_set_read_handler(io->l_io, NULL, NULL, NULL);
>
>
>
> - return l_io_set_read_handler(io->l_io, read_callback, io, NULL);
>
> + if (!callback) {
>
> + watch_destroy(io->read_watch);
>
> + io->read_watch = NULL;
>
> + return true;
>
> + }
>
> + }
>
> +
>
> + io->read_watch = watch_new(io, callback, user_data, destroy);
>
> +
>
> + result = l_io_set_read_handler(io->l_io, watch_callback, io->read_watch,
>
> + watch_destroy);
>
> +
>
> + if (!result) {
>
> + watch_destroy(io->read_watch);
>
> + io->read_watch = NULL;
>
> + }
>
> +
>
> + return result;
>
>  }
>
>
>
>  bool io_set_write_handler(struct io *io, io_callback_func_t callback,
>
>   void *user_data, io_destroy_func_t destroy)
>
>  {
>
> + bool result;
>
> +
>
>   if (!io || !io->l_io)
>
>   return false;
>
>
>
> - io->write_cb = callback;
>
> - io->write_data = user_data;
>
> - io->write_destroy = destroy;
>
> + if (io->write_watch) {
>
> + l_io_set_write_handler(io->l_io, NULL, NULL, NULL);
>
>
>
> - return l_io_set_write_handler(io->l_io, write_callback, io, NULL);
>
> + if (!callback) {
>
> + watch_destroy(io->write_watch);
>
> + io->write_watch = NULL;
>
> + return true;
>
> + }
>
> + }
>
> +
>
> + io->write_watch = watch_new(io, callback, user_data, destroy);
>
> +
>
> + result = l_io_set_write_handler(io->l_io, watch_callback,
>
> + io->write_watch, watch_destroy);
>
> +
>
> + if (!result) {
>
> + watch_destroy(io->write_watch);
>
> + io->write_watch = NULL;
>
> + }
>
> +
>
> + return result;
>
>  }
>
>
>
>  bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
>
>   void *user_data, io_destroy_func_t destroy)
>
>  {
>
> + bool result;
>
> +
>
>   if (!io || !io->l_io)
>
>   return false;
>
>
>
> - return l_io_set_disconnect_handler(io->l_io, (void *) callback,
>
> - user_data, destroy);
>
> + if (io->disc_watch) {
>
> + l_io_set_disconnect_handler(io->l_io, NULL, NULL, NULL);
>
> +
>
> + if (!callback) {
>
> + watch_destroy(io->disc_watch);
>
> + io->disc_watch = NULL;
>
> + return true;
>
> + }
>
> + }
>
> +
>
> + io->disc_watch = watch_new(io, callback, user_data, destroy);
>
> +
>
> + result = l_io_set_disconnect_handler(io->l_io, disc_callback,
>
> + io->disc_watch, watch_destroy);
>
> +
>
> + if (!result) {
>
> + watch_destroy(io->disc_watch);
>
> + io->disc_watch = NULL;
>
> + }
>
> +
>
> + return result;
>
>  }
>
>
>
>  ssize_t io_send(struct io *io, const struct iovec *iov, int iovcnt)

Applied, thanks.

-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2020-10-19 20:18 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-25 22:38 [PATCH BlueZ] shared/io-ell: Add reference count to io structure Inga Stotland
2020-09-25 22:52 ` [BlueZ] " bluez.test.bot
     [not found] ` <28971312d4000cf290ed1868dc7835aa8e063283.camel@intel.com>
     [not found]   ` <5a8c06c73e1a4a18aea6dcbb33910eac9e93f38f.camel@intel.com>
     [not found]     ` <34b8fe82558fa3467a99181bc5a4a4f1e185b756.camel@intel.com>
2020-10-19 20:17       ` [PATCH BlueZ] " Luiz Augusto von Dentz

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.