1 /* DLIFE Copyright (C) 2000 Richard W.M. Jones <rich@annexia.org>
2 * and other authors listed in the ``AUTHORS'' file.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 * $Id: main.c,v 1.3 2002/12/11 17:16:21 rich Exp $
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
58 unsigned soup_fetch_failure = 1000000;
59 unsigned inc_pc_failure = 1000000;
60 unsigned insn_exec_failure = 1000000;
61 unsigned access_control_failure = 10;
62 unsigned cell_initialization_failure = 1000000;
63 int reaper_invoke_threshold = 80;
64 int reaper_reap_threshold = 79;
66 int outgoing_period = 10;
67 int incoming_period = 60;
69 int max_cells_incoming_per_pass = 4;
73 static int soup_size = 128*1024; /* Read from configuration file. */
75 static const char *conf_file = CONFDIR "/soup.conf";
76 static const char *save_dir = SPOOLDIR;
78 static void parse_args (int argc, char *argv[]);
79 static void read_config_file (void);
80 static int detect_nr_cpus (void);
83 main (int argc, char *argv[])
88 /* Parse the command line. */
89 parse_args (argc, argv);
91 /* Read the configuration file. */
94 /* Initialize stuff. */
98 /* Open connection to syslog. */
99 openlog ("dlife_soup", LOG_PID, LOG_DAEMON);
102 /* Find out how many processors are available. */
103 nr_cpus = detect_nr_cpus ();
105 /* Find existing saves directory. If there is a soup image in there,
106 * then we will load it. Otherwise we will start with the god cell.
108 if (chdir (save_dir) < 0)
115 /* Reduce our priority down to the minimum. */
119 #if defined(HAVE_GETUID) && defined(HAVE_SETUID) && defined(HAVE_SETGID) && defined(HAVE_GETPWNAM) && defined(HAVE_INITGROUPS)
120 /* If we are running as root, change to user dlife. */
123 struct passwd *pw = getpwnam ("dlife");
127 initgroups ("dlife", pw->pw_gid);
133 fprintf (stderr, "cannot change to user/group dlife");
140 "version " VERSION " starting [conf="
141 CONFDIR ", spool=" SPOOLDIR ", cpus=%d]", nr_cpus);
144 /* Fork once for each processor. */
145 for (i = 0; i < nr_cpus; ++i)
158 /* This is the child process. */
159 struct state *cpu_state;
161 /* Try to load the previous soup image. If the soup image
162 * cannot be found, then instead load the god cell.
164 sprintf (filename, "saved/soup%d.img", i);
166 cpu_state = image_load (filename, soup_size, i);
171 printf ("CPU %d: starting from previous image file.\n", i);
178 printf ("CPU %d: no soup image found, loading god cell\n", i);
180 cpu_state = state_malloc (soup_size, i);
182 if ((god = load_cell (cpu_state, "god.dlo")) == 0)
184 fprintf (stderr, "dlife_soup: cannot load god cell god.dlo\n");
187 "cannot load god cell " SPOOLDIR
188 "/god.dlo -- exiting");
192 cell_activate (cpu_state, god);
195 cpu_state->filename = strdup (filename);
197 /* Detach from the terminal. */
204 run_thread (cpu_state);
210 /* Parent process exits. The children will automatically be
211 * cleaned up by init(8).
216 /* Parse the command line arguments. */
218 parse_args (int argc, char *argv[])
222 while ((c = getopt (argc, argv, "f:r:v")) != -1)
237 "usage: dlife_soup [-f conf-file] [-r save-dir] [-v]\n");
243 /* Return true if n is a power of 2. */
253 read_config_file (void)
256 char buffer[256], *t;
258 fp = fopen (conf_file, "r");
261 if (verbose) printf ("No configuration file found.\n");
265 while (fgets (buffer, sizeof buffer, fp) != 0)
267 /* Remove trailing \n and \r. */
268 t = buffer + strlen (buffer) - 1;
269 while (t >= buffer && (*t == '\n' || *t == '\r'))
272 /* Remove any comments (after a ``#'' character). */
273 t = strchr (buffer, '#');
277 /* Look for lines which we understand. */
278 if (sscanf (buffer, "soup_fetch_failure %u", &soup_fetch_failure) == 1)
280 /* No checks required. */
283 if (sscanf (buffer, "inc_pc_failure %u", &inc_pc_failure) == 1)
285 /* No checks required. */
288 if (sscanf (buffer, "insn_exec_failure %u", &insn_exec_failure) == 1)
290 /* No checks required. */
293 if (sscanf (buffer, "access_control_failure %u", &access_control_failure) == 1)
295 /* No checks required. */
298 if (sscanf (buffer, "cell_initialization_failure %u", &cell_initialization_failure) == 1)
300 /* No checks required. */
303 if (sscanf (buffer, "reaper_invoke_threshold %d", &reaper_invoke_threshold) == 1)
305 if (reaper_invoke_threshold < 0 || reaper_invoke_threshold > 100)
307 fprintf (stderr, "reaper_invoke_threshold is a percentage: it must be 0 - 100\n");
312 if (sscanf (buffer, "reaper_reap_threshold %d", &reaper_reap_threshold) == 1)
314 if (reaper_reap_threshold < 0 || reaper_reap_threshold > 100)
316 fprintf (stderr, "reaper_reap_threshold is a percentage: it must be 0 - 100\n");
321 if (sscanf (buffer, "soup_size %d", &soup_size) == 1)
323 if (soup_size <= 0 || ! is_power_2 (soup_size))
325 fprintf (stderr, "soup_size must be a power of 2\n");
330 if (sscanf (buffer, "save_period %d", &save_period) == 1)
332 /* No checks required. */
335 if (sscanf (buffer, "outgoing_period %d", &outgoing_period) == 1)
337 /* No checks required. */
340 if (sscanf (buffer, "incoming_period %d", &incoming_period) == 1)
342 /* No checks required. */
345 if (sscanf (buffer, "info_period %d", &info_period) == 1)
347 /* No checks required. */
353 /* Detect the number of CPUs available. This is very operating system
368 fp = fopen ("/proc/cpuinfo", "r");
371 perror ("/proc/cpuinfo");
372 fprintf (stderr, "warning: cannot detect number of CPUs available\n");
376 while (fgets (line, sizeof line, fp))
378 if (sscanf (line, "cpus detected : %d", &n) == 1)
385 printf ("number of CPUs detected: %d\n", n);
389 fprintf (stderr, "warning: cannot detect number of CPUs available\n");
405 fp = fopen ("/proc/cpuinfo", "r");
408 perror ("/proc/cpuinfo");
409 fprintf (stderr, "warning: cannot detect number of CPUs available\n");
413 while (fgets (line, sizeof line, fp))
415 if (sscanf (line, "ncpus active : %d", &n) == 1)
422 printf ("number of CPUs detected: %d\n", n);
426 fprintf (stderr, "warning: cannot detect number of CPUs available\n");
433 #else /* !__alpha__ || __sparc__ */
442 fp = fopen ("/proc/cpuinfo", "r");
445 perror ("/proc/cpuinfo");
446 fprintf (stderr, "warning: cannot detect number of CPUs available\n");
450 while (fgets (line, sizeof line, fp))
452 if (sscanf (line, "processor : %d", &n) == 1 && n+1 > c)
461 printf ("number of CPUs detected: %d\n", c);
465 fprintf (stderr, "warning: cannot detect number of CPUs available\n");
472 #endif /* !__alpha__ */
479 fprintf (stderr, "warning: cannot detect number of CPUs available on this platform\n");