diff options
author | Justus Winter <justus@gnupg.org> | 2016-02-27 09:10:23 +0100 |
---|---|---|
committer | Justus Winter <justus@gnupg.org> | 2016-02-27 09:10:23 +0100 |
commit | 2cf0c62f09dc2069a9446a5a694bb73dd1322108 (patch) | |
tree | 0cb0d4b951f4ec9efa4686b2b3d9c05c92fed9eb /device/intr.c | |
parent | 9482ee4ba48f8033f7916551f2767f48f9bd0c55 (diff) |
No need for a new kind of notification, we can provide a smoother upgrade path
Diffstat (limited to 'device/intr.c')
-rw-r--r-- | device/intr.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/device/intr.c b/device/intr.c index 143bed3..5033d93 100644 --- a/device/intr.c +++ b/device/intr.c @@ -172,9 +172,23 @@ intr_entry_port_lookup (ipc_port_t port) boolean_t intr_entry_notify (mach_msg_header_t *msg) { - if (msg->msgh_id == MACH_NOTIFY_DEAD_NAME) + struct intr_entry *entry; + + if (msg->msgh_id == MACH_NOTIFY_NO_SENDERS) + { + extern void enable_irq (unsigned int irq_nr); + mach_no_senders_notification_t *ns; + + ns = (mach_no_senders_notification_t *) msg; + entry = intr_entry_port_lookup + ((ipc_port_t) ns->not_header.msgh_remote_port); + assert (entry); + + enable_irq (entry->line); /* entry is not locked here */ + return TRUE; + } + else if (msg->msgh_id == MACH_NOTIFY_DEAD_NAME) { - struct intr_entry *entry; int line; mach_dead_name_notification_t *dn; unsigned long flags; @@ -188,6 +202,7 @@ intr_entry_notify (mach_msg_header_t *msg) line = entry->line; assert (!queue_empty (&intr_queue)); queue_remove (&intr_queue, entry, struct intr_entry *, chain); + remove_user_intr_handler (entry->line, entry); cpu_intr_restore (flags); ipc_port_dealloc_kernel (entry->port); @@ -212,7 +227,8 @@ init_mach_intr_notification (mach_intr_notification_t *n) mach_msg_header_t *m = &n->intr_header; mach_msg_type_t *t = &n->intr_type; - m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0); + m->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_PORT_SEND, + MACH_MSG_TYPE_PORT_SEND); m->msgh_size = sizeof *n; m->msgh_seqno = INTR_NOTIFY_MSGH_SEQNO; m->msgh_local_port = MACH_PORT_NULL; @@ -229,10 +245,11 @@ init_mach_intr_notification (mach_intr_notification_t *n) } static boolean_t -deliver_intr (int line, ipc_port_t dest_port) +deliver_intr (int line, ipc_port_t dest_port, ipc_port_t interrupt_port) { ipc_kmsg_t kmsg; mach_intr_notification_t *n; + ipc_port_t sright, sonce, old; mach_port_t dest = (mach_port_t) dest_port; if (dest == MACH_PORT_NULL) @@ -246,7 +263,17 @@ deliver_intr (int line, ipc_port_t dest_port) n = (mach_intr_notification_t *) &kmsg->ikm_header; *n = mach_intr_notification_template; + /* Arrange no-senders notification. */ + sright = ipc_port_make_send (interrupt_port); + sonce = ipc_port_make_sonce (interrupt_port); + ip_lock (interrupt_port); + ipc_port_nsrequest (interrupt_port, interrupt_port->ip_mscount, + sonce, &old); + if (old != IP_NULL) + ipc_port_release_sonce (old); + n->intr_header.msgh_remote_port = dest; + n->intr_header.msgh_local_port = (mach_port_t) sright; n->line = line; ipc_port_copy_send (dest_port); @@ -269,7 +296,7 @@ init_mach_intr_notification2 (mach_intr_notification2_t *n) m->msgh_seqno = INTR_NOTIFY_MSGH_SEQNO; m->msgh_local_port = MACH_PORT_NULL; m->msgh_remote_port = MACH_PORT_NULL; - m->msgh_id = MACH_INTR_NOTIFY; + m->msgh_id = MACH_INTR_NOTIFY2; t->msgt_name = MACH_MSG_TYPE_INTEGER_32; t->msgt_size = 32; @@ -289,7 +316,7 @@ init_mach_intr_notification2 (mach_intr_notification2_t *n) t->msgt_unused = 0; t = &n->port_type; - t->msgt_name = MACH_MSG_TYPE_MAKE_SEND; + t->msgt_name = MACH_MSG_TYPE_MOVE_SEND; t->msgt_size = 32; t->msgt_number = 1; t->msgt_inline = TRUE; @@ -304,6 +331,7 @@ deliver_intr_notification2 (ipc_port_t notification_port, ipc_port_t interrupt_port) { ipc_kmsg_t kmsg; + ipc_port_t sright, sonce, old; mach_intr_notification2_t *n; assert (notification_port); @@ -317,10 +345,19 @@ deliver_intr_notification2 (ipc_port_t notification_port, n = (mach_intr_notification2_t *) &kmsg->ikm_header; *n = mach_intr_notification2_template; + /* Arrange no-senders notification. */ + sright = ipc_port_make_send (interrupt_port); + sonce = ipc_port_make_sonce (interrupt_port); + ip_lock (interrupt_port); + ipc_port_nsrequest (interrupt_port, interrupt_port->ip_mscount, + sonce, &old); + if (old != IP_NULL) + ipc_port_release_sonce (old); + n->intr_header.msgh_remote_port = (mach_port_t) notification_port; n->line = line; n->count = count; - n->interrupt_port = (mach_port_t) interrupt_port; + n->interrupt_port = (mach_port_t) sright; ipc_port_copy_send (notification_port); ipc_mqueue_send_always(kmsg); @@ -351,16 +388,18 @@ intr_thread () queue_iterate (&intr_queue, e, struct intr_entry *, chain) if (e->interrupts) { + int ok; + ipc_port_t interrupt_port = e->port; + int count = e->interrupts; line = e->line; dest = e->dest; if (e->new_style) { - ipc_port_t interrupt_port = e->port; - int count = e->interrupts; e->interrupts = 0; cpu_intr_restore (flags); - deliver_intr_notification2 (dest, line, count, interrupt_port); + ok = deliver_intr_notification2 (dest, line, count, interrupt_port); + printf ("new: count? %d ok? %d\n", count, ok); cpu_intr_save (&flags); } else @@ -368,8 +407,10 @@ intr_thread () e->interrupts--; cpu_intr_restore (flags); - deliver_intr (line, dest); + deliver_intr (line, dest, interrupt_port); cpu_intr_save (&flags); + + assert (e->interrupts == 0); } /* We cannot assume that e still exists at this point |