kernel: msg: implement asynchronous event messages
This commit is contained in:
@@ -1,16 +1,29 @@
|
||||
#include <kernel/channel.h>
|
||||
#include <kernel/port.h>
|
||||
#include <kernel/printk.h>
|
||||
#include <kernel/thread.h>
|
||||
#include <kernel/util.h>
|
||||
|
||||
#define PORT_CAST(p) OBJECT_C_CAST(struct port, p_base, &port_type, p)
|
||||
|
||||
static kern_status_t port_cleanup(struct object *obj);
|
||||
|
||||
static struct object_type port_type = {
|
||||
.ob_name = "port",
|
||||
.ob_size = sizeof(struct port),
|
||||
.ob_header_offset = offsetof(struct port, p_base),
|
||||
.ob_ops = {
|
||||
.destroy = port_cleanup,
|
||||
},
|
||||
};
|
||||
|
||||
static kern_status_t port_cleanup(struct object *obj, struct queue *q)
|
||||
{
|
||||
struct port *port = PORT_CAST(obj);
|
||||
port_disconnect(port);
|
||||
return KERN_OK;
|
||||
}
|
||||
|
||||
kern_status_t port_type_init(void)
|
||||
{
|
||||
return object_type_register(&port_type);
|
||||
@@ -58,9 +71,26 @@ struct port *port_create(void)
|
||||
kern_status_t port_connect(struct port *port, struct channel *remote)
|
||||
{
|
||||
if (port->p_status != PORT_OFFLINE) {
|
||||
tracek("port_connect: port in bad state (%d)", port->p_status);
|
||||
return KERN_BAD_STATE;
|
||||
}
|
||||
|
||||
struct msg *msg = msg_alloc();
|
||||
if (!msg) {
|
||||
return KERN_NO_MEMORY;
|
||||
}
|
||||
|
||||
msg->msg_status = KMSG_ASYNC;
|
||||
msg->msg_type = KERN_MSG_TYPE_EVENT;
|
||||
msg->msg_event = KERN_MSG_EVENT_CONNECTION;
|
||||
msg->msg_sender_thread = current_thread();
|
||||
msg->msg_sender_port = port;
|
||||
|
||||
unsigned long flags;
|
||||
channel_lock_irqsave(remote, &flags);
|
||||
channel_enqueue_msg(remote, msg);
|
||||
channel_unlock_irqrestore(remote, flags);
|
||||
|
||||
port->p_remote = remote;
|
||||
port->p_status = PORT_READY;
|
||||
return KERN_OK;
|
||||
@@ -69,9 +99,27 @@ kern_status_t port_connect(struct port *port, struct channel *remote)
|
||||
kern_status_t port_disconnect(struct port *port)
|
||||
{
|
||||
if (port->p_status != PORT_READY) {
|
||||
tracek("port_disconnect: port in bad state (%d)",
|
||||
port->p_status);
|
||||
return KERN_BAD_STATE;
|
||||
}
|
||||
|
||||
struct msg *msg = msg_alloc();
|
||||
if (!msg) {
|
||||
return KERN_NO_MEMORY;
|
||||
}
|
||||
|
||||
msg->msg_status = KMSG_ASYNC;
|
||||
msg->msg_type = KERN_MSG_TYPE_EVENT;
|
||||
msg->msg_event = KERN_MSG_EVENT_DISCONNECTION;
|
||||
msg->msg_sender_thread = current_thread();
|
||||
msg->msg_sender_port = port;
|
||||
|
||||
unsigned long flags;
|
||||
channel_lock_irqsave(port->p_remote, &flags);
|
||||
channel_enqueue_msg(port->p_remote, msg);
|
||||
channel_unlock_irqrestore(port->p_remote, flags);
|
||||
|
||||
port->p_remote = NULL;
|
||||
port->p_status = PORT_OFFLINE;
|
||||
return KERN_OK;
|
||||
@@ -84,12 +132,14 @@ kern_status_t port_send_msg(
|
||||
unsigned long *lock_flags)
|
||||
{
|
||||
if (port->p_status != PORT_READY) {
|
||||
tracek("port_send_msg: port in bad state (%d)", port->p_status);
|
||||
return KERN_BAD_STATE;
|
||||
}
|
||||
|
||||
struct thread *self = current_thread();
|
||||
struct msg msg;
|
||||
memset(&msg, 0x0, sizeof msg);
|
||||
msg.msg_type = KERN_MSG_TYPE_DATA;
|
||||
msg.msg_status = KMSG_WAIT_RECEIVE;
|
||||
msg.msg_sender_thread = self;
|
||||
msg.msg_sender_port = port;
|
||||
|
||||
Reference in New Issue
Block a user