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: cell.c,v 1.3 2002/12/11 17:16:21 rich Exp $
46 #ifdef HAVE_SYS_TYPES_H
47 #include <sys/types.h>
66 #define PRINT_SIMULATION_STATS 0
68 static volatile int quit = 0, save = 0, outgoing = 0, incoming = 0, info = 0;
69 static void save_cell_in_outgoing (struct state *, const struct cell *);
71 /* Initialize the common fields of a cell. */
73 init_cell (struct cell *cell)
75 /* Public fields are subject to initialization errors. */
76 if (! chance (cell_initialization_failure))
78 cell->a = cell->b = cell->i = cell->p = 0;
79 memset (cell->stack, 0, sizeof cell->stack);
85 cell->a = get_rand_short ();
86 cell->b = get_rand_short ();
87 cell->i = get_rand_short ();
88 cell->p = 0; /* Cell would be non-viable otherwise. */
90 for (i = 0; i < STACK_SIZE; ++i)
91 cell->stack[i] = get_rand_short ();
93 cell->next = cell->prev = 0;
94 cell->worse = cell->better = 0;
97 cell->state = state_exec;
104 cell->crc = 0; /* Initialize these at DIVIDE. */
105 cell->mother_crc = 0;
109 cell_malloc (struct state *state,
110 const struct cell *mother,
111 struct soup_frag *daughter_frag)
115 cell = malloc (sizeof (struct cell));
116 if (cell == 0) { perror ("malloc"); abort (); }
119 cell->frag = daughter_frag;
121 state->nr_cells_allocated++;
127 cell_divide (struct state *state,
128 const struct cell *mother,
129 struct cell *daughter)
131 /* Initialize CRC fields. */
132 daughter->mother_crc = mother->crc;
133 daughter->crc = soup_frag_compute_crc32 (state, daughter->frag);
135 /* If the outgoing signal has just gone, then this cell is the
136 * lucky cell which has been nominated to be written into the
142 save_cell_in_outgoing (state, daughter);
146 printf ("DIVIDE: 0x%08X/%d -> 0x%08X/%d\n",
147 daughter->mother_crc, mother->frag->len,
148 daughter->crc, daughter->frag->len);
152 /* Put a cell onto the alive list. */
154 cell_activate (struct state *state, struct cell *cell)
156 insert_before_first (cell, &state->alive_list);
158 /* We assume that cells start off with no errors. */
159 assert (cell->errors == 0);
160 insert_before_first (cell, &state->best_list);
162 state->nr_cells_alive++;
165 /* This function is called after the INC_ERRORS macro has incremented
166 * the number of errors in a cell and found that the cell should be
167 * moved up in the linked list by one or more places.
170 _cell_move_worse (struct state *state, struct cell *cell)
172 while (cell->worse && cell->errors > cell->worse->errors)
173 move_towards_last (cell, &state->best_list);
176 /* Kill a cell (and undivided offspring, if any). */
178 cell_kill (struct state *state, struct cell *cell)
180 remove_element (cell, &state->alive_list);
181 remove_element (cell, &state->best_list);
183 soup_frag_free (state, cell->frag);
185 /* Pro-life programmers may wish to look away at this point ... */
188 soup_frag_free (state, cell->daughter->frag);
189 cell->daughter->errors = -1;
190 free (cell->daughter);
192 state->nr_cells_allocated--;
198 state->nr_cells_allocated--;
199 state->nr_cells_alive--;
202 /* Run the grim reaper, culling cells until the amount of free soup
203 * left is less than the appropriate threshold.
206 reaper (struct state *state)
210 /* How many bytes do we need to free up? */
211 bytes_to_free = (100 - reaper_reap_threshold) * state->soup_size
212 / 100 - state->soup_free;
213 assert (bytes_to_free > 0);
216 printf ("\ninvoking reaper to save %d bytes of soup ...\n", bytes_to_free);
219 while (bytes_to_free > 0)
223 /* Pick the most error-prone cell and kill it. */
224 cell = (struct cell *) state->best_list.last;
225 bytes_to_free -= cell->frag->len;
226 if (cell->daughter) bytes_to_free -= cell->daughter->frag->len;
229 printf (" killing cell with %d errors\n", cell->errors);
232 cell_kill (state, cell);
236 /* Remove any cells with more than MAX_ERRORS errors. */
238 reap_error_prone_cells (struct state *state)
242 /* Just go down the list of cells, killing them until we
243 * reach a cell with < MAX_ERRORS errors.
245 while ((cell = (struct cell *) state->best_list.last) &&
246 cell->errors >= MAX_ERRORS)
249 printf ("killing cell with %d errors (>= MAX_ERRORS)\n", cell->errors);
252 cell_kill (state, cell);
257 check_one_cell (struct state *state, const struct cell *cell, int is_daughter)
259 assert (cell->sp >= 0 && cell->sp < STACK_SIZE);
260 assert (cell->errors >= 0);
261 assert (cell->state == state_exec || cell->state == state_find);
262 assert (cell->dir >= -1 && cell->dir <= 1);
263 assert (cell->frag != 0);
267 assert (is_daughter == 0);
268 check_one_cell (state, cell->daughter, 1);
272 /* Check the consistency of each cell. This is only used when we are
273 * debugging the simulation.
276 cell_check (struct state *state)
278 const struct cell *p;
279 int alive = 0, allocated = 0, errors = 0;
281 /* Check the alive list and each cell on it. */
282 for (p = (struct cell *) state->alive_list.first; p; p = p->next)
284 check_one_cell (state, p, 0);
285 alive++; allocated++;
286 if (p->daughter) allocated++;
289 assert (alive == state->nr_cells_alive);
290 assert (allocated == state->nr_cells_allocated);
292 /* Check the best list. */
293 alive = allocated = 0;
294 for (p = (struct cell *) state->best_list.first; p; p = p->worse)
296 assert (errors <= p->errors);
298 alive++; allocated++;
299 if (p->daughter) allocated++;
302 assert (alive == state->nr_cells_alive);
303 assert (allocated == state->nr_cells_allocated);
306 /* Take a complete checkpoint of the state and save it onto disk. */
308 save_me (struct state *state)
310 char filename2[256], filename3[256];
312 sprintf (filename2, "%s.new", state->filename);
314 if (image_save (state, filename2) == 0)
316 sprintf (filename3, "%s~", state->filename);
318 rename (state->filename, filename3);
319 rename (filename2, state->filename);
322 printf ("CPU %d: Saved soup image to file.\n", state->thread_num);
326 sprintf (filename3, "/tmp/%s", state->filename);
328 if (image_save (state, filename3) == 0)
331 "save directory is unwritable! saved to %s instead\n",
336 fprintf (stderr, "could not save state!\n");
341 /* Check the incoming queue. */
343 check_incoming (struct state *state)
351 #error "require working opendir/readdir/closedir"
354 dir = opendir ("incoming");
355 if (dir == NULL) { perror ("incoming"); return; }
357 while ((d = readdir (dir)) != 0)
359 int len = strlen (d->d_name);
362 d->d_name[len-4] == '.' &&
363 d->d_name[len-3] == 'd' &&
364 d->d_name[len-2] == 'l' &&
365 d->d_name[len-1] == 'o')
367 if (cells_read < max_cells_incoming_per_pass)
371 sprintf (filename, "incoming/%s", d->d_name);
373 /* Read the contents of the file. */
374 cell = load_cell (state, filename);
378 cell_activate (state, cell);
383 /* Remove the file - we've finished with it now. */
390 info_to_syslog (const struct state *state)
392 int soup_used_percent
393 = 100 * (state->soup_size - state->soup_free) / state->soup_size;
397 "#%d: cycles: %LuB cells: %d [+%d] soup: %d%% (%d/%d)",
399 state->cell_cycle / 1000000000,
400 state->nr_cells_alive,
401 state->nr_cells_allocated - state->nr_cells_alive,
403 state->soup_size - state->soup_free,
415 catch_alarm (int sig)
417 static int minutes = 0;
421 if ((minutes % save_period) == 0)
426 if ((minutes % outgoing_period) == 0)
431 if ((minutes % incoming_period) == 0)
436 if ((minutes % info_period) == 0)
445 run_thread (struct state *state)
447 int start_time = time (NULL), end_time;
448 unsigned long long start_cycle = state->cell_cycle;
449 struct sigaction sigact;
451 /* Set up signal handlers to save the soup periodically and
452 * handle exits gracefully.
454 memset (&sigact, 0, sizeof sigact);
455 sigact.sa_handler = catch_quit;
458 sigaction (SIGINT, &sigact, 0);
459 sigaction (SIGQUIT, &sigact, 0);
460 sigaction (SIGTERM, &sigact, 0);
462 sigact.sa_handler = catch_alarm;
463 sigact.sa_flags = SA_RESTART;
464 sigaction (SIGALRM, &sigact, 0);
471 int soup_used_percent;
473 /* Iterate over the list of alive cells, executing a single
474 * intruction of each.
476 for (p = (struct cell *) state->alive_list.first; p; p = p->next)
478 exec_insn (state, p);
481 /* Print some statistics. */
483 = 100 * (state->soup_size - state->soup_free) / state->soup_size;
485 #if PRINT_SIMULATION_STATS
486 printf ("cycles: %LuB cells: %d [+%d] soup: %d%% \r",
487 state->cell_cycle / 1000000000,
488 state->nr_cells_alive,
489 state->nr_cells_allocated - state->nr_cells_alive,
494 /* Do we need to invoke the grim reaper? */
495 if (soup_used_percent >= reaper_invoke_threshold)
500 /* Do we need to reap any remaining cells with more than
503 reap_error_prone_cells (state);
510 /* Save image every so often. */
517 /* Check incoming queue? */
521 check_incoming (state);
524 /* Dump status information to syslog? */
528 info_to_syslog (state);
532 end_time = time (NULL);
534 syslog (LOG_INFO, "CPU %d: Cycles processed: %LuB Time: %dH Cycles/second: %d\n",
536 (state->cell_cycle - start_cycle) / 1000000000,
537 (end_time - start_time) / (60 * 60),
538 (int) ((state->cell_cycle - start_cycle)
539 / (end_time - start_time)));
541 /* Each thread is responsible for saving its own state. */
545 /* Something of a hack: get any fragment and return it. */
547 _cell_get_any_frag (struct state *state)
549 return ((struct cell *) state->alive_list.first)->frag;
552 /* Save the current state of the cell table to a file. This function
553 * is non-destructive.
556 cell_state_save (struct state *state, FILE *fp)
560 /* Write out the number of cells. */
561 fwrite (&state->nr_cells_allocated, sizeof state->nr_cells_allocated, 1, fp);
562 fwrite (&state->nr_cells_alive, sizeof state->nr_cells_alive, 1, fp);
564 /* Write the cells out in order to the file. */
565 for (p = (struct cell *) state->alive_list.first; p; p = p->next)
567 p->fbase = p->frag->base;
568 fwrite (p, sizeof (struct cell), 1, fp);
571 p->daughter->fbase = p->daughter->frag->base;
572 fwrite (p->daughter, sizeof (struct cell), 1, fp);
578 compare_nr_errors (const void *cv1, const void *cv2)
580 const struct cell **cp1 = (const struct cell **) cv1;
581 const struct cell **cp2 = (const struct cell **) cv2;
583 return (*cp1)->errors - (*cp2)->errors;
586 /* Load the cells from a previously saved file. */
588 cell_state_load (struct state *state, FILE *fp)
592 struct cell **cellptr_list;
594 assert (state->nr_cells_allocated == 0);
595 assert (state->nr_cells_alive == 0);
597 /* Read in the number of cells. */
598 if (fread (&state->nr_cells_allocated,
599 sizeof state->nr_cells_allocated, 1, fp) != 1)
601 syslog (LOG_ERR, "error in cell state\n");
604 if (fread (&state->nr_cells_alive,
605 sizeof state->nr_cells_alive, 1, fp) != 1)
607 syslog (LOG_ERR, "error in cell state\n");
611 assert (state->nr_cells_alive <= state->nr_cells_allocated);
613 cellptr_list = malloc (sizeof (struct cell *) * state->nr_cells_alive);
615 /* Read each cell in from the file. */
616 for (i = 0; i < state->nr_cells_alive; ++i)
618 p = malloc (sizeof (struct cell));
619 if (p == 0) { perror ("malloc"); abort (); }
621 if (fread (p, sizeof (struct cell), 1, fp) != 1)
623 syslog (LOG_ERR, "error in cell state\n");
629 insert_before_last (p, &state->alive_list);
633 p->daughter = malloc (sizeof (struct cell));
634 if (p->daughter == 0) { perror ("malloc"); abort (); }
636 if (fread (p->daughter, sizeof (struct cell), 1, fp) != 1)
638 syslog (LOG_ERR, "error in cell state\n");
644 /* Order the living cells from best to worst, and from this
645 * reconstruct the best list.
647 qsort (cellptr_list, state->nr_cells_alive, sizeof (struct cell *),
650 for (i = 0; i < state->nr_cells_alive; ++i)
652 insert_before_last (cellptr_list[i], &state->best_list);
656 /* This function is used when loading the soup (just after loading the
657 * cells) to fix up references from the cells to soup fragments. It
658 * uses the hidden ``fbase'' member of struct cell to save the reference.
661 _cell_fixup_soup_ref (struct state *state,
662 addr_t fbase, struct soup_frag *frag)
666 for (p = (struct cell *) state->alive_list.first; p; p = p->next)
668 if (p->fbase == fbase)
673 else if (p->daughter && p->daughter->fbase == fbase)
675 p->daughter->frag = frag;
680 syslog (LOG_ERR, "cell fixup not found (fbase = %d)\n", fbase);
684 /* Save a single cell in the outgoing queue. */
686 save_cell_in_outgoing (struct state *state,
687 const struct cell *cell)
693 /* Choose a random name. */
694 sprintf (filename, "outgoing/%d.dlo", get_rand_int());
696 fp = fopen (filename, "w");
697 if (fp == NULL) { perror (filename); return; } /* Fail silently. */
699 for (i = 0; i < cell->frag->len; ++i)
700 fprintf (fp, "%02X", get_soup (state, cell->frag, i));