source: trunk/minix/servers/rs/main.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 7.0 KB
Line 
1/* Reincarnation Server. This servers starts new system services and detects
2 * they are exiting. In case of errors, system services can be restarted.
3 * The RS server periodically checks the status of all registered services
4 * services to see whether they are still alive. The system services are
5 * expected to periodically send a heartbeat message.
6 *
7 * Created:
8 * Jul 22, 2005 by Jorrit N. Herder
9 */
10#include "inc.h"
11#include <minix/dmap.h>
12#include <minix/endpoint.h>
13#include "../../kernel/const.h"
14#include "../../kernel/type.h"
15
16/* Declare some local functions. */
17FORWARD _PROTOTYPE(void init_server, (void) );
18FORWARD _PROTOTYPE(void sig_handler, (void) );
19FORWARD _PROTOTYPE(void get_work, (message *m) );
20FORWARD _PROTOTYPE(void reply, (int whom, int result) );
21
22/* Data buffers to retrieve info during initialization. */
23PRIVATE struct boot_image image[NR_BOOT_PROCS];
24PUBLIC struct dmap dmap[NR_DEVICES];
25
26/*===========================================================================*
27 * main *
28 *===========================================================================*/
29PUBLIC int main(void)
30{
31/* This is the main routine of this service. The main loop consists of
32 * three major activities: getting new work, processing the work, and
33 * sending the reply. The loop never terminates, unless a panic occurs.
34 */
35 message m; /* request message */
36 int call_nr, who_e,who_p; /* call number and caller */
37 int result; /* result to return */
38 sigset_t sigset; /* system signal set */
39 int s;
40
41 /* Initialize the server, then go to work. */
42 init_server();
43
44 /* Main loop - get work and do it, forever. */
45 while (TRUE) {
46
47 /* Wait for request message. */
48 get_work(&m);
49 who_e = m.m_source;
50 who_p = _ENDPOINT_P(who_e);
51 if(who_p < -NR_TASKS || who_p >= NR_PROCS)
52 panic("RS","message from bogus source", who_e);
53
54 call_nr = m.m_type;
55
56 /* Now determine what to do. Three types of requests are expected:
57 * - Heartbeat messages (notifications from registered system services)
58 * - System notifications (POSIX signals or synchronous alarm)
59 * - User requests (control messages to manage system services)
60 */
61
62 /* Notification messages are control messages and do not need a reply.
63 * These include heartbeat messages and system notifications.
64 */
65 if (m.m_type & NOTIFY_MESSAGE) {
66 switch (call_nr) {
67 case SYN_ALARM:
68 do_period(&m); /* check drivers status */
69 continue;
70 case PROC_EVENT:
71 sig_handler();
72 continue;
73 default: /* heartbeat notification */
74 if (rproc_ptr[who_p] != NULL) /* mark heartbeat time */
75 rproc_ptr[who_p]->r_alive_tm = m.NOTIFY_TIMESTAMP;
76 }
77 }
78
79 /* If this is not a notification message, it is a normal request.
80 * Handle the request and send a reply to the caller.
81 */
82 else {
83 switch(call_nr) {
84 case RS_UP: result = do_up(&m); break;
85 case RS_DOWN: result = do_down(&m); break;
86 case RS_REFRESH: result = do_refresh(&m); break;
87 case RS_RESCUE: result = do_rescue(&m); break;
88 case RS_SHUTDOWN: result = do_shutdown(&m); break;
89 case GETSYSINFO: result = do_getsysinfo(&m); break;
90 default:
91 printf("Warning, RS got unexpected request %d from %d\n",
92 m.m_type, m.m_source);
93 result = EINVAL;
94 }
95
96 /* Finally send reply message, unless disabled. */
97 if (result != EDONTREPLY) {
98 reply(who_e, result);
99 }
100 }
101 }
102}
103
104
105/*===========================================================================*
106 * init_server *
107 *===========================================================================*/
108PRIVATE void init_server(void)
109{
110/* Initialize the reincarnation server. */
111 struct sigaction sa;
112 struct boot_image *ip;
113 int s,t;
114
115 /* Install signal handlers. Ask PM to transform signal into message. */
116 sa.sa_handler = SIG_MESS;
117 sigemptyset(&sa.sa_mask);
118 sa.sa_flags = 0;
119 if (sigaction(SIGCHLD,&sa,NULL)<0) panic("RS","sigaction failed", errno);
120 if (sigaction(SIGTERM,&sa,NULL)<0) panic("RS","sigaction failed", errno);
121
122 /* Initialize the system process table. Use the boot image from the kernel
123 * and the device map from the FS to gather all needed information.
124 */
125 if ((s = sys_getimage(image)) != OK)
126 panic("RS","warning: couldn't get copy of image table", s);
127 if ((s = getsysinfo(FS_PROC_NR, SI_DMAP_TAB, dmap)) < 0)
128 panic("RS","warning: couldn't get copy of dmap table", errno);
129
130 /* Now initialize the table with the processes in the system image.
131 * Prepend /sbin/ to the binaries so that we can actually find them.
132 */
133 for (s=0; s< NR_BOOT_PROCS; s++) {
134 ip = &image[s];
135 if (ip->proc_nr >= 0) {
136 nr_in_use ++;
137 rproc[s].r_flags = RS_IN_USE;
138 rproc[s].r_proc_nr_e = ip->endpoint;
139 rproc[s].r_pid = getnpid(ip->proc_nr);
140 for(t=0; t< NR_DEVICES; t++)
141 if (dmap[t].dmap_driver == ip->proc_nr)
142 rproc[s].r_dev_nr = t;
143 strcpy(rproc[s].r_cmd, "/sbin/");
144 strcpy(rproc[s].r_cmd+6, ip->proc_name);
145 rproc[s].r_argc = 1;
146 rproc[s].r_argv[0] = rproc[s].r_cmd;
147 rproc[s].r_argv[1] = NULL;
148 }
149 }
150
151 /* Set alarm to periodically check driver status. */
152 if (OK != (s=sys_setalarm(RS_DELTA_T, 0)))
153 panic("RS", "couldn't set alarm", s);
154
155}
156
157/*===========================================================================*
158 * sig_handler *
159 *===========================================================================*/
160PRIVATE void sig_handler()
161{
162 sigset_t sigset;
163 int sig;
164
165 /* Try to obtain signal set from PM. */
166 if (getsigset(&sigset) != 0) return;
167
168 /* Check for known signals. */
169 if (sigismember(&sigset, SIGCHLD)) do_exit(NULL);
170 if (sigismember(&sigset, SIGTERM)) do_shutdown(NULL);
171}
172
173/*===========================================================================*
174 * get_work *
175 *===========================================================================*/
176PRIVATE void get_work(m_in)
177message *m_in; /* pointer to message */
178{
179 int s; /* receive status */
180 if (OK != (s=receive(ANY, m_in))) /* wait for message */
181 panic("RS","receive failed", s);
182}
183
184
185/*===========================================================================*
186 * reply *
187 *===========================================================================*/
188PRIVATE void reply(who, result)
189int who; /* replyee */
190int result; /* report result */
191{
192 message m_out; /* reply message */
193 int s; /* send status */
194
195 m_out.m_type = result; /* build reply message */
196 if (OK != (s=send(who, &m_out))) /* send the message */
197 panic("RS", "unable to send reply", s);
198}
199
200
201
Note: See TracBrowser for help on using the repository browser.