Hi, Whenever an interrupt occurs, I need to send a message to the user space.
An RPC device_intr_notify is defined, so the user-level driver can register its port in the kernel. The server side of the RPC is below: io_return_t ds_device_intr_notify (ipc_port_t master_port, int irq, int id, ipc_port_t receive_port) { /* Open must be called on the master device port. */ if (master_port != master_device_port) return D_INVALID_OPERATION; if (irq < 0 || irq >= 16) return D_INVALID_OPERATION; intr_rcv_ports[irq] = receive_port; return 0; } deliver_irq() is to send a notification message to the port registered by the user. The code is below: boolean_t deliver_irq (int irq) { ipc_kmsg_t kmsg; mach_irq_notification_t *n; ipc_port_t dest_port = intr_rcv_ports[irq]; mach_port_t dest = (mach_port_t) dest_port; if (dest == MACH_PORT_NULL) return FALSE; kmsg = ikm_alloc(sizeof *n); if (kmsg == IKM_NULL) return FALSE; ikm_init(kmsg, sizeof *n); n = (mach_irq_notification_t *) &kmsg->ikm_header; mach_msg_header_t *m = &n->irq_header; mach_msg_type_t *t = &n->irq_type; m->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND, 0); m->msgh_size = sizeof *n; m->msgh_seqno = IRQ_NOTIFY_MSGH_SEQNO; m->msgh_local_port = MACH_PORT_NULL; m->msgh_remote_port = MACH_PORT_NULL; m->msgh_id = MACH_NOTIFY_IRQ; t->msgt_name = MACH_MSG_TYPE_INTEGER_32; t->msgt_size = 32; t->msgt_number = 1; t->msgt_inline = TRUE; t->msgt_longform = FALSE; t->msgt_deallocate = FALSE; t->msgt_unused = 0; n->irq_header.msgh_remote_port = dest; n->irq = irq; ipc_port_copy_send (dest_port); ipc_mqueue_send_always(kmsg); return TRUE; } It can work most of time. However, it seems that the code above causes a bug in the kernel. The kernel might crash with the following error: Assertion '(&dest_mqueue->imq_threads)->ithq_base == (receiver)' failed in file "../gnumach/ipc/mach_msg.c", line 998 I traced the stack, and it is: (null):~/gnumach# addr2line -e ../gnumach-build/gnumach 0x117a06 0x117a57 0x145b57 /root/gnumach-build/../gnumach/kern/debug.c:103 ??:0 /root/gnumach-build/../gnumach/ipc/mach_msg.c:892 I don't understand how the assertion can fail here. mach_msg_trap() locks the message queue before accessing it and my code seems to do the same. Could anyone tell me whether I did something wrong in the code above? Thank you, Zheng Da