[tipc] Rework how IPC chan handles gets destroyed
Stop registering shutdown callback for ports and channels.
Instead invoke corresponding shutdown code when last
reference to handle goes away. This way, handle_close is
effectively just decrements handle ref. Stop using handle_close
in favor of handle_decref where appropriate.
Change-Id: I8dff9182bc886f1187cb43c8320ae2c5400eeaee
diff --git a/lib/trusty/include/lib/trusty/ipc.h b/lib/trusty/include/lib/trusty/ipc.h
index 3d25f83..9947ee2 100644
--- a/lib/trusty/include/lib/trusty/ipc.h
+++ b/lib/trusty/include/lib/trusty/ipc.h
@@ -39,7 +39,6 @@
enum {
IPC_PORT_STATE_INVALID = 0,
IPC_PORT_STATE_LISTENING = 1,
- IPC_PORT_STATE_CLOSING = 2,
};
enum {
diff --git a/lib/trusty/ipc.c b/lib/trusty/ipc.c
index 59fe72a..816f58a 100644
--- a/lib/trusty/ipc.c
+++ b/lib/trusty/ipc.c
@@ -60,7 +60,6 @@
static void port_handle_destroy(handle_t *handle);
static uint32_t chan_poll(handle_t *handle, uint32_t emask, bool finalize);
-static void chan_shutdown(handle_t *handle);
static void chan_handle_destroy(handle_t *handle);
static ipc_port_t *port_find_locked(const char *path);
@@ -71,13 +70,11 @@
static struct handle_ops ipc_port_handle_ops = {
.poll = port_poll,
- .shutdown = port_shutdown,
.destroy = port_handle_destroy,
};
static struct handle_ops ipc_chan_handle_ops = {
.poll = chan_poll,
- .shutdown = chan_shutdown,
.destroy = chan_handle_destroy,
};
@@ -174,13 +171,9 @@
LTRACEF("shutting down port %p\n", port);
- /* change status to closing */
- port->state = IPC_PORT_STATE_CLOSING;
-
/* detach it from global list if it is in the list */
if (list_in_list(&port->node)) {
list_delete(&port->node);
- handle_decref(phandle);
}
/* tear down pending connections */
@@ -195,11 +188,6 @@
/* remove connection from the list */
list_delete(&server->node);
chan_del_ref(server, &server->node_ref); /* drop list ref */
-
- /* decrement usage count on port as pending connection
- is gone
- */
- handle_decref(phandle);
}
mutex_release(&ipc_lock);
@@ -215,6 +203,9 @@
ASSERT(phandle);
ASSERT(ipc_is_port(phandle));
+ /* invoke port shutdown first */
+ port_shutdown(phandle);
+
ipc_port_t *port = containerof(phandle, ipc_port_t, handle);
/* pending list should be empty and
@@ -250,7 +241,6 @@
} else {
port->state = IPC_PORT_STATE_LISTENING;
list_add_tail(&ipc_port_list, &port->node);
- handle_incref(&port->handle); /* and inc usage count */
/* go through pending connection list and pick those we can handle */
ipc_chan_t *client, *temp;
@@ -489,29 +479,16 @@
}
}
-/*
- * Called when caller closes handle.
- */
-static void chan_shutdown(handle_t *chandle)
-{
- DEBUG_ASSERT(chandle);
- DEBUG_ASSERT(ipc_is_channel(chandle));
-
- mutex_acquire(&ipc_lock);
-
- ipc_chan_t *chan = containerof(chandle, ipc_chan_t, handle);
-
- chan_shutdown_locked(chan);
-
- mutex_release(&ipc_lock);
-}
-
static void chan_handle_destroy(handle_t *chandle)
{
DEBUG_ASSERT(chandle);
DEBUG_ASSERT(ipc_is_channel(chandle));
ipc_chan_t *chan = containerof(chandle, ipc_chan_t, handle);
+
+ mutex_acquire(&ipc_lock);
+ chan_shutdown_locked(chan);
+ mutex_release(&ipc_lock);
chan_del_ref(chan, &chan->handle_ref);
}
@@ -651,9 +628,6 @@
chan_add_ref(server, &server->node_ref);
list_add_tail(&port->pending_list, &server->node);
- /* bump a ref to the port while there's a pending connection */
- handle_incref(&port->handle);
-
/* Notify port that there is a pending connection */
handle_notify(&port->handle);
@@ -790,21 +764,21 @@
if (ret < 0) {
/* timeout or other error */
- handle_close(chandle);
+ handle_decref(chandle);
return ret;
}
if ((event & IPC_HANDLE_POLL_HUP) &&
!(event & IPC_HANDLE_POLL_MSG)) {
/* hangup and no pending messages */
- handle_close(chandle);
+ handle_decref(chandle);
return ERR_CHANNEL_CLOSED;
}
if (!(event & IPC_HANDLE_POLL_READY)) {
/* not connected */
TRACEF("Unexpected channel state: event = 0x%x\n", event);
- handle_close(chandle);
+ handle_decref(chandle);
return ERR_NOT_READY;
}
}
@@ -812,7 +786,7 @@
ret = uctx_handle_install(ctx, chandle, &handle_id);
if (ret != NO_ERROR) {
/* Failed to install handle into user context */
- handle_close(chandle);
+ handle_decref(chandle);
return (long) ret;
}
@@ -868,9 +842,6 @@
chan_add_ref(server, &tmp_server_ref); /* add local ref */
chan_del_ref(server, &server->node_ref); /* drop list ref */
- /* drop the ref to port we took in connect() */
- handle_decref(&port->handle);
-
client = server->peer;
/* there must be a client, it must be in CONNECTING state and
@@ -941,7 +912,7 @@
err_uuid_copy:
uctx_handle_remove(ctx, new_id, NULL);
err_install:
- handle_close(chandle);
+ handle_decref(chandle);
err_accept:
handle_decref(phandle);
return (long) ret;
diff --git a/lib/trusty/tipc_dev.c b/lib/trusty/tipc_dev.c
index 91bcff3..2e60a0c 100644
--- a/lib/trusty/tipc_dev.c
+++ b/lib/trusty/tipc_dev.c
@@ -308,7 +308,7 @@
local = alloc_local_addr(dev, remote, chan);
if (local == 0) {
LTRACEF("failed to alloc local address\n");
- handle_close(chan);
+ handle_decref(chan);
chan = NULL;
}
mutex_release(&dev->ept_lock);
@@ -371,7 +371,7 @@
handle_set_cookie(chan, NULL);
/* close handle */
- handle_close(chan);
+ handle_decref(chan);
}
free_local_addr(dev, ept_to_addr(dev, ept));
@@ -672,7 +672,7 @@
handle_set_cookie(chan, NULL);
/* close it */
- handle_close(chan);
+ handle_decref(chan);
/* free_local_address */
free_local_addr(dev, local);
@@ -810,7 +810,7 @@
handle_list_del(&dev->handle_list, ept->chan);
handle_set_cookie(ept->chan, NULL);
- handle_close(ept->chan);
+ handle_decref(ept->chan);
free_local_addr(dev, ept_to_addr(dev, ept));
}
mutex_release(&dev->ept_lock);