Пример #1
0
os_word collect_rest(os_thread_info* self_info, os_word arg) {
  collect_args* args = (collect_args*)arg;
  gc_heap* heap = args->heap;
  int max_zone = args->max_zone;

  os_thread_info* other_info = 0;
  int other_info_count;
  os_other_thread_info(&other_info, &other_info_count);

  sync_thread_contexts(heap, other_info, other_info_count, self_info);

  gc_trace trace;
  initialize_trace(heap, &trace, max_zone);

  trace_heap(heap, &trace, self_info, other_info, other_info_count);

  if(trace.did_mark_objects) {
    gc_compaction cpt;
    initialize_compaction(heap, &cpt);
    compact_heap(heap, &trace, &cpt);
    finalize_compaction(&cpt);
  }

  finalize_trace(heap, &trace);

  return 0;
}
Пример #2
0
/* Move all free space to the end of the code heap. This is not very efficient,
since it makes several passes over the code and data heaps, but we only ever
do this before saving a deployed image and exiting, so performaance is not
critical here */
void compact_code_heap(void)
{
	/* Free all unreachable code blocks */
	gc();

	/* Figure out where the code heap blocks are going to end up */
	CELL size = compute_heap_forwarding(&code_heap);

	/* Update word and quotation code pointers */
	forward_object_xts();

	/* Actually perform the compaction */
	compact_heap(&code_heap);

	/* Update word and quotation XTs */
	fixup_object_xts();

	/* Now update the free list; there will be a single free block at
	the end */
	build_free_list(&code_heap,size);
}
Пример #3
0
Файл: driver.c Проект: sos22/dwc
int
main(int argc, char *argv[])
{
	int fd;
	struct stat statbuf;
	off_t size;
	unsigned nr_workers;
	int workers_left_alive;
	struct pollfd *polls;
	struct worker *workers;
	unsigned x;
	int idx;
	int *poll_slots_to_workers;
	int offline;
	int prepopulate;
	int poll_slots_in_use;
	struct mallinfo mi;

	init_malloc(false);
	gettimeofday(&start, NULL);

	if (argc == 1)
		errx(1, "arguments are either --offline and a list of files, or a list of ip port1 port2 triples");

	prepopulate = 0;
	if (!strcmp(argv[1], "--prepopulate")) {
		prepopulate = 1;
		argv++;
		argc--;
	}

	offline = 0;
	if (!strcmp(argv[1], "--offline"))
		offline = 1;

	if (!offline) {
		if ((argc - 2) % 3)
			errx(1, "non-integer number of workers?");

		fd = open(argv[1], O_RDONLY);
		if (fd < 0)
			err(1, "open(%s)", argv[1]);
		if (fstat(fd, &statbuf) < 0)
			err(1, "stat(%s)", argv[1]);
		size = statbuf.st_size;
		nr_workers = (argc - 2) / 3;
	} else {
		fd = -1;
		size = 0;
		nr_workers = argc - 2;
	}

	workers = calloc(nr_workers, sizeof(workers[0]));
	polls = calloc(nr_workers, sizeof(polls[0]));
	poll_slots_to_workers = calloc(nr_workers, sizeof(polls[0]));
	for (x = 0; x < nr_workers; x++) {
		if (offline) {
			workers[x].to_worker_fd = -1;
			workers[x].from_worker_fd = open(argv[x + 2], O_RDONLY | O_NONBLOCK);
			if (workers[x].from_worker_fd < 0)
				err(1, "opening %s", argv[x + 2]);
			polls[x].fd = workers[x].from_worker_fd;
			polls[x].events = POLLIN;
		} else {
			connect_to_worker(argv[x * 3 + 2],
					  argv[x * 3 + 3],
					  argv[x * 3 + 4],
					  &workers[x].to_worker_fd,
					  &workers[x].from_worker_fd);

			polls[x].fd = workers[x].to_worker_fd;
			polls[x].events = POLLOUT;

			workers[x].send_offset = x * (size / nr_workers);
			if (x != 0)
				workers[x-1].end_of_chunk = workers[x].send_offset;
		}
		workers[x].finished_hash_entries = -1;
		poll_slots_to_workers[x] = x;
	}
	workers[nr_workers - 1].end_of_chunk = size;

	workers_left_alive = nr_workers;
	poll_slots_in_use = nr_workers;
	DBG("Start main loop\n");
	while (workers_left_alive != 0) {
		int r = poll(polls, poll_slots_in_use, -1);
		if (r < 0)
			err(1, "poll()");
		for (x = 0; x < poll_slots_in_use && r; x++) {
			if (!polls[x].revents)
				continue;
			r--;
			idx = poll_slots_to_workers[x];

			assert(!(polls[x].revents & POLLNVAL));
			if (polls[x].revents & POLLERR)
				errx(1, "error on worker %d", idx);
			if (polls[x].revents & POLLHUP) {
				if (workers[idx].to_worker_fd < 0) {
					polls[x].revents = POLLIN;
					warnx("worker %d hung up on us, but that's okay", idx);
				} else {
					errx(1, "worker %d hung up on us when it really shouldn't have done", idx);
				}
			}

			if (polls[x].revents & POLLOUT) {
				ssize_t s;
				assert(!offline);
				assert(workers[idx].send_offset < workers[idx].end_of_chunk);
				s = sendfile(workers[idx].to_worker_fd,
					     fd,
					     &workers[idx].send_offset,
					     workers[idx].end_of_chunk - workers[idx].send_offset);
				if (s == 0)
					errx(1, "worker hung up on us");
				if (s < 0)
					err(1, "sending to worker");
				assert(workers[idx].send_offset <= workers[idx].end_of_chunk);
				if (workers[idx].send_offset == workers[idx].end_of_chunk) {
					DBG("Finished sending input to worker %d\n",
					       idx);
					if (prepopulate) {
						memmove(poll_slots_to_workers + x,
							poll_slots_to_workers + x + 1,
							(poll_slots_in_use - x - 1) * sizeof(int));
						memmove(polls + x,
							polls + x + 1,
							(poll_slots_in_use - x - 1) * sizeof(polls[0]));
						poll_slots_in_use--;
						if (poll_slots_in_use == 0) {
							/* Okay, we've
							   done the
							   prepopulate
							   phase.
							   Switch
							   modes. */
							DBG("Finished prepopulate phase\n");
							for (idx = 0; idx < nr_workers; idx++) {
								polls[idx].events = POLLIN;
								polls[idx].revents = 0;
								polls[idx].fd = workers[idx].from_worker_fd;
								poll_slots_to_workers[idx] = idx;
								close(workers[idx].to_worker_fd);
								workers[idx].to_worker_fd = -1;
							}
							DBG("All workers go\n");
							poll_slots_in_use = nr_workers;
						}
					} else {
						close(workers[idx].to_worker_fd);
						workers[idx].to_worker_fd = -1;
						polls[x].events = POLLIN;
						polls[x].revents = 0;
						polls[x].fd = workers[idx].from_worker_fd;
					}
				}
			} else if (polls[x].revents & POLLIN) {
				do_rx(workers + idx,
				      idx == 0,
				      idx == nr_workers - 1,
				      idx);
			}
		}

		for (x = 0; x < poll_slots_in_use; x++) {
			idx = poll_slots_to_workers[x];
			if (workers[idx].finished) {
				DBG("expunge worker %d\n", idx);
				memmove(poll_slots_to_workers + x,
					poll_slots_to_workers + x + 1,
					(poll_slots_in_use - x - 1) * sizeof(int));
				memmove(polls + x,
					polls + x + 1,
					(poll_slots_in_use - x - 1) * sizeof(polls[0]));
				poll_slots_in_use--;
				workers_left_alive--;
				x--;
			}
		}

		mi = mallinfo();
		if (mi.uordblks > TARGET_MAX_HEAP_SIZE)
			compact_heap(workers, nr_workers, polls);

	}

	DBG("All done\n");

	for (idx = last_gced_hash_slot + 1; idx < NR_HASH_TABLE_SLOTS; idx++) {
		struct word *w;
		for (w = hash_table[idx]; w; w = w->next) {
			printf("%16d %.*s\n",
			       w->counter,
			       w->len,
			       w->word);
		}
	}
	printf("Boundary screw ups:\n");
	for (idx = 0; idx <= last_gced_hash_slot; idx++) {
		struct word *w;
		for (w = hash_table[idx]; w; w = w->next) {
			printf("%16d %.*s\n",
			       w->counter,
			       w->len,
			       w->word);
		}
	}
	DBG("Finished producing output\n");

	return 0;
}