vm/ipc: only report signals when it matters to ipc

. ipc wants to know about processes that get
	  signals, so that it can break blocking ipc operations
	. doing it for every single signal is wasteful
	  and causes the annoying 'no slot for signals' message
	. this fix tells vm on a per-process basis it (ipc)
	  wants to be notified, i.e. only when it does any ipc calls
	. move ipc config to separate config file while we're at it
This commit is contained in:
Ben Gras 2011-08-04 23:52:03 +00:00
parent 862fb8354d
commit d477a9ed82
12 changed files with 77 additions and 23 deletions

View file

@ -1074,6 +1074,7 @@ struct
{ "GETREF", VM_GETREF },
{ "RS_SET_PRIV", VM_RS_SET_PRIV },
{ "QUERY_EXIT", VM_QUERY_EXIT },
{ "WATCH_EXIT", VM_WATCH_EXIT },
{ "NOTIFY_SIG", VM_NOTIFY_SIG },
{ "INFO", VM_INFO },
{ "RS_UPDATE", VM_RS_UPDATE },

View file

@ -1071,8 +1071,11 @@
# define VM_RS_MEM_PIN 0 /* pin memory */
# define VM_RS_MEM_MAKE_VM 1 /* make VM instance */
#define VM_WATCH_EXIT (VM_RQ_BASE+43)
# define VM_WE_EP m1_i1
/* Total. */
#define NR_VM_CALLS 43
#define NR_VM_CALLS 44
#define VM_CALL_MASK_SIZE BITMAP_CHUNKS(NR_VM_CALLS)
/* not handled as a normal VM call, thus at the end of the reserved rage */

View file

@ -26,7 +26,8 @@ _PROTOTYPE( int vm_notify_sig, (endpoint_t ep, endpoint_t ipc_ep));
_PROTOTYPE( int vm_set_priv, (int procnr, void *buf));
_PROTOTYPE( int vm_update, (endpoint_t src_e, endpoint_t dst_e));
_PROTOTYPE( int vm_memctl, (endpoint_t ep, int req));
_PROTOTYPE( int vm_query_exit, (int *endpt));
_PROTOTYPE( int vm_query_exit, (endpoint_t *endpt));
_PROTOTYPE( int vm_watch_exit, (endpoint_t ep));
_PROTOTYPE( int vm_forgetblock, (u64_t id));
_PROTOTYPE( void vm_forgetblocks, (void));
_PROTOTYPE( int vm_yield_block_get_block, (u64_t yieldid, u64_t getid,

View file

@ -520,25 +520,6 @@ service amddev
uid 0;
};
service ipc
{
system
UMAP # 14
VIRCOPY # 15
;
uid 0;
ipc
SYSTEM USER pm rs log tty ds vm
;
vm
REMAP
SHM_UNMAP
GETPHYS
GETREF
QUERY_EXIT
;
};
service osscore
{
system

View file

@ -22,3 +22,14 @@ PUBLIC int vm_query_exit(int *endpt)
*endpt = m.VM_QUERY_RET_PT;
return (m.VM_QUERY_IS_MORE ? 1 : 0);
}
PUBLIC int vm_watch_exit(endpoint_t ep)
{
message m;
int r;
memset(&m, 0, sizeof(m));
m.VM_WE_EP = ep;
return _syscall(VM_PROC_NR, VM_WATCH_EXIT, &m);
}

View file

@ -8,5 +8,8 @@ LDADD+= -lsys
MAN=
BINDIR?= /usr/sbin
FILES=ipc.conf
FILESNAME=ipc
FILESDIR= /etc/system.conf.d
.include <minix.service.mk>

19
servers/ipc/ipc.conf Normal file
View file

@ -0,0 +1,19 @@
service ipc
{
system
UMAP # 14
VIRCOPY # 15
;
uid 0;
ipc
SYSTEM USER pm rs log tty ds vm
;
vm
REMAP
SHM_UNMAP
GETPHYS
GETREF
QUERY_EXIT
WATCH_EXIT
;
};

View file

@ -64,6 +64,14 @@ PUBLIC int main(int argc, char *argv[])
/* dispatch messages */
for (i = 0; i < SIZE(ipc_calls); i++) {
/* If any process does an IPC call,
* we have to know about it exiting.
* Tell VM to watch it for us.
*/
if(vm_watch_exit(m.m_source) != OK) {
printf("IPC: watch failed on %d\n", m.m_source);
}
if (ipc_calls[i].type == call_type) {
int result;

View file

@ -365,6 +365,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
CALLMAP(VM_GETREF, do_get_refcount);
CALLMAP(VM_INFO, do_info);
CALLMAP(VM_QUERY_EXIT, do_query_exit);
CALLMAP(VM_WATCH_EXIT, do_watch_exit);
CALLMAP(VM_FORGETBLOCKS, do_forgetblocks);
CALLMAP(VM_FORGETBLOCK, do_forgetblock);
CALLMAP(VM_YIELDBLOCKGETBLOCK, do_yieldblockgetblock);

View file

@ -207,5 +207,6 @@ _PROTOTYPE(int do_rs_memctl, (message *m));
/* queryexit.c */
_PROTOTYPE(int do_query_exit, (message *m));
_PROTOTYPE(int do_watch_exit, (message *m));
_PROTOTYPE(int do_notify_sig, (message *m));
_PROTOTYPE(void init_query_exit, (void));

View file

@ -67,10 +67,19 @@ PUBLIC int do_query_exit(message *m)
*===========================================================================*/
PUBLIC int do_notify_sig(message *m)
{
int i, avails = 0;
int i, avails = 0, p;
endpoint_t ep = m->VM_NOTIFY_SIG_ENDPOINT;
endpoint_t ipc_ep = m->VM_NOTIFY_SIG_IPC;
int r;
struct vmproc *vmp;
int pslot;
if(vm_isokendpt(ep, &pslot) != OK) return ESRCH;
vmp = &vmproc[pslot];
/* Only record the event if we've been asked to report it. */
if(!(vmp->vm_flags & VMF_WATCHEXIT))
return OK;
for (i = 0; i < NR_PROCS; i++) {
/* its signal is already here */
@ -80,7 +89,7 @@ PUBLIC int do_notify_sig(message *m)
avails++;
}
if (!avails) {
/* no slot for signals, impossible */
/* no slot for signals, unlikely */
printf("VM: no slot for signals!\n");
return ENOMEM;
}
@ -106,6 +115,21 @@ out:
return OK;
}
/*===========================================================================*
* do_watch_exit *
*===========================================================================*/
PUBLIC int do_watch_exit(message *m)
{
endpoint_t e = m->VM_WE_EP;
struct vmproc *vmp;
int p;
if(vm_isokendpt(e, &p) != OK) return ESRCH;
vmp = &vmproc[p];
vmp->vm_flags |= VMF_WATCHEXIT;
return OK;
}
/*===========================================================================*
* init_query_exit *
*===========================================================================*/

View file

@ -65,5 +65,6 @@ struct vmproc {
#define VMF_HAS_DMA 0x010 /* Process directly or indirectly granted
* DMA buffers.
*/
#define VMF_WATCHEXIT 0x020 /* Store in queryexit table */
#endif