xref: /minix/minix/servers/ipc/main.c (revision 7f5f010b)
1 #include "inc.h"
2 
3 int identifier = 0x1234;
4 endpoint_t who_e;
5 int call_type;
6 
7 static struct {
8 	int type;
9 	int (*func)(message *);
10 	int reply;	/* whether the reply action is passed through */
11 } ipc_calls[] = {
12 	{ IPC_SHMGET,	do_shmget,	0 },
13 	{ IPC_SHMAT,	do_shmat,	0 },
14 	{ IPC_SHMDT,	do_shmdt,	0 },
15 	{ IPC_SHMCTL,	do_shmctl,	0 },
16 	{ IPC_SEMGET,	do_semget,	0 },
17 	{ IPC_SEMCTL,	do_semctl,	0 },
18 	{ IPC_SEMOP,	do_semop,	1 },
19 };
20 
21 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
22 
23 static int verbose = 0;
24 
25 /* SEF functions and variables. */
26 static void sef_local_startup(void);
27 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
28 static void sef_cb_signal_handler(int signo);
29 
30 int main(int argc, char *argv[])
31 {
32 	message m;
33 
34 	/* SEF local startup. */
35 	env_setargs(argc, argv);
36 	sef_local_startup();
37 
38 	while (TRUE) {
39 		int r;
40 		int ipc_number;
41 
42 		if ((r = sef_receive(ANY, &m)) != OK)
43 			printf("sef_receive failed %d.\n", r);
44 		who_e = m.m_source;
45 		call_type = m.m_type;
46 
47 		if(verbose)
48 			printf("IPC: get %d from %d\n", call_type, who_e);
49 
50 		if (call_type & NOTIFY_MESSAGE) {
51 			switch (who_e) {
52 			case VM_PROC_NR:
53 				/* currently, only semaphore needs such information. */
54 				sem_process_vm_notify();
55 				break;
56 			default:
57 				printf("IPC: ignoring notify() from %d\n",
58 					who_e);
59 				break;
60 			}
61 			continue;
62 		}
63 
64 		/*
65 		 * The ipc number in the table can be obtained
66 		 * with a simple equation because the values of
67 		 * IPC system calls are consecutive and begin
68 		 * at ( IPC_BASE + 1 )
69 		 */
70 
71 		ipc_number = call_type - (IPC_BASE + 1);
72 
73 		/* dispatch message */
74 		if (ipc_number >= 0 && ipc_number < SIZE(ipc_calls)) {
75 			int result;
76 
77 			if (ipc_calls[ipc_number].type != call_type)
78 				panic("IPC: call table order mismatch");
79 
80 			/* If any process does an IPC call,
81 			 * we have to know about it exiting.
82 			 * Tell VM to watch it for us.
83 			 */
84 			if(vm_watch_exit(m.m_source) != OK) {
85 				printf("IPC: watch failed on %d\n", m.m_source);
86 			}
87 
88 			result = ipc_calls[ipc_number].func(&m);
89 
90 			/*
91 			 * The handler of the IPC call did not
92 			 * post a reply.
93 			 */
94 			if (!ipc_calls[ipc_number].reply) {
95 
96 				m.m_type = result;
97 
98 				if(verbose && result != OK)
99 					printf("IPC: error for %d: %d\n",
100 						call_type, result);
101 
102 				if ((r = ipc_sendnb(who_e, &m)) != OK)
103 					printf("IPC send error %d.\n", r);
104 			}
105 		} else {
106 			/* warn and then ignore */
107 			printf("IPC unknown call type: %d from %d.\n",
108 				call_type, who_e);
109 		}
110 		update_refcount_and_destroy();
111 	}
112 
113 	/* no way to get here */
114 	return -1;
115 }
116 
117 /*===========================================================================*
118  *			       sef_local_startup			     *
119  *===========================================================================*/
120 static void sef_local_startup()
121 {
122   /* Register init callbacks. */
123   sef_setcb_init_fresh(sef_cb_init_fresh);
124   sef_setcb_init_restart(sef_cb_init_fresh);
125 
126   /* No live update support for now. */
127 
128   /* Register signal callbacks. */
129   sef_setcb_signal_handler(sef_cb_signal_handler);
130 
131   /* Let SEF perform startup. */
132   sef_startup();
133 }
134 
135 /*===========================================================================*
136  *		            sef_cb_init_fresh                                *
137  *===========================================================================*/
138 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info))
139 {
140 /* Initialize the ipc server. */
141 
142   if(verbose)
143       printf("IPC: self: %d\n", sef_self());
144 
145   return(OK);
146 }
147 
148 /*===========================================================================*
149  *		            sef_cb_signal_handler                            *
150  *===========================================================================*/
151 static void sef_cb_signal_handler(int signo)
152 {
153   /* Only check for termination signal, ignore anything else. */
154   if (signo != SIGTERM) return;
155 
156   /* Checkout if there are still IPC keys. Inform the user in that case. */
157   if (!is_sem_nil() || !is_shm_nil())
158       printf("IPC: exit with un-clean states.\n");
159 }
160 
161