|
@@ -17,26 +17,25 @@
|
|
/*
|
|
/*
|
|
* shim_ipc_helper.c
|
|
* shim_ipc_helper.c
|
|
*
|
|
*
|
|
- * This file contains code to create an IPC helper thread inside library OS
|
|
|
|
- * and maintain bookkeeping of IPC ports.
|
|
|
|
|
|
+ * This file contains code to create an IPC helper thread inside library OS and maintain bookkeeping
|
|
|
|
+ * of IPC ports.
|
|
*/
|
|
*/
|
|
|
|
|
|
-#include <shim_internal.h>
|
|
|
|
-#include <shim_utils.h>
|
|
|
|
-#include <shim_thread.h>
|
|
|
|
|
|
+#include <list.h>
|
|
|
|
+#include <pal.h>
|
|
|
|
+#include <pal_error.h>
|
|
|
|
+#include <shim_checkpoint.h>
|
|
#include <shim_handle.h>
|
|
#include <shim_handle.h>
|
|
|
|
+#include <shim_internal.h>
|
|
#include <shim_ipc.h>
|
|
#include <shim_ipc.h>
|
|
-#include <shim_checkpoint.h>
|
|
|
|
#include <shim_profile.h>
|
|
#include <shim_profile.h>
|
|
-
|
|
|
|
-#include <pal.h>
|
|
|
|
-#include <pal_error.h>
|
|
|
|
-#include <list.h>
|
|
|
|
|
|
+#include <shim_thread.h>
|
|
|
|
+#include <shim_utils.h>
|
|
|
|
|
|
#define IPC_HELPER_STACK_SIZE (g_pal_alloc_align * 4)
|
|
#define IPC_HELPER_STACK_SIZE (g_pal_alloc_align * 4)
|
|
|
|
|
|
-#define PORT_MGR_ALLOC 32
|
|
|
|
-#define OBJ_TYPE struct shim_ipc_port
|
|
|
|
|
|
+#define PORT_MGR_ALLOC 32
|
|
|
|
+#define OBJ_TYPE struct shim_ipc_port
|
|
#include "memmgr.h"
|
|
#include "memmgr.h"
|
|
static MEM_MGR port_mgr;
|
|
static MEM_MGR port_mgr;
|
|
|
|
|
|
@@ -46,7 +45,7 @@ static LISTP_TYPE(shim_ipc_port) port_list;
|
|
static enum { HELPER_NOTALIVE, HELPER_ALIVE } ipc_helper_state;
|
|
static enum { HELPER_NOTALIVE, HELPER_ALIVE } ipc_helper_state;
|
|
|
|
|
|
static struct shim_thread* ipc_helper_thread;
|
|
static struct shim_thread* ipc_helper_thread;
|
|
-static struct shim_lock ipc_helper_lock;
|
|
|
|
|
|
+static struct shim_lock ipc_helper_lock;
|
|
|
|
|
|
static AEVENTTYPE install_new_event;
|
|
static AEVENTTYPE install_new_event;
|
|
|
|
|
|
@@ -54,38 +53,38 @@ static int create_ipc_helper(void);
|
|
static int ipc_resp_callback(struct shim_ipc_msg* msg, struct shim_ipc_port* port);
|
|
static int ipc_resp_callback(struct shim_ipc_msg* msg, struct shim_ipc_port* port);
|
|
|
|
|
|
static ipc_callback ipc_callbacks[IPC_CODE_NUM] = {
|
|
static ipc_callback ipc_callbacks[IPC_CODE_NUM] = {
|
|
- /* RESP */ &ipc_resp_callback,
|
|
|
|
- /* CHECKPOINT */ &ipc_checkpoint_callback,
|
|
|
|
|
|
+ /* RESP */ &ipc_resp_callback,
|
|
|
|
+ /* CHECKPOINT */ &ipc_checkpoint_callback,
|
|
|
|
|
|
/* parents and children */
|
|
/* parents and children */
|
|
- /* CLD_EXIT */ &ipc_cld_exit_callback,
|
|
|
|
|
|
+ /* CLD_EXIT */ &ipc_cld_exit_callback,
|
|
|
|
|
|
#ifdef PROFILE
|
|
#ifdef PROFILE
|
|
- /* CLD_PROFILE */ &ipc_cld_profile_callback,
|
|
|
|
|
|
+ /* CLD_PROFILE */ &ipc_cld_profile_callback,
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* pid namespace */
|
|
/* pid namespace */
|
|
IPC_NS_CALLBACKS(pid)
|
|
IPC_NS_CALLBACKS(pid)
|
|
- /* PID_KILL */ &ipc_pid_kill_callback,
|
|
|
|
- /* PID_GETSTATUS */ &ipc_pid_getstatus_callback,
|
|
|
|
- /* PID_RETSTATUS */ &ipc_pid_retstatus_callback,
|
|
|
|
- /* PID_GETMETA */ &ipc_pid_getmeta_callback,
|
|
|
|
- /* PID_RETMETA */ &ipc_pid_retmeta_callback,
|
|
|
|
- /* PID_NOP */ &ipc_pid_nop_callback,
|
|
|
|
- /* PID_SENDRPC */ &ipc_pid_sendrpc_callback,
|
|
|
|
|
|
+ /* PID_KILL */ &ipc_pid_kill_callback,
|
|
|
|
+ /* PID_GETSTATUS */ &ipc_pid_getstatus_callback,
|
|
|
|
+ /* PID_RETSTATUS */ &ipc_pid_retstatus_callback,
|
|
|
|
+ /* PID_GETMETA */ &ipc_pid_getmeta_callback,
|
|
|
|
+ /* PID_RETMETA */ &ipc_pid_retmeta_callback,
|
|
|
|
+ /* PID_NOP */ &ipc_pid_nop_callback,
|
|
|
|
+ /* PID_SENDRPC */ &ipc_pid_sendrpc_callback,
|
|
|
|
|
|
/* sysv namespace */
|
|
/* sysv namespace */
|
|
IPC_NS_CALLBACKS(sysv)
|
|
IPC_NS_CALLBACKS(sysv)
|
|
IPC_NS_KEY_CALLBACKS(sysv)
|
|
IPC_NS_KEY_CALLBACKS(sysv)
|
|
- /* SYSV_DELRES */ &ipc_sysv_delres_callback,
|
|
|
|
- /* SYSV_MOVRES */ &ipc_sysv_movres_callback,
|
|
|
|
- /* SYSV_MSGSND */ &ipc_sysv_msgsnd_callback,
|
|
|
|
- /* SYSV_MSGRCV */ &ipc_sysv_msgrcv_callback,
|
|
|
|
- /* SYSV_MSGMOV */ &ipc_sysv_msgmov_callback,
|
|
|
|
- /* SYSV_SEMOP */ &ipc_sysv_semop_callback,
|
|
|
|
- /* SYSV_SEMCTL */ &ipc_sysv_semctl_callback,
|
|
|
|
- /* SYSV_SEMRET */ &ipc_sysv_semret_callback,
|
|
|
|
- /* SYSV_SEMMOV */ &ipc_sysv_semmov_callback,
|
|
|
|
|
|
+ /* SYSV_DELRES */ &ipc_sysv_delres_callback,
|
|
|
|
+ /* SYSV_MOVRES */ &ipc_sysv_movres_callback,
|
|
|
|
+ /* SYSV_MSGSND */ &ipc_sysv_msgsnd_callback,
|
|
|
|
+ /* SYSV_MSGRCV */ &ipc_sysv_msgrcv_callback,
|
|
|
|
+ /* SYSV_MSGMOV */ &ipc_sysv_msgmov_callback,
|
|
|
|
+ /* SYSV_SEMOP */ &ipc_sysv_semop_callback,
|
|
|
|
+ /* SYSV_SEMCTL */ &ipc_sysv_semctl_callback,
|
|
|
|
+ /* SYSV_SEMRET */ &ipc_sysv_semret_callback,
|
|
|
|
+ /* SYSV_SEMMOV */ &ipc_sysv_semmov_callback,
|
|
};
|
|
};
|
|
|
|
|
|
static int init_self_ipc_port(void) {
|
|
static int init_self_ipc_port(void) {
|
|
@@ -102,11 +101,8 @@ static int init_self_ipc_port(void) {
|
|
/* execve case: inherited IPC port from parent process */
|
|
/* execve case: inherited IPC port from parent process */
|
|
assert(cur_process.self->pal_handle && !qstrempty(&cur_process.self->uri));
|
|
assert(cur_process.self->pal_handle && !qstrempty(&cur_process.self->uri));
|
|
|
|
|
|
- add_ipc_port_by_id(cur_process.self->vmid,
|
|
|
|
- cur_process.self->pal_handle,
|
|
|
|
- IPC_PORT_SERVER,
|
|
|
|
- /*fini=*/NULL,
|
|
|
|
- &cur_process.self->port);
|
|
|
|
|
|
+ add_ipc_port_by_id(cur_process.self->vmid, cur_process.self->pal_handle, IPC_PORT_SERVER,
|
|
|
|
+ /*fini=*/NULL, &cur_process.self->port);
|
|
}
|
|
}
|
|
|
|
|
|
unlock(&cur_process.lock);
|
|
unlock(&cur_process.lock);
|
|
@@ -122,19 +118,17 @@ static int init_parent_ipc_port(void) {
|
|
lock(&cur_process.lock);
|
|
lock(&cur_process.lock);
|
|
assert(cur_process.parent && cur_process.parent->vmid);
|
|
assert(cur_process.parent && cur_process.parent->vmid);
|
|
|
|
|
|
- /* for execve case, my parent is the parent of my parent (current
|
|
|
|
- * process transparently inherits the "real" parent through already
|
|
|
|
- * opened pal_handle on "temporary" parent's cur_process.parent) */
|
|
|
|
|
|
+ /* for execve case, my parent is the parent of my parent (current process transparently inherits
|
|
|
|
+ * the "real" parent through already opened pal_handle on "temporary" parent's
|
|
|
|
+ * cur_process.parent) */
|
|
if (!cur_process.parent->pal_handle) {
|
|
if (!cur_process.parent->pal_handle) {
|
|
/* for clone/fork case, parent is connected on parent_process */
|
|
/* for clone/fork case, parent is connected on parent_process */
|
|
cur_process.parent->pal_handle = PAL_CB(parent_process);
|
|
cur_process.parent->pal_handle = PAL_CB(parent_process);
|
|
}
|
|
}
|
|
|
|
|
|
- add_ipc_port_by_id(cur_process.parent->vmid,
|
|
|
|
- cur_process.parent->pal_handle,
|
|
|
|
|
|
+ add_ipc_port_by_id(cur_process.parent->vmid, cur_process.parent->pal_handle,
|
|
IPC_PORT_DIRPRT | IPC_PORT_LISTEN,
|
|
IPC_PORT_DIRPRT | IPC_PORT_LISTEN,
|
|
- /*fini=*/NULL,
|
|
|
|
- &cur_process.parent->port);
|
|
|
|
|
|
+ /*fini=*/NULL, &cur_process.parent->port);
|
|
|
|
|
|
unlock(&cur_process.lock);
|
|
unlock(&cur_process.lock);
|
|
return 0;
|
|
return 0;
|
|
@@ -147,9 +141,8 @@ static int init_ns_ipc_port(int ns_idx) {
|
|
}
|
|
}
|
|
|
|
|
|
if (!cur_process.ns[ns_idx]->pal_handle && qstrempty(&cur_process.ns[ns_idx]->uri)) {
|
|
if (!cur_process.ns[ns_idx]->pal_handle && qstrempty(&cur_process.ns[ns_idx]->uri)) {
|
|
- /* there is no connection to NS leader via PAL handle and there is no
|
|
|
|
- * URI to find NS leader: do not create NS IPC port now, it will be
|
|
|
|
- * created on-demand during NS leader lookup */
|
|
|
|
|
|
+ /* there is no connection to NS leader via PAL handle and there is no URI to find NS leader:
|
|
|
|
+ * do not create NS IPC port now, it will be created on-demand during NS leader lookup */
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -157,7 +150,8 @@ static int init_ns_ipc_port(int ns_idx) {
|
|
|
|
|
|
if (!cur_process.ns[ns_idx]->pal_handle) {
|
|
if (!cur_process.ns[ns_idx]->pal_handle) {
|
|
debug("Reconnecting IPC port %s\n", qstrgetstr(&cur_process.ns[ns_idx]->uri));
|
|
debug("Reconnecting IPC port %s\n", qstrgetstr(&cur_process.ns[ns_idx]->uri));
|
|
- cur_process.ns[ns_idx]->pal_handle = DkStreamOpen(qstrgetstr(&cur_process.ns[ns_idx]->uri), 0, 0, 0, 0);
|
|
|
|
|
|
+ cur_process.ns[ns_idx]->pal_handle =
|
|
|
|
+ DkStreamOpen(qstrgetstr(&cur_process.ns[ns_idx]->uri), 0, 0, 0, 0);
|
|
if (!cur_process.ns[ns_idx]->pal_handle) {
|
|
if (!cur_process.ns[ns_idx]->pal_handle) {
|
|
unlock(&cur_process.lock);
|
|
unlock(&cur_process.lock);
|
|
return -PAL_ERRNO;
|
|
return -PAL_ERRNO;
|
|
@@ -165,11 +159,9 @@ static int init_ns_ipc_port(int ns_idx) {
|
|
}
|
|
}
|
|
|
|
|
|
IDTYPE type = (ns_idx == PID_NS) ? IPC_PORT_PIDLDR : IPC_PORT_SYSVLDR;
|
|
IDTYPE type = (ns_idx == PID_NS) ? IPC_PORT_PIDLDR : IPC_PORT_SYSVLDR;
|
|
- add_ipc_port_by_id(cur_process.ns[ns_idx]->vmid,
|
|
|
|
- cur_process.ns[ns_idx]->pal_handle,
|
|
|
|
|
|
+ add_ipc_port_by_id(cur_process.ns[ns_idx]->vmid, cur_process.ns[ns_idx]->pal_handle,
|
|
type | IPC_PORT_LISTEN,
|
|
type | IPC_PORT_LISTEN,
|
|
- /*fini=*/NULL,
|
|
|
|
- &cur_process.ns[ns_idx]->port);
|
|
|
|
|
|
+ /*fini=*/NULL, &cur_process.ns[ns_idx]->port);
|
|
|
|
|
|
unlock(&cur_process.lock);
|
|
unlock(&cur_process.lock);
|
|
return 0;
|
|
return 0;
|
|
@@ -192,16 +184,14 @@ int init_ipc_ports(void) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
int init_ipc_helper(void) {
|
|
int init_ipc_helper(void) {
|
|
/* early enough in init, can write global vars without the lock */
|
|
/* early enough in init, can write global vars without the lock */
|
|
ipc_helper_state = HELPER_NOTALIVE;
|
|
ipc_helper_state = HELPER_NOTALIVE;
|
|
create_lock(&ipc_helper_lock);
|
|
create_lock(&ipc_helper_lock);
|
|
create_event(&install_new_event);
|
|
create_event(&install_new_event);
|
|
|
|
|
|
- /* some IPC ports were already added before this point, so spawn IPC
|
|
|
|
- * helper thread (and enable locking mechanisms if not done already
|
|
|
|
- * since we are going in multi-threaded mode) */
|
|
|
|
|
|
+ /* some IPC ports were already added before this point, so spawn IPC helper thread (and enable
|
|
|
|
+ * locking mechanisms if not done already since we are going in multi-threaded mode) */
|
|
enable_locking();
|
|
enable_locking();
|
|
lock(&ipc_helper_lock);
|
|
lock(&ipc_helper_lock);
|
|
create_ipc_helper();
|
|
create_ipc_helper();
|
|
@@ -261,8 +251,7 @@ void put_ipc_port(struct shim_ipc_port* port) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-static void __add_ipc_port(struct shim_ipc_port* port, IDTYPE vmid,
|
|
|
|
- IDTYPE type, port_fini fini) {
|
|
|
|
|
|
+static void __add_ipc_port(struct shim_ipc_port* port, IDTYPE vmid, IDTYPE type, port_fini fini) {
|
|
port->type |= type;
|
|
port->type |= type;
|
|
if (vmid && !port->vmid)
|
|
if (vmid && !port->vmid)
|
|
port->vmid = vmid;
|
|
port->vmid = vmid;
|
|
@@ -273,7 +262,7 @@ static void __add_ipc_port(struct shim_ipc_port* port, IDTYPE vmid,
|
|
__UNUSED(found_empty_slot);
|
|
__UNUSED(found_empty_slot);
|
|
for (int i = 0; i < MAX_IPC_PORT_FINI_CB; i++)
|
|
for (int i = 0; i < MAX_IPC_PORT_FINI_CB; i++)
|
|
if (!port->fini[i] || port->fini[i] == fini) {
|
|
if (!port->fini[i] || port->fini[i] == fini) {
|
|
- port->fini[i] = fini;
|
|
|
|
|
|
+ port->fini[i] = fini;
|
|
found_empty_slot = true;
|
|
found_empty_slot = true;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
@@ -292,8 +281,8 @@ static void __add_ipc_port(struct shim_ipc_port* port, IDTYPE vmid,
|
|
}
|
|
}
|
|
|
|
|
|
static void __del_ipc_port(struct shim_ipc_port* port) {
|
|
static void __del_ipc_port(struct shim_ipc_port* port) {
|
|
- debug("Deleting port %p (handle %p) of process %u\n",
|
|
|
|
- port, port->pal_handle, port->vmid & 0xFFFF);
|
|
|
|
|
|
+ debug("Deleting port %p (handle %p) of process %u\n", port, port->pal_handle,
|
|
|
|
+ port->vmid & 0xFFFF);
|
|
|
|
|
|
DkStreamDelete(port->pal_handle, 0);
|
|
DkStreamDelete(port->pal_handle, 0);
|
|
LISTP_DEL_INIT(port, &port_list, list);
|
|
LISTP_DEL_INIT(port, &port_list, list);
|
|
@@ -306,8 +295,8 @@ static void __del_ipc_port(struct shim_ipc_port* port) {
|
|
LISTP_DEL_INIT(msg, &port->msgs, list);
|
|
LISTP_DEL_INIT(msg, &port->msgs, list);
|
|
msg->retval = -ECONNRESET;
|
|
msg->retval = -ECONNRESET;
|
|
if (msg->thread) {
|
|
if (msg->thread) {
|
|
- debug("Deleted pending message on port %p, wake up blocking thread %d\n",
|
|
|
|
- port, msg->thread->tid);
|
|
|
|
|
|
+ debug("Deleted pending message on port %p, wake up blocking thread %d\n", port,
|
|
|
|
+ msg->thread->tid);
|
|
thread_wakeup(msg->thread);
|
|
thread_wakeup(msg->thread);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -321,18 +310,17 @@ static void __del_ipc_port(struct shim_ipc_port* port) {
|
|
}
|
|
}
|
|
|
|
|
|
void add_ipc_port(struct shim_ipc_port* port, IDTYPE vmid, IDTYPE type, port_fini fini) {
|
|
void add_ipc_port(struct shim_ipc_port* port, IDTYPE vmid, IDTYPE type, port_fini fini) {
|
|
- debug("Adding port %p (handle %p) for process %u (type=%04x)\n",
|
|
|
|
- port, port->pal_handle, port->vmid & 0xFFFF, type);
|
|
|
|
|
|
+ debug("Adding port %p (handle %p) for process %u (type=%04x)\n", port, port->pal_handle,
|
|
|
|
+ port->vmid & 0xFFFF, type);
|
|
|
|
|
|
lock(&ipc_helper_lock);
|
|
lock(&ipc_helper_lock);
|
|
__add_ipc_port(port, vmid, type, fini);
|
|
__add_ipc_port(port, vmid, type, fini);
|
|
unlock(&ipc_helper_lock);
|
|
unlock(&ipc_helper_lock);
|
|
}
|
|
}
|
|
|
|
|
|
-void add_ipc_port_by_id(IDTYPE vmid, PAL_HANDLE hdl, IDTYPE type,
|
|
|
|
- port_fini fini, struct shim_ipc_port** portptr) {
|
|
|
|
- debug("Adding port (handle %p) for process %u (type %04x)\n",
|
|
|
|
- hdl, vmid & 0xFFFF, type);
|
|
|
|
|
|
+void add_ipc_port_by_id(IDTYPE vmid, PAL_HANDLE hdl, IDTYPE type, port_fini fini,
|
|
|
|
+ struct shim_ipc_port** portptr) {
|
|
|
|
+ debug("Adding port (handle %p) for process %u (type %04x)\n", hdl, vmid & 0xFFFF, type);
|
|
|
|
|
|
struct shim_ipc_port* port = NULL;
|
|
struct shim_ipc_port* port = NULL;
|
|
if (portptr)
|
|
if (portptr)
|
|
@@ -341,14 +329,15 @@ void add_ipc_port_by_id(IDTYPE vmid, PAL_HANDLE hdl, IDTYPE type,
|
|
assert(hdl);
|
|
assert(hdl);
|
|
lock(&ipc_helper_lock);
|
|
lock(&ipc_helper_lock);
|
|
|
|
|
|
- /* check if port with this PAL handle already exists, then we only
|
|
|
|
- * need to update its vmid, type, and fini callback */
|
|
|
|
|
|
+ /* check if port with this PAL handle already exists, then we only need to update its vmid,
|
|
|
|
+ * type, and fini callback */
|
|
struct shim_ipc_port* tmp;
|
|
struct shim_ipc_port* tmp;
|
|
- LISTP_FOR_EACH_ENTRY(tmp, &port_list, list)
|
|
|
|
|
|
+ LISTP_FOR_EACH_ENTRY(tmp, &port_list, list) {
|
|
if (tmp->pal_handle == hdl) {
|
|
if (tmp->pal_handle == hdl) {
|
|
port = tmp;
|
|
port = tmp;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
if (!port) {
|
|
if (!port) {
|
|
/* port does not yet exist, create it */
|
|
/* port does not yet exist, create it */
|
|
@@ -399,8 +388,9 @@ void del_all_ipc_ports(void) {
|
|
|
|
|
|
struct shim_ipc_port* port;
|
|
struct shim_ipc_port* port;
|
|
struct shim_ipc_port* tmp;
|
|
struct shim_ipc_port* tmp;
|
|
- LISTP_FOR_EACH_ENTRY_SAFE(port, tmp, &port_list, list)
|
|
|
|
|
|
+ LISTP_FOR_EACH_ENTRY_SAFE(port, tmp, &port_list, list) {
|
|
__del_ipc_port(port);
|
|
__del_ipc_port(port);
|
|
|
|
+ }
|
|
|
|
|
|
unlock(&ipc_helper_lock);
|
|
unlock(&ipc_helper_lock);
|
|
}
|
|
}
|
|
@@ -414,8 +404,8 @@ struct shim_ipc_port* lookup_ipc_port(IDTYPE vmid, IDTYPE type) {
|
|
struct shim_ipc_port* tmp;
|
|
struct shim_ipc_port* tmp;
|
|
LISTP_FOR_EACH_ENTRY(tmp, &port_list, list) {
|
|
LISTP_FOR_EACH_ENTRY(tmp, &port_list, list) {
|
|
if (tmp->vmid == vmid && (tmp->type & type)) {
|
|
if (tmp->vmid == vmid && (tmp->type & type)) {
|
|
- debug("Found port %p (handle %p) for process %u (type %04x)\n",
|
|
|
|
- tmp, tmp->pal_handle, tmp->vmid & 0xFFFF, tmp->type);
|
|
|
|
|
|
+ debug("Found port %p (handle %p) for process %u (type %04x)\n", tmp, tmp->pal_handle,
|
|
|
|
+ tmp->vmid & 0xFFFF, tmp->type);
|
|
port = tmp;
|
|
port = tmp;
|
|
__get_ipc_port(port);
|
|
__get_ipc_port(port);
|
|
break;
|
|
break;
|
|
@@ -437,9 +427,9 @@ int broadcast_ipc(struct shim_ipc_msg* msg, int target_type, struct shim_ipc_por
|
|
assert(target_type);
|
|
assert(target_type);
|
|
lock(&ipc_helper_lock);
|
|
lock(&ipc_helper_lock);
|
|
|
|
|
|
- /* Collect all ports with appropriate types. In common case, stack-allocated
|
|
|
|
- * array of PORTS_ON_STACK_CNT ports is enough. If there are more ports, we
|
|
|
|
- * will allocate a bigger array on the heap and collect all ports again. */
|
|
|
|
|
|
+ /* Collect all ports with appropriate types. In common case, stack-allocated array of
|
|
|
|
+ * PORTS_ON_STACK_CNT ports is enough. If there are more ports, we will allocate a bigger array
|
|
|
|
+ * on the heap and collect all ports again. */
|
|
struct shim_ipc_port* target_ports_stack[PORTS_ON_STACK_CNT];
|
|
struct shim_ipc_port* target_ports_stack[PORTS_ON_STACK_CNT];
|
|
LISTP_FOR_EACH_ENTRY(port, &port_list, list) {
|
|
LISTP_FOR_EACH_ENTRY(port, &port_list, list) {
|
|
if (port == exclude_port)
|
|
if (port == exclude_port)
|
|
@@ -453,11 +443,11 @@ int broadcast_ipc(struct shim_ipc_msg* msg, int target_type, struct shim_ipc_por
|
|
target_ports = target_ports_stack;
|
|
target_ports = target_ports_stack;
|
|
|
|
|
|
if (target_ports_cnt > PORTS_ON_STACK_CNT) {
|
|
if (target_ports_cnt > PORTS_ON_STACK_CNT) {
|
|
- /* Rare case when there are more than PORTS_ON_STACK_CNT ports. Allocate
|
|
|
|
- * big-enough array on the heap and collect all ports again. */
|
|
|
|
|
|
+ /* Rare case when there are more than PORTS_ON_STACK_CNT ports. Allocate big-enough array on
|
|
|
|
+ * the heap and collect all ports again. */
|
|
size_t cnt = 0;
|
|
size_t cnt = 0;
|
|
struct shim_ipc_port** target_ports_heap =
|
|
struct shim_ipc_port** target_ports_heap =
|
|
- malloc(sizeof(struct shim_ipc_port *) * target_ports_cnt);
|
|
|
|
|
|
+ malloc(sizeof(struct shim_ipc_port*) * target_ports_cnt);
|
|
|
|
|
|
LISTP_FOR_EACH_ENTRY(port, &port_list, list) {
|
|
LISTP_FOR_EACH_ENTRY(port, &port_list, list) {
|
|
if (port == exclude_port)
|
|
if (port == exclude_port)
|
|
@@ -500,7 +490,7 @@ out:
|
|
}
|
|
}
|
|
|
|
|
|
static int ipc_resp_callback(struct shim_ipc_msg* msg, struct shim_ipc_port* port) {
|
|
static int ipc_resp_callback(struct shim_ipc_msg* msg, struct shim_ipc_port* port) {
|
|
- struct shim_ipc_resp* resp = (struct shim_ipc_resp*) &msg->msg;
|
|
|
|
|
|
+ struct shim_ipc_resp* resp = (struct shim_ipc_resp*)&msg->msg;
|
|
debug("IPC callback from %u: IPC_RESP(%d)\n", msg->src & 0xFFFF, resp->retval);
|
|
debug("IPC callback from %u: IPC_RESP(%d)\n", msg->src & 0xFFFF, resp->retval);
|
|
|
|
|
|
if (!msg->seq)
|
|
if (!msg->seq)
|
|
@@ -524,12 +514,12 @@ int send_response_ipc_message(struct shim_ipc_port* port, IDTYPE dest, int ret,
|
|
ret = (ret == RESPONSE_CALLBACK) ? 0 : ret;
|
|
ret = (ret == RESPONSE_CALLBACK) ? 0 : ret;
|
|
|
|
|
|
/* create IPC_RESP msg to send to dest, with sequence number seq, and in-body retval ret */
|
|
/* create IPC_RESP msg to send to dest, with sequence number seq, and in-body retval ret */
|
|
- size_t total_msg_size = get_ipc_msg_size(sizeof(struct shim_ipc_resp));
|
|
|
|
|
|
+ size_t total_msg_size = get_ipc_msg_size(sizeof(struct shim_ipc_resp));
|
|
struct shim_ipc_msg* resp_msg = __alloca(total_msg_size);
|
|
struct shim_ipc_msg* resp_msg = __alloca(total_msg_size);
|
|
init_ipc_msg(resp_msg, IPC_RESP, total_msg_size, dest);
|
|
init_ipc_msg(resp_msg, IPC_RESP, total_msg_size, dest);
|
|
resp_msg->seq = seq;
|
|
resp_msg->seq = seq;
|
|
|
|
|
|
- struct shim_ipc_resp* resp = (struct shim_ipc_resp *)resp_msg->msg;
|
|
|
|
|
|
+ struct shim_ipc_resp* resp = (struct shim_ipc_resp*)resp_msg->msg;
|
|
resp->retval = ret;
|
|
resp->retval = ret;
|
|
|
|
|
|
debug("IPC send to %u: IPC_RESP(%d)\n", resp_msg->dst & 0xFFFF, ret);
|
|
debug("IPC send to %u: IPC_RESP(%d)\n", resp_msg->dst & 0xFFFF, ret);
|
|
@@ -539,11 +529,11 @@ int send_response_ipc_message(struct shim_ipc_port* port, IDTYPE dest, int ret,
|
|
static int receive_ipc_message(struct shim_ipc_port* port) {
|
|
static int receive_ipc_message(struct shim_ipc_port* port) {
|
|
int ret;
|
|
int ret;
|
|
size_t readahead = IPC_MSG_MINIMAL_SIZE * 2;
|
|
size_t readahead = IPC_MSG_MINIMAL_SIZE * 2;
|
|
- size_t bufsize = IPC_MSG_MINIMAL_SIZE + readahead;
|
|
|
|
|
|
+ size_t bufsize = IPC_MSG_MINIMAL_SIZE + readahead;
|
|
|
|
|
|
struct shim_ipc_msg* msg = malloc(bufsize);
|
|
struct shim_ipc_msg* msg = malloc(bufsize);
|
|
- size_t expected_size = IPC_MSG_MINIMAL_SIZE;
|
|
|
|
- size_t bytes = 0;
|
|
|
|
|
|
+ size_t expected_size = IPC_MSG_MINIMAL_SIZE;
|
|
|
|
+ size_t bytes = 0;
|
|
|
|
|
|
do {
|
|
do {
|
|
while (bytes < expected_size) {
|
|
while (bytes < expected_size) {
|
|
@@ -557,14 +547,16 @@ static int receive_ipc_message(struct shim_ipc_port* port) {
|
|
msg = tmp_buf;
|
|
msg = tmp_buf;
|
|
}
|
|
}
|
|
|
|
|
|
- PAL_NUM read = DkStreamRead(port->pal_handle, /*offset=*/0, expected_size - bytes + readahead,
|
|
|
|
- (void *) msg + bytes, NULL, 0);
|
|
|
|
|
|
+ PAL_NUM read =
|
|
|
|
+ DkStreamRead(port->pal_handle, /*offset=*/0, expected_size - bytes + readahead,
|
|
|
|
+ (void*)msg + bytes, NULL, 0);
|
|
|
|
|
|
if (read == PAL_STREAM_ERROR) {
|
|
if (read == PAL_STREAM_ERROR) {
|
|
if (PAL_ERRNO == EINTR || PAL_ERRNO == EAGAIN || PAL_ERRNO == EWOULDBLOCK)
|
|
if (PAL_ERRNO == EINTR || PAL_ERRNO == EAGAIN || PAL_ERRNO == EWOULDBLOCK)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- debug("Port %p (handle %p) closed while receiving IPC message\n", port, port->pal_handle);
|
|
|
|
|
|
+ debug("Port %p (handle %p) closed while receiving IPC message\n", port,
|
|
|
|
+ port->pal_handle);
|
|
del_ipc_port_fini(port, -ECHILD);
|
|
del_ipc_port_fini(port, -ECHILD);
|
|
ret = -PAL_ERRNO;
|
|
ret = -PAL_ERRNO;
|
|
goto out;
|
|
goto out;
|
|
@@ -577,8 +569,11 @@ static int receive_ipc_message(struct shim_ipc_port* port) {
|
|
expected_size = msg->size;
|
|
expected_size = msg->size;
|
|
}
|
|
}
|
|
|
|
|
|
- debug("Received IPC message from port %p (handle %p): code=%d size=%lu src=%u dst=%u seq=%lx\n",
|
|
|
|
- port, port->pal_handle, msg->code, msg->size, msg->src & 0xFFFF, msg->dst & 0xFFFF, msg->seq);
|
|
|
|
|
|
+ debug(
|
|
|
|
+ "Received IPC message from port %p (handle %p): code=%d size=%lu "
|
|
|
|
+ "src=%u dst=%u seq=%lx\n",
|
|
|
|
+ port, port->pal_handle, msg->code, msg->size, msg->src & 0xFFFF, msg->dst & 0xFFFF,
|
|
|
|
+ msg->seq);
|
|
|
|
|
|
/* skip messages coming from myself (in case of broadcast) */
|
|
/* skip messages coming from myself (in case of broadcast) */
|
|
if (msg->src != cur_process.vmid) {
|
|
if (msg->src != cur_process.vmid) {
|
|
@@ -589,8 +584,8 @@ static int receive_ipc_message(struct shim_ipc_port* port) {
|
|
/* send IPC_RESP message to sender of this msg */
|
|
/* send IPC_RESP message to sender of this msg */
|
|
ret = send_response_ipc_message(port, msg->src, ret, msg->seq);
|
|
ret = send_response_ipc_message(port, msg->src, ret, msg->seq);
|
|
if (ret < 0) {
|
|
if (ret < 0) {
|
|
- debug("Sending IPC_RESP msg on port %p (handle %p) to %u failed\n",
|
|
|
|
- port, port->pal_handle, msg->src & 0xFFFF);
|
|
|
|
|
|
+ debug("Sending IPC_RESP msg on port %p (handle %p) to %u failed\n", port,
|
|
|
|
+ port->pal_handle, msg->src & 0xFFFF);
|
|
ret = -PAL_ERRNO;
|
|
ret = -PAL_ERRNO;
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
@@ -598,12 +593,12 @@ static int receive_ipc_message(struct shim_ipc_port* port) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- bytes -= expected_size; /* one message was received and handled */
|
|
|
|
|
|
+ bytes -= expected_size; /* one message was received and handled */
|
|
|
|
|
|
if (bytes > 0) {
|
|
if (bytes > 0) {
|
|
- /* we may have started reading the next message, move this message
|
|
|
|
- * to beginning of msg buffer and reset expected size */
|
|
|
|
- memmove(msg, (void *)msg + expected_size, bytes);
|
|
|
|
|
|
+ /* we may have started reading the next message, move this message to beginning of msg
|
|
|
|
+ * buffer and reset expected size */
|
|
|
|
+ memmove(msg, (void*)msg + expected_size, bytes);
|
|
expected_size = IPC_MSG_MINIMAL_SIZE;
|
|
expected_size = IPC_MSG_MINIMAL_SIZE;
|
|
if (bytes >= IPC_MSG_MINIMAL_SIZE)
|
|
if (bytes >= IPC_MSG_MINIMAL_SIZE)
|
|
expected_size = msg->size;
|
|
expected_size = msg->size;
|
|
@@ -616,28 +611,24 @@ out:
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
-/* Main routine of the IPC helper thread. IPC helper thread is spawned when
|
|
|
|
- * the first IPC port is added and is terminated only when the whole Graphene
|
|
|
|
- * application terminates. IPC helper thread runs in an endless loop and waits
|
|
|
|
- * on port events (either the addition/removal of ports or actual port events:
|
|
|
|
- * acceptance of new client or receiving/sending messages). In particular,
|
|
|
|
- * IPC helper thread calls receive_ipc_message() if a message arrives on port.
|
|
|
|
|
|
+/* Main routine of the IPC helper thread. IPC helper thread is spawned when the first IPC port is
|
|
|
|
+ * added and is terminated only when the whole Graphene application terminates. IPC helper thread
|
|
|
|
+ * runs in an endless loop and waits on port events (either the addition/removal of ports or actual
|
|
|
|
+ * port events: acceptance of new client or receiving/sending messages). In particular, IPC helper
|
|
|
|
+ * thread calls receive_ipc_message() if a message arrives on port.
|
|
*
|
|
*
|
|
- * Other threads add and remove IPC ports via add_ipc_xxx() and del_ipc_xxx()
|
|
|
|
- * functions. These ports are added to port_list which the IPC helper thread
|
|
|
|
- * consults before each new DkObjectsWaitAny().
|
|
|
|
|
|
+ * Other threads add and remove IPC ports via add_ipc_xxx() and del_ipc_xxx() functions. These ports
|
|
|
|
+ * are added to port_list which the IPC helper thread consults before each new DkObjectsWaitAny().
|
|
*
|
|
*
|
|
- * Note that ports are copied from global port_list to local object_list. This
|
|
|
|
- * is because ports may be removed from port_list by other threads while IPC
|
|
|
|
- * helper thread is waiting on DkObjectsWaitAny(). For this reason IPC thread
|
|
|
|
- * also get references to all current ports and puts them after handling all
|
|
|
|
- * ports in object_list.
|
|
|
|
|
|
+ * Note that ports are copied from global port_list to local object_list. This is because ports may
|
|
|
|
+ * be removed from port_list by other threads while IPC helper thread is waiting on
|
|
|
|
+ * DkObjectsWaitAny(). For this reason IPC thread also get references to all current ports and puts
|
|
|
|
+ * them after handling all ports in object_list.
|
|
*
|
|
*
|
|
- * Previous implementation went to great lengths to keep changes to the list of
|
|
|
|
- * current ports to a minimum (instead of repopulating the list before each wait
|
|
|
|
- * like in current code). Unfortunately, this resulted in undue complexity.
|
|
|
|
- * Current implementation should perform fine for usual case of <100 IPC ports
|
|
|
|
- * and with IPC helper thread always running in background on its own core.
|
|
|
|
|
|
+ * Previous implementation went to great lengths to keep changes to the list of current ports to a
|
|
|
|
+ * minimum (instead of repopulating the list before each wait like in current code). Unfortunately,
|
|
|
|
+ * this resulted in undue complexity. Current implementation should perform fine for usual case of
|
|
|
|
+ * <100 IPC ports and with IPC helper thread always running in background on its own core.
|
|
*/
|
|
*/
|
|
noreturn static void shim_ipc_helper(void* dummy) {
|
|
noreturn static void shim_ipc_helper(void* dummy) {
|
|
__UNUSED(dummy);
|
|
__UNUSED(dummy);
|
|
@@ -647,22 +638,21 @@ noreturn static void shim_ipc_helper(void* dummy) {
|
|
|
|
|
|
/* Initialize two lists:
|
|
/* Initialize two lists:
|
|
* - object_list collects IPC port objects and is the main handled list
|
|
* - object_list collects IPC port objects and is the main handled list
|
|
- * - palhandle_list collects corresponding PAL handles of IPC port objects
|
|
|
|
- * and is needed for DkObjectsWaitAny(.., <array-of-PAL-handles>, ..)
|
|
|
|
- * interface; palhandle_list always contains at least install_new_event
|
|
|
|
|
|
+ * - palhandle_list collects corresponding PAL handles of IPC port objects and is needed for
|
|
|
|
+ * DkObjectsWaitAny(.., <array-of-PAL-handles>, ..) interface; palhandle_list always contains
|
|
|
|
+ * at least install_new_event
|
|
*
|
|
*
|
|
- * We allocate these two lists on the heap so they do not overflow the
|
|
|
|
- * limited PAL stack. We grow them at runtime if needed.
|
|
|
|
|
|
+ * We allocate these two lists on the heap so they do not overflow the limited PAL stack. We
|
|
|
|
+ * grow them at runtime if needed.
|
|
*/
|
|
*/
|
|
- size_t object_list_size = 0;
|
|
|
|
|
|
+ size_t object_list_size = 0;
|
|
size_t object_list_maxsize = 32;
|
|
size_t object_list_maxsize = 32;
|
|
struct shim_ipc_port** object_list =
|
|
struct shim_ipc_port** object_list =
|
|
- malloc(sizeof(struct shim_ipc_port *) * object_list_maxsize);
|
|
|
|
- PAL_HANDLE* palhandle_list =
|
|
|
|
- malloc(sizeof(PAL_HANDLE) * (1 + object_list_maxsize));
|
|
|
|
|
|
+ malloc(sizeof(struct shim_ipc_port*) * object_list_maxsize);
|
|
|
|
+ PAL_HANDLE* palhandle_list = malloc(sizeof(PAL_HANDLE) * (1 + object_list_maxsize));
|
|
|
|
|
|
PAL_HANDLE install_new_event_hdl = event_handle(&install_new_event);
|
|
PAL_HANDLE install_new_event_hdl = event_handle(&install_new_event);
|
|
- palhandle_list[0] = install_new_event_hdl;
|
|
|
|
|
|
+ palhandle_list[0] = install_new_event_hdl;
|
|
|
|
|
|
while (true) {
|
|
while (true) {
|
|
lock(&ipc_helper_lock);
|
|
lock(&ipc_helper_lock);
|
|
@@ -676,8 +666,8 @@ noreturn static void shim_ipc_helper(void* dummy) {
|
|
struct shim_ipc_port* polled_port = NULL;
|
|
struct shim_ipc_port* polled_port = NULL;
|
|
|
|
|
|
if (polled == install_new_event_hdl) {
|
|
if (polled == install_new_event_hdl) {
|
|
- /* some thread wants to install new event; this event is found
|
|
|
|
- * in object_list below, so just re-init install_new_event */
|
|
|
|
|
|
+ /* some thread wants to install new event; this event is found in object_list below, so
|
|
|
|
+ * just re-init install_new_event */
|
|
debug("New IPC event was requested (port was added/removed)\n");
|
|
debug("New IPC event was requested (port was added/removed)\n");
|
|
clear_event(&install_new_event);
|
|
clear_event(&install_new_event);
|
|
} else {
|
|
} else {
|
|
@@ -691,18 +681,17 @@ noreturn static void shim_ipc_helper(void* dummy) {
|
|
|
|
|
|
if (polled_port) {
|
|
if (polled_port) {
|
|
if (polled_port->type & IPC_PORT_SERVER) {
|
|
if (polled_port->type & IPC_PORT_SERVER) {
|
|
- /* if polled port is server port, accept a client,
|
|
|
|
- * create client port, and add it to port list */
|
|
|
|
|
|
+ /* if polled port is server port, accept a client, create client port, and add it to
|
|
|
|
+ * port list */
|
|
PAL_HANDLE client = DkStreamWaitForClient(polled_port->pal_handle);
|
|
PAL_HANDLE client = DkStreamWaitForClient(polled_port->pal_handle);
|
|
if (client) {
|
|
if (client) {
|
|
- /* type of client port is the same as original server port
|
|
|
|
- * but with LISTEN (for remote client) and without SERVER
|
|
|
|
- * (this port doesn't wait for new clients) */
|
|
|
|
|
|
+ /* type of client port is the same as original server port but with LISTEN (for
|
|
|
|
+ * remote client) and without SERVER (this port doesn't wait for new clients) */
|
|
IDTYPE client_type = (polled_port->type & ~IPC_PORT_SERVER) | IPC_PORT_LISTEN;
|
|
IDTYPE client_type = (polled_port->type & ~IPC_PORT_SERVER) | IPC_PORT_LISTEN;
|
|
add_ipc_port_by_id(polled_port->vmid, client, client_type, NULL, NULL);
|
|
add_ipc_port_by_id(polled_port->vmid, client, client_type, NULL, NULL);
|
|
} else {
|
|
} else {
|
|
- debug("Port %p (handle %p) was removed during accepting client\n",
|
|
|
|
- polled_port, polled_port->pal_handle);
|
|
|
|
|
|
+ debug("Port %p (handle %p) was removed during accepting client\n", polled_port,
|
|
|
|
+ polled_port->pal_handle);
|
|
del_ipc_port_fini(polled_port, -ECHILD);
|
|
del_ipc_port_fini(polled_port, -ECHILD);
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
@@ -715,13 +704,13 @@ noreturn static void shim_ipc_helper(void* dummy) {
|
|
}
|
|
}
|
|
|
|
|
|
if (attr.disconnected) {
|
|
if (attr.disconnected) {
|
|
- debug("Port %p (handle %p) disconnected\n",
|
|
|
|
- polled_port, polled_port->pal_handle);
|
|
|
|
|
|
+ debug("Port %p (handle %p) disconnected\n", polled_port,
|
|
|
|
+ polled_port->pal_handle);
|
|
del_ipc_port_fini(polled_port, -ECONNRESET);
|
|
del_ipc_port_fini(polled_port, -ECONNRESET);
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- debug("Port %p (handle %p) was removed during attr querying\n",
|
|
|
|
- polled_port, polled_port->pal_handle);
|
|
|
|
|
|
+ debug("Port %p (handle %p) was removed during attr querying\n", polled_port,
|
|
|
|
+ polled_port->pal_handle);
|
|
del_ipc_port_fini(polled_port, -PAL_ERRNO);
|
|
del_ipc_port_fini(polled_port, -PAL_ERRNO);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -743,14 +732,12 @@ noreturn static void shim_ipc_helper(void* dummy) {
|
|
|
|
|
|
if (object_list_size == object_list_maxsize) {
|
|
if (object_list_size == object_list_maxsize) {
|
|
/* grow object_list and palhandle_list to accomodate more objects */
|
|
/* grow object_list and palhandle_list to accomodate more objects */
|
|
- struct shim_ipc_port** tmp_array = malloc(
|
|
|
|
- sizeof(struct shim_ipc_port *) * (object_list_maxsize * 2));
|
|
|
|
- PAL_HANDLE* tmp_pal_array = malloc(
|
|
|
|
- sizeof(PAL_HANDLE) * (1 + object_list_maxsize * 2));
|
|
|
|
- memcpy(tmp_array, object_list,
|
|
|
|
- sizeof(struct shim_ipc_port *) * (object_list_size));
|
|
|
|
- memcpy(tmp_pal_array, palhandle_list,
|
|
|
|
- sizeof(PAL_HANDLE) * (1 + object_list_size));
|
|
|
|
|
|
+ struct shim_ipc_port** tmp_array =
|
|
|
|
+ malloc(sizeof(struct shim_ipc_port*) * (object_list_maxsize * 2));
|
|
|
|
+ PAL_HANDLE* tmp_pal_array =
|
|
|
|
+ malloc(sizeof(PAL_HANDLE) * (1 + object_list_maxsize * 2));
|
|
|
|
+ memcpy(tmp_array, object_list, sizeof(struct shim_ipc_port*) * (object_list_size));
|
|
|
|
+ memcpy(tmp_pal_array, palhandle_list, sizeof(PAL_HANDLE) * (1 + object_list_size));
|
|
object_list_maxsize *= 2;
|
|
object_list_maxsize *= 2;
|
|
free(object_list);
|
|
free(object_list);
|
|
free(palhandle_list);
|
|
free(palhandle_list);
|
|
@@ -788,7 +775,7 @@ noreturn static void shim_ipc_helper(void* dummy) {
|
|
}
|
|
}
|
|
|
|
|
|
static void shim_ipc_helper_prepare(void* arg) {
|
|
static void shim_ipc_helper_prepare(void* arg) {
|
|
- struct shim_thread * self = (struct shim_thread *) arg;
|
|
|
|
|
|
+ struct shim_thread* self = (struct shim_thread*)arg;
|
|
if (!arg)
|
|
if (!arg)
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -814,7 +801,7 @@ static void shim_ipc_helper_prepare(void* arg) {
|
|
|
|
|
|
/* swap stack to be sure we don't drain the small stack PAL provides */
|
|
/* swap stack to be sure we don't drain the small stack PAL provides */
|
|
self->stack_top = stack + IPC_HELPER_STACK_SIZE;
|
|
self->stack_top = stack + IPC_HELPER_STACK_SIZE;
|
|
- self->stack = stack;
|
|
|
|
|
|
+ self->stack = stack;
|
|
__SWITCH_STACK(self->stack_top, shim_ipc_helper, NULL);
|
|
__SWITCH_STACK(self->stack_top, shim_ipc_helper, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
@@ -823,19 +810,19 @@ static int create_ipc_helper(void) {
|
|
if (ipc_helper_state == HELPER_ALIVE)
|
|
if (ipc_helper_state == HELPER_ALIVE)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- struct shim_thread * new = get_new_internal_thread();
|
|
|
|
|
|
+ struct shim_thread* new = get_new_internal_thread();
|
|
if (!new)
|
|
if (!new)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
|
|
|
|
ipc_helper_thread = new;
|
|
ipc_helper_thread = new;
|
|
- ipc_helper_state = HELPER_ALIVE;
|
|
|
|
|
|
+ ipc_helper_state = HELPER_ALIVE;
|
|
|
|
|
|
PAL_HANDLE handle = thread_create(shim_ipc_helper_prepare, new);
|
|
PAL_HANDLE handle = thread_create(shim_ipc_helper_prepare, new);
|
|
|
|
|
|
if (!handle) {
|
|
if (!handle) {
|
|
int ret = -PAL_ERRNO; /* put_thread() may overwrite errno */
|
|
int ret = -PAL_ERRNO; /* put_thread() may overwrite errno */
|
|
ipc_helper_thread = NULL;
|
|
ipc_helper_thread = NULL;
|
|
- ipc_helper_state = HELPER_NOTALIVE;
|
|
|
|
|
|
+ ipc_helper_state = HELPER_NOTALIVE;
|
|
put_thread(new);
|
|
put_thread(new);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -844,10 +831,10 @@ static int create_ipc_helper(void) {
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-/* On success, the reference to ipc helper thread is returned with refcount
|
|
|
|
- * incremented. It is the responsibility of caller to wait for ipc helper's
|
|
|
|
- * exit and then release the final reference to free related resources (it is
|
|
|
|
- * problematic for the thread itself to release its own resources e.g. stack).
|
|
|
|
|
|
+/* On success, the reference to ipc helper thread is returned with refcount incremented. It is the
|
|
|
|
+ * responsibility of caller to wait for ipc helper's exit and then release the final reference to
|
|
|
|
+ * free related resources (it is problematic for the thread itself to release its own resources e.g.
|
|
|
|
+ * stack).
|
|
*/
|
|
*/
|
|
struct shim_thread* terminate_ipc_helper(void) {
|
|
struct shim_thread* terminate_ipc_helper(void) {
|
|
/* First check if thread is alive. */
|
|
/* First check if thread is alive. */
|
|
@@ -858,18 +845,18 @@ struct shim_thread* terminate_ipc_helper(void) {
|
|
}
|
|
}
|
|
unlock(&ipc_helper_lock);
|
|
unlock(&ipc_helper_lock);
|
|
|
|
|
|
- /* NOTE: Graphene doesn't have an abstraction of a queue of pending signals
|
|
|
|
- * between communicating processes (instead all communication is done over
|
|
|
|
- * streams). Thus, app code like this (found in e.g. Lmbench's bw_unix):
|
|
|
|
|
|
+ /* NOTE: Graphene doesn't have an abstraction of a queue of pending signals between
|
|
|
|
+ * communicating processes (instead all communication is done over streams). Thus, app code like
|
|
|
|
+ * this (found in e.g. Lmbench's bw_unix):
|
|
* kill(child, SIGKILL);
|
|
* kill(child, SIGKILL);
|
|
* exit(0);
|
|
* exit(0);
|
|
- * results in a data race between the SIGKILL message sent over IPC stream
|
|
|
|
- * and the parent process exiting. In the worst case, the parent will exit
|
|
|
|
- * before the SIGKILL message goes through the host-OS stream, the host OS
|
|
|
|
- * will close the stream, and the message will never be seen by child. To
|
|
|
|
- * prevent such cases, we simply wait for a bit before exiting.
|
|
|
|
- * */
|
|
|
|
- debug("Waiting for 0.5s for all in-flight IPC messages to reach their destinations\n");
|
|
|
|
|
|
+ * results in a data race between the SIGKILL message sent over IPC stream and the parent
|
|
|
|
+ * process exiting. In the worst case, the parent will exit before the SIGKILL message goes
|
|
|
|
+ * through the host-OS stream, the host OS will close the stream, and the message will never be
|
|
|
|
+ * seen by child. To prevent such cases, we simply wait for a bit before exiting.
|
|
|
|
+ */
|
|
|
|
+ debug(
|
|
|
|
+ "Waiting for 0.5s for all in-flight IPC messages to reach their destinations\n");
|
|
DkThreadDelayExecution(500000); /* in microseconds */
|
|
DkThreadDelayExecution(500000); /* in microseconds */
|
|
|
|
|
|
lock(&ipc_helper_lock);
|
|
lock(&ipc_helper_lock);
|