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 -- To UNSUBSCRIBE, email to debian-hurd-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/1379340545-10168-1-git-send-email-4win...@informatik.uni-hamburg.de