161 lines
3.9 KiB
C
161 lines
3.9 KiB
C
|
#include "inc.h"
|
||
|
|
||
|
int identifier = 0x1234;
|
||
|
endpoint_t who_e;
|
||
|
int call_type;
|
||
|
|
||
|
static struct {
|
||
|
int type;
|
||
|
int (*func)(message *);
|
||
|
int reply; /* whether the reply action is passed through */
|
||
|
} ipc_calls[] = {
|
||
|
{ IPC_SHMGET, do_shmget, 0 },
|
||
|
{ IPC_SHMAT, do_shmat, 0 },
|
||
|
{ IPC_SHMDT, do_shmdt, 0 },
|
||
|
{ IPC_SHMCTL, do_shmctl, 0 },
|
||
|
{ IPC_SEMGET, do_semget, 0 },
|
||
|
{ IPC_SEMCTL, do_semctl, 0 },
|
||
|
{ IPC_SEMOP, do_semop, 1 },
|
||
|
};
|
||
|
|
||
|
#define SIZE(a) (sizeof(a)/sizeof(a[0]))
|
||
|
|
||
|
static int verbose = 0;
|
||
|
|
||
|
/* SEF functions and variables. */
|
||
|
static void sef_local_startup(void);
|
||
|
static int sef_cb_init_fresh(int type, sef_init_info_t *info);
|
||
|
static void sef_cb_signal_handler(int signo);
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
message m;
|
||
|
|
||
|
/* SEF local startup. */
|
||
|
env_setargs(argc, argv);
|
||
|
sef_local_startup();
|
||
|
|
||
|
while (TRUE) {
|
||
|
int r;
|
||
|
int ipc_number;
|
||
|
|
||
|
if ((r = sef_receive(ANY, &m)) != OK)
|
||
|
printf("sef_receive failed %d.\n", r);
|
||
|
who_e = m.m_source;
|
||
|
call_type = m.m_type;
|
||
|
|
||
|
if(verbose)
|
||
|
printf("IPC: get %d from %d\n", call_type, who_e);
|
||
|
|
||
|
if (call_type & NOTIFY_MESSAGE) {
|
||
|
switch (who_e) {
|
||
|
case VM_PROC_NR:
|
||
|
/* currently, only semaphore needs such information. */
|
||
|
sem_process_vm_notify();
|
||
|
break;
|
||
|
default:
|
||
|
printf("IPC: ignoring notify() from %d\n",
|
||
|
who_e);
|
||
|
break;
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* The ipc number in the table can be obtained
|
||
|
* with a simple equation because the values of
|
||
|
* IPC system calls are consecutive and begin
|
||
|
* at ( IPC_BASE + 1 )
|
||
|
*/
|
||
|
|
||
|
ipc_number = call_type - (IPC_BASE + 1);
|
||
|
|
||
|
/* dispatch message */
|
||
|
if (ipc_number >= 0 && ipc_number < SIZE(ipc_calls)) {
|
||
|
int result;
|
||
|
|
||
|
if (ipc_calls[ipc_number].type != call_type)
|
||
|
panic("IPC: call table order mismatch");
|
||
|
|
||
|
/* 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);
|
||
|
}
|
||
|
|
||
|
result = ipc_calls[ipc_number].func(&m);
|
||
|
|
||
|
/*
|
||
|
* The handler of the IPC call did not
|
||
|
* post a reply.
|
||
|
*/
|
||
|
if (!ipc_calls[ipc_number].reply) {
|
||
|
|
||
|
m.m_type = result;
|
||
|
|
||
|
if(verbose && result != OK)
|
||
|
printf("IPC: error for %d: %d\n",
|
||
|
call_type, result);
|
||
|
|
||
|
if ((r = ipc_sendnb(who_e, &m)) != OK)
|
||
|
printf("IPC send error %d.\n", r);
|
||
|
}
|
||
|
} else {
|
||
|
/* warn and then ignore */
|
||
|
printf("IPC unknown call type: %d from %d.\n",
|
||
|
call_type, who_e);
|
||
|
}
|
||
|
update_refcount_and_destroy();
|
||
|
}
|
||
|
|
||
|
/* no way to get here */
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* sef_local_startup *
|
||
|
*===========================================================================*/
|
||
|
static void sef_local_startup()
|
||
|
{
|
||
|
/* Register init callbacks. */
|
||
|
sef_setcb_init_fresh(sef_cb_init_fresh);
|
||
|
sef_setcb_init_restart(sef_cb_init_fresh);
|
||
|
|
||
|
/* No live update support for now. */
|
||
|
|
||
|
/* Register signal callbacks. */
|
||
|
sef_setcb_signal_handler(sef_cb_signal_handler);
|
||
|
|
||
|
/* Let SEF perform startup. */
|
||
|
sef_startup();
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* sef_cb_init_fresh *
|
||
|
*===========================================================================*/
|
||
|
static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
|
||
|
{
|
||
|
/* Initialize the ipc server. */
|
||
|
|
||
|
if(verbose)
|
||
|
printf("IPC: self: %d\n", sef_self());
|
||
|
|
||
|
return(OK);
|
||
|
}
|
||
|
|
||
|
/*===========================================================================*
|
||
|
* sef_cb_signal_handler *
|
||
|
*===========================================================================*/
|
||
|
static void sef_cb_signal_handler(int signo)
|
||
|
{
|
||
|
/* Only check for termination signal, ignore anything else. */
|
||
|
if (signo != SIGTERM) return;
|
||
|
|
||
|
/* Checkout if there are still IPC keys. Inform the user in that case. */
|
||
|
if (!is_sem_nil() || !is_shm_nil())
|
||
|
printf("IPC: exit with un-clean states.\n");
|
||
|
}
|
||
|
|