[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 1/7] libnotify: add a general notification library
From: |
Justus Winter |
Subject: |
[PATCH 1/7] libnotify: add a general notification library |
Date: |
Mon, 16 Sep 2013 16:08:59 +0200 |
XXX
---
libhurdnotify/Makefile | 28 ++++++
libhurdnotify/notify.c | 251 ++++++++++++++++++++++++++++++++++++++++++++++++
libhurdnotify/notify.h | 73 ++++++++++++++
3 files changed, 352 insertions(+)
create mode 100644 libhurdnotify/Makefile
create mode 100644 libhurdnotify/notify.c
create mode 100644 libhurdnotify/notify.h
diff --git a/libhurdnotify/Makefile b/libhurdnotify/Makefile
new file mode 100644
index 0000000..8c7b780
--- /dev/null
+++ b/libhurdnotify/Makefile
@@ -0,0 +1,28 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Hurd.
+#
+# The GNU Hurd is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2, or (at
+# your option) any later version.
+#
+# The GNU Hurd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>.
+
+dir := libhurdnotify
+makemode := library
+
+libname := libhurdnotify
+SRCS = notify.c
+installhdrs = notify.h
+
+OBJS = $(SRCS:.c=.o)
+HURDLIBS = ihash
+
+include ../Makeconf
diff --git a/libhurdnotify/notify.c b/libhurdnotify/notify.c
new file mode 100644
index 0000000..26bc149
--- /dev/null
+++ b/libhurdnotify/notify.c
@@ -0,0 +1,251 @@
+/* XXX */
+
+#include <hurd/notify.h>
+#include <stdlib.h>
+#include <time.h>
+
+static void hurd_notify_cleanup (hurd_ihash_value_t value, void *arg);
+
+/* XXX */
+void
+hurd_notify_init (hurd_notify_t n,
+ hurd_notify_func_t notify_func,
+ hurd_notify_cleanup_t cleanup_func)
+{
+ hurd_ihash_init (&n->receivers, HURD_IHASH_NO_LOCP);
+ hurd_ihash_set_cleanup (&n->receivers, hurd_notify_cleanup, &n);
+ n->notify_func = notify_func;
+ n->cleanup_func = cleanup_func;
+ n->first = NULL;
+ n->last = NULL;
+}
+
+/* XXX */
+void
+hurd_notify_destroy (hurd_notify_t n)
+{
+ hurd_ihash_destroy (&n->receivers);
+}
+
+/* XXX */
+error_t
+hurd_notify_create (hurd_notify_t *n,
+ hurd_notify_func_t notify_func,
+ hurd_notify_cleanup_t cleanup_func)
+{
+ *n = malloc (sizeof (struct hurd_notify));
+ if (*n == NULL)
+ return ENOMEM;
+
+ hurd_notify_init (*n, notify_func, cleanup_func);
+
+ return 0;
+}
+
+/* XXX */
+void
+hurd_notify_free (hurd_notify_t n)
+{
+ hurd_notify_destroy (n);
+ free (n);
+}
+
+static struct hurd_notify_receiver *
+new_receiver (mach_port_t notify,
+ void *data,
+ struct hurd_notify_receiver *previous,
+ struct hurd_notify_receiver *next)
+{
+ struct hurd_notify_receiver *r;
+ r = malloc (sizeof (struct hurd_notify_receiver));
+ if (! r)
+ return NULL;
+
+ r->port = notify;
+ r->data = data;
+ r->previous = previous;
+ r->next = next;
+ return r;
+}
+
+
+/* XXX */
+error_t
+hurd_notify_prepend (hurd_notify_t n, mach_port_t notify, void *data)
+{
+ error_t err;
+
+ struct hurd_notify_receiver *r;
+ r = new_receiver (notify, data, NULL, n->first);
+ if (! r)
+ return ENOMEM;
+
+ err = hurd_ihash_add (&n->receivers, notify, r);
+ if (err)
+ {
+ free (r);
+ return err;
+ }
+
+ n->first = r;
+ if (! n->last)
+ n->last = r;
+ return 0;
+}
+
+/* XXX */
+error_t
+hurd_notify_append (hurd_notify_t n, mach_port_t notify, void *data)
+{
+ error_t err;
+
+ struct hurd_notify_receiver *r;
+ r = new_receiver (notify, data, n->last, NULL);
+ if (! r)
+ return ENOMEM;
+
+ err = hurd_ihash_add (&n->receivers, notify, r);
+ if (err)
+ {
+ free (r);
+ return err;
+ }
+
+ if (! n->first)
+ n->first = r;
+ n->last = r;
+ return 0;
+}
+
+static void
+hurd_notify_cleanup (hurd_ihash_value_t value, void *arg)
+{
+ struct hurd_notify *n = arg;
+ struct hurd_notify_receiver *r = value;
+
+ if (n->cleanup_func)
+ n->cleanup_func (r);
+
+ if (r->previous)
+ r->previous->next = r->next;
+ else
+ n->first = r->next;
+
+ if (r->next)
+ r->next->previous = r->previous;
+ else
+ n->last = r->previous;
+
+ free (r);
+}
+
+/* XXX */
+int
+hurd_notify_remove (hurd_notify_t n, mach_port_t notify)
+{
+ return hurd_ihash_remove (&n->receivers, notify);
+}
+
+/* XXX */
+error_t
+hurd_notify_do_notify (hurd_notify_t n, void *common_data)
+{
+ error_t err;
+ for (struct hurd_notify_receiver *r = n->first;
+ r; r = r? r->next: n->first)
+ {
+ err = n->notify_func (r->port,
+ MACH_PORT_NULL,
+ r->data,
+ common_data);
+ if (err == MACH_SEND_INVALID_DEST)
+ {
+ hurd_ihash_key_t key = (hurd_ihash_key_t) r->port;
+ r = r->previous?: NULL;
+ hurd_notify_remove (n, key);
+ }
+ }
+
+ return 0;
+}
+
+/* XXX */
+error_t
+hurd_notify_do_notify_wait (hurd_notify_t n,
+ void *common_data,
+ natural_t timeout)
+{
+ error_t err;
+ mach_port_t port_set;
+ err = mach_port_allocate (mach_task_self (),
+ MACH_PORT_RIGHT_PORT_SET,
+ &port_set);
+ if (err)
+ return err;
+
+ int count = 0;
+ for (struct hurd_notify_receiver *r = n->first;
+ r; r = r? r->next: n->first)
+ {
+ mach_port_t reply_port = mach_reply_port ();
+ if (reply_port == MACH_PORT_NULL)
+ return ENOMEM; /* XXX */
+
+ err = mach_port_move_member (mach_task_self (),
+ reply_port,
+ port_set);
+ if (err)
+ return err; /* XXX */
+
+ err = n->notify_func (r->port,
+ reply_port,
+ r->data,
+ common_data);
+ if (err == MACH_SEND_INVALID_DEST)
+ {
+ hurd_ihash_key_t key = (hurd_ihash_key_t) r->port;
+ r = r->previous?: NULL;
+ hurd_notify_remove (n, key);
+ continue;
+ }
+
+ count += 1;
+ }
+
+ time_t start_time = time (NULL);
+ time_t remaining_time;
+ while (count > 0 &&
+ (remaining_time = timeout - (time (NULL) - start_time) * 1000) > 0)
+ {
+ struct Reply {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } reply;
+
+ /* Receive a reply message from any port in our port set with
+ timeout being set to the remaining time. */
+ err = mach_msg (&reply.Head,
+ MACH_RCV_MSG|MACH_MSG_OPTION_NONE|MACH_RCV_TIMEOUT,
+ 0,
+ sizeof (struct Reply),
+ port_set,
+ remaining_time,
+ MACH_PORT_NULL);
+ if (err)
+ return err; /* XXX */
+
+ /* Remove that port from the set. */
+ err = mach_port_move_member (mach_task_self (),
+ reply.Head.msgh_remote_port,
+ MACH_PORT_NULL);
+ if (err)
+ return err; /* XXX */
+
+ mach_port_deallocate (mach_task_self (), reply.Head.msgh_remote_port);
+
+ count -= 1;
+ }
+
+ return 0;
+}
diff --git a/libhurdnotify/notify.h b/libhurdnotify/notify.h
new file mode 100644
index 0000000..7428180
--- /dev/null
+++ b/libhurdnotify/notify.h
@@ -0,0 +1,73 @@
+/* XXX */
+
+#ifndef _HURD_NOTIFY_H
+#define _HURD_NOTIFY_H
+
+#include <hurd/ihash.h>
+#include <mach.h>
+
+/* XXX */
+typedef error_t (*hurd_notify_func_t) (mach_port_t port,
+ mach_port_t reply_port,
+ void *data,
+ void *common_data);
+
+/* Cleanup function. */
+typedef void (*hurd_notify_cleanup_t) (void *data);
+
+/* This structure keeps track of each receiver. */
+struct hurd_notify_receiver
+{
+ mach_port_t port;
+ void *data;
+ struct hurd_notify_receiver *previous;
+ struct hurd_notify_receiver *next;
+};
+
+
+/* XXX */
+struct hurd_notify
+{
+ struct hurd_ihash receivers;
+ hurd_notify_func_t notify_func;
+ hurd_notify_cleanup_t cleanup_func;
+ struct hurd_notify_receiver *first;
+ struct hurd_notify_receiver *last;
+};
+
+typedef struct hurd_notify *hurd_notify_t;
+
+/* XXX */
+void hurd_notify_init (hurd_notify_t n,
+ hurd_notify_func_t notify_func,
+ hurd_notify_cleanup_t cleanup_func);
+
+/* XXX */
+void hurd_notify_destroy (hurd_notify_t n);
+
+/* XXX */
+error_t hurd_notify_create (hurd_notify_t *n,
+ hurd_notify_func_t notify_func,
+ hurd_notify_cleanup_t cleanup_func);
+
+/* XXX */
+void hurd_notify_free (hurd_notify_t n);
+
+/* XXX */
+error_t hurd_notify_prepend (hurd_notify_t n, mach_port_t notify, void *data);
+
+/* XXX */
+error_t hurd_notify_append (hurd_notify_t n, mach_port_t notify, void *data);
+
+/* XXX */
+int hurd_notify_remove (hurd_notify_t n, mach_port_t notify);
+
+/* XXX */
+error_t hurd_notify_do_notify (hurd_notify_t n, void *common_data);
+
+/* XXX */
+error_t hurd_notify_do_notify_wait (hurd_notify_t n,
+ void *common_data,
+ natural_t timeout);
+
+#endif /* _HURD_NOTIFY_H */
--
1.7.10.4
- cgroupfs, /hurd/proc and subhurds, Justus Winter, 2013/09/16
- [PATCH 1/7] libnotify: add a general notification library,
Justus Winter <=
- [PATCH 4/7] proc: implement proc_request_process_change_notification, Justus Winter, 2013/09/16
- [PATCH 5/7] hurd: add proc_request_process_change_notification, Justus Winter, 2013/09/16
- [PATCH 6/7] FIX BUILD, Justus Winter, 2013/09/16
- [PATCH 2/7] init: use libhurdnotify for shutdown notifications, Justus Winter, 2013/09/16
- [PATCH 3/7] hurd: add notification callbacks for the process management, Justus Winter, 2013/09/16
- [PATCH 7/7] XXX: register for new task notifications, Justus Winter, 2013/09/16
- [PATCH] kern: new task notifications, Justus Winter, 2013/09/16
- Re: cgroupfs, /hurd/proc and subhurds, Ludovic Courtès, 2013/09/17