diff options
Diffstat (limited to 'debian/patches/700008-Fix-reference-counting-use-dead-name-notification.patch')
-rw-r--r-- | debian/patches/700008-Fix-reference-counting-use-dead-name-notification.patch | 371 |
1 files changed, 0 insertions, 371 deletions
diff --git a/debian/patches/700008-Fix-reference-counting-use-dead-name-notification.patch b/debian/patches/700008-Fix-reference-counting-use-dead-name-notification.patch deleted file mode 100644 index 4b12e3b..0000000 --- a/debian/patches/700008-Fix-reference-counting-use-dead-name-notification.patch +++ /dev/null @@ -1,371 +0,0 @@ -From e5921e151ef397b25db7fe85a325728503a77e9b Mon Sep 17 00:00:00 2001 -From: Justus Winter <justus@gnupg.org> -Date: Fri, 26 Feb 2016 15:24:45 +0100 -Subject: [PATCH gnumach 08/10] Fix reference counting; use dead-name - notification - ---- - device/ds_routines.c | 15 ++--- - device/interrupt.h | 4 +- - device/intr.c | 168 +++++++++++++++++++++++++++++++++++++-------------- - kern/ipc_kobject.c | 8 +++ - kern/ipc_kobject.h | 5 +- - 5 files changed, 141 insertions(+), 59 deletions(-) - -diff --git a/device/ds_routines.c b/device/ds_routines.c -index 7a5dda5..2b9869a 100644 ---- a/device/ds_routines.c -+++ b/device/ds_routines.c -@@ -87,6 +87,7 @@ - #include <device/dev_hdr.h> - #include <device/conf.h> - #include <device/io_req.h> -+#include <device/interrupt.h> - #include <device/ds_routines.h> - #include <device/net_status.h> - #include <device/device_port.h> -@@ -332,6 +333,9 @@ experimental_device_intr_register (ipc_port_t master_port, int line, - if (master_port != master_device_port) - return D_INVALID_OPERATION; - -+ if (receive_port == MACH_PORT_NULL) -+ return D_INVALID_OPERATION; -+ - /* XXX: move to arch-specific */ - if (line < 0 || line >= 16) - return D_INVALID_OPERATION; -@@ -339,17 +343,8 @@ experimental_device_intr_register (ipc_port_t master_port, int line, - ret = insert_intr_entry (line, receive_port, &entry); - if (ret) - return ret; -- // TODO The original port should be replaced -- // when the same device driver calls it again, -- // in order to handle the case that the device driver crashes and restarts. -- ret = install_user_intr_handler (line, flags, entry); -- -- /* If the port is installed successfully, increase its reference by 1. -- * Thus, the port won't be destroyed after its task is terminated. */ -- if (ret == 0) -- ip_reference (receive_port); - -- return ret; -+ return install_user_intr_handler (line, flags, entry); - #endif /* MACH_XEN */ - } - -diff --git a/device/interrupt.h b/device/interrupt.h -index 0de43c2..8adc02d 100644 ---- a/device/interrupt.h -+++ b/device/interrupt.h -@@ -3,12 +3,14 @@ - - struct intr_entry; - boolean_t queue_intr (struct intr_entry *e); --int insert_intr_entry (int line, ipc_port_t dest, struct intr_entry **entry); -+kern_return_t insert_intr_entry (int line, ipc_port_t dest, -+ struct intr_entry **entry); - - int install_user_intr_handler (unsigned int line, - unsigned long flags, - struct intr_entry *entry); - -+boolean_t intr_entry_notify (mach_msg_header_t *msg); - void intr_thread (void); - - #endif /* DEVICE_INTERRUPT_H */ -diff --git a/device/intr.c b/device/intr.c -index 0fa43c5..7a1eccb 100644 ---- a/device/intr.c -+++ b/device/intr.c -@@ -1,7 +1,9 @@ - #include <device/intr.h> - #include <device/ds_routines.h> -+#include <ipc/ipc_space.h> - #include <kern/queue.h> - #include <kern/printf.h> -+#include <mach/notify.h> - - #include "interrupt.h" - -@@ -15,12 +17,14 @@ static struct kmem_cache intr_entry_cache; - - struct intr_entry - { -+ ipc_port_t port; /* We receive notifications on this port. */ - queue_chain_t chain; - ipc_port_t dest; - int line; - /* The number of interrupts occur since last run of intr_thread. */ - int interrupts; - }; -+typedef struct intr_entry *intr_entry_t; - - static queue_head_t intr_queue; - /* The total number of unprocessed interrupts. */ -@@ -30,18 +34,6 @@ static int tot_num_intr; - boolean_t - queue_intr (struct intr_entry *e) - { -- /* The reference of the port was increased when the port was -- * installed. If the reference is 1, it means the port should have -- * been destroyed and I destroy it now. */ -- if (e->dest && e->dest->ip_references == 1) -- { -- /* JW: I don't like running this from an interrupt handler. */ -- ipc_port_release (e->dest); -- e->dest = NULL; -- printf ("irq handler %d: release an dead delivery port\n", e->line); -- return FALSE; -- } -- - cli (); - e->interrupts++; - tot_num_intr++; -@@ -54,20 +46,58 @@ queue_intr (struct intr_entry *e) - /* insert an interrupt entry in the queue. - * This entry exists in the queue until - * the corresponding interrupt port is removed.*/ --int -+kern_return_t - insert_intr_entry (int line, ipc_port_t dest, struct intr_entry **entry) - { -- int err = 0; -+ kern_return_t err = 0; - struct intr_entry *e, *new; - int free = 0; -+ ipc_port_t dnnotify; -+ ipc_port_request_index_t dnindex; - - new = (struct intr_entry *) kmem_cache_alloc (&intr_entry_cache); - if (new == NULL) - return D_NO_MEMORY; -+ -+ /* Allocate port, keeping a reference for it. */ -+ new->port = ipc_port_alloc_kernel (); -+ if (new->port == IP_NULL) -+ { -+ kmem_cache_free (&intr_entry_cache, (vm_offset_t) new); -+ return KERN_RESOURCE_SHORTAGE; -+ } -+ -+ /* Associate the port with the object. */ -+ ipc_kobject_set (new->port, (ipc_kobject_t) new, IKOT_INTR_ENTRY); -+ - new->line = line; - new->dest = dest; - new->interrupts = 0; - -+ /* Register a dead-name notification so that we are notified if the -+ userspace handler dies. */ -+ dnnotify = ipc_port_make_sonce (new->port); -+ ip_lock (dest); -+ /* We use a bogus port name. We don't need it to distinguish the -+ notifications because we register just one per object. */ -+ retry: -+ err = ipc_port_dnrequest (dest, (mach_port_t) 1, dnnotify, &dnindex); -+ if (err) -+ { -+ err = ipc_port_dngrow (dest); -+ /* dest is unlocked */ -+ if (err != KERN_SUCCESS) -+ { -+ ipc_port_release_sonce (dnnotify); -+ kmem_cache_free (&intr_entry_cache, (vm_offset_t) new); -+ return err; -+ } -+ ip_lock (dest); -+ goto retry; -+ } -+ /* dest is locked. dnindex is only valid until we unlock it and we -+ might decide to cancel. */ -+ - /* check whether the intr entry has been in the queue. */ - cli (); - queue_iterate (&intr_queue, e, struct intr_entry *, chain) -@@ -84,11 +114,74 @@ insert_intr_entry (int line, ipc_port_t dest, struct intr_entry **entry) - out: - sti (); - if (free) -- kmem_cache_free (&intr_entry_cache, (vm_offset_t) new); -+ { -+ ipc_port_dncancel (new->dest, (mach_port_t) 1, dnindex); -+ ip_unlock (new->dest); -+ ipc_port_release_sonce (dnnotify); -+ ipc_port_dealloc_kernel (new->port); -+ ipc_port_release_send (new->dest); -+ kmem_cache_free (&intr_entry_cache, (vm_offset_t) new); -+ } -+ else -+ ip_unlock (new->dest); - *entry = new; - return err; - } - -+/* Lookup a intr_entry object by its port. */ -+static intr_entry_t -+intr_entry_port_lookup (ipc_port_t port) -+{ -+ struct intr_entry *entry; -+ -+ if (!IP_VALID(port)) -+ return 0; -+ -+ ip_lock (port); -+ if (ip_active (port) && (ip_kotype (port) == IKOT_INTR_ENTRY)) -+ entry = (struct intr_entry *) port->ip_kobject; -+ else -+ entry = 0; -+ ip_unlock (port); -+ return entry; -+} -+ -+/* Process a dead-name notification for a userspace interrupt handler -+ notification port. */ -+boolean_t -+intr_entry_notify (mach_msg_header_t *msg) -+{ -+ if (msg->msgh_id == MACH_NOTIFY_DEAD_NAME) -+ { -+ struct intr_entry *entry; -+ int line; -+ mach_dead_name_notification_t *dn; -+ -+ dn = (mach_dead_name_notification_t *) msg; -+ entry = intr_entry_port_lookup -+ ((ipc_port_t) dn->not_header.msgh_remote_port); -+ assert (entry); -+ -+ cli (); -+ line = entry->line; -+ assert (!queue_empty (&intr_queue)); -+ queue_remove (&intr_queue, entry, struct intr_entry *, chain); -+ sti (); -+ -+ ipc_port_dealloc_kernel (entry->port); -+ ipc_port_release_send (entry->dest); -+ kmem_cache_free (&intr_entry_cache, (vm_offset_t) entry); -+ -+ printf ("irq handler %d: userspace handler died\n", line); -+ return TRUE; -+ } -+ -+ printf ("intr_entry_notify: strange notification %d\n", -+ msg->msgh_id); -+ return FALSE; -+} -+ -+ - mach_intr_notification_t mach_intr_notification_template; - - static void -@@ -156,43 +249,26 @@ intr_thread () - { - assert_wait ((event_t) &intr_thread, FALSE); - cli (); -- while (tot_num_intr) -- { -- int del = 0; - -- queue_iterate (&intr_queue, e, struct intr_entry *, chain) -+ while (tot_num_intr) -+ queue_iterate (&intr_queue, e, struct intr_entry *, chain) -+ if (e->interrupts) - { -- /* if an entry doesn't have dest port, -- * we should remove it. */ -- if (e->dest == NULL) -- { -- del = 1; -- break; -- } -- -- if (e->interrupts) -- { -- line = e->line; -- dest = e->dest; -- e->interrupts--; -- tot_num_intr--; -- -- sti (); -- deliver_intr (line, dest); -- cli (); -- } -- } -+ line = e->line; -+ dest = e->dest; -+ e->interrupts--; -+ tot_num_intr--; - -- /* remove the entry without dest port from the queue and free it. */ -- if (del) -- { -- assert (!queue_empty (&intr_queue)); -- queue_remove (&intr_queue, e, struct intr_entry *, chain); - sti (); -- kmem_cache_free (&intr_entry_cache, (vm_offset_t) e); -+ deliver_intr (line, dest); - cli (); -+ -+ /* We cannot assume that e still exists at this point -+ because we released the lock. Hence we restart the -+ iteration. */ -+ break; - } -- } -+ - sti (); - thread_block (thread_no_continuation); - } -diff --git a/kern/ipc_kobject.c b/kern/ipc_kobject.c -index c65458b..97c632a 100644 ---- a/kern/ipc_kobject.c -+++ b/kern/ipc_kobject.c -@@ -48,6 +48,7 @@ - #include <vm/vm_object.h> - #include <vm/memory_object_proxy.h> - #include <device/ds_routines.h> -+#include <device/interrupt.h> - - #include <kern/mach.server.h> - #include <ipc/mach_port.server.h> -@@ -326,6 +327,10 @@ ipc_kobject_destroy( - vm_object_pager_wakeup(port); - break; - -+ case IKOT_INTR_ENTRY: -+ /* Do nothing. */ -+ break; -+ - default: - #if MACH_ASSERT - printf("ipc_kobject_destroy: port 0x%p, kobj 0x%lx, type %d\n", -@@ -368,6 +373,9 @@ ipc_kobject_notify(request_header, reply_header) - case IKOT_PAGER_PROXY: - return memory_object_proxy_notify(request_header); - -+ case IKOT_INTR_ENTRY: -+ return intr_entry_notify(request_header); -+ - default: - return FALSE; - } -diff --git a/kern/ipc_kobject.h b/kern/ipc_kobject.h -index 606a66a..6aefea7 100644 ---- a/kern/ipc_kobject.h -+++ b/kern/ipc_kobject.h -@@ -77,9 +77,10 @@ typedef unsigned int ipc_kobject_type_t; - #define IKOT_CLOCK 25 - #define IKOT_CLOCK_CTRL 26 - #define IKOT_PAGER_PROXY 27 -+#define IKOT_INTR_ENTRY 28 - /* << new entries here */ --#define IKOT_UNKNOWN 28 /* magic catchall */ --#define IKOT_MAX_TYPE 29 /* # of IKOT_ types */ -+#define IKOT_UNKNOWN 29 /* magic catchall */ -+#define IKOT_MAX_TYPE 30 /* # of IKOT_ types */ - /* Please keep ipc/ipc_object.c:ikot_print_array up to date */ - - #define is_ipc_kobject(ikot) (ikot != IKOT_NONE) --- -2.1.4 - |