示例#1
0
文件: rec_sched.c 项目: wisicn/rr
/**
 * Registers a new thread to the runtime system. This includes
 * initialization of the hardware performance counters
 */
void rec_sched_register_thread(pid_t parent, pid_t child, int flags)
{
	struct tasklist_entry* entry = sys_malloc_zero(sizeof(*entry));
	struct task* t = &entry->t;

	assert(child > 0 && child < MAX_TID);

	t->status = 0;
	t->rec_tid = t->tid = child;
	t->child_mem_fd = sys_open_child_mem(child);
	push_placeholder_event(t);
	if (parent) {
		struct task* parent_t = get_task(parent);
		struct sighandlers* parent_handlers = parent_t->sighandlers;

		t->syscallbuf_lib_start = parent_t->syscallbuf_lib_start;
		t->syscallbuf_lib_end = parent_t->syscallbuf_lib_end;
		t->task_group =
			(SHARE_TASK_GROUP & flags) ?
			task_group_add_and_ref(parent_t->task_group, t) :
			task_group_new_and_add(t);
		t->sighandlers = (SHARE_SIGHANDLERS & flags) ?
				 sighandlers_ref(parent_handlers) :
				 sighandlers_copy(parent_handlers);
	} else {
		/* After the first task is forked, we always need to
		 * know the parent in order to initialize some task
		 * state. */
		static int is_first_task = 1;
		assert(is_first_task);
		is_first_task = 0;
		t->task_group = task_group_new_and_add(t);
		/* The very first task we fork inherits our
		 * sighandlers (which should all be default at this
		 * point, but ...).  From there on, new tasks will
		 * transitively inherit from this first task.  */
		t->sighandlers = sighandlers_new();
		sighandlers_init_from_current_process(t->sighandlers);
	}
	/* These will be initialized when the syscall buffer is. */
	t->desched_fd = t->desched_fd_child = -1;

	sys_ptrace_setup(child);

	init_hpc(t);
	start_hpc(t, rr_flags()->max_rbc);

	CIRCLEQ_INSERT_TAIL(&head, entry, entries);
	num_active_threads++;

	tid_to_entry[child] = entry;
}
示例#2
0
/**
 * main replayer method
 */
static void start(int option, int argc, char* argv[], char** envp)
{
	pid_t pid;
	int status, fake_argc;

	if (option == RECORD) {
		copy_executable(argv[2]);
		if (access(__executable, X_OK)) {
			printf("The specified file '%s' does not exist or is not executable\n", __executable);
			return;
		}

		/* create directory for trace files */
		setup_trace_dir(0);

		/* initialize trace files */
		open_trace_files();
		init_trace_files();
		copy_argv(argc, argv);
		copy_envp(envp);
		record_argv_envp(argc, __argv, __envp);
		close_trace_files();

		pid = sys_fork();
		/* child process */
		if (pid == 0) {
			sys_start_trace(__executable, __argv, __envp);
			/* parent process */
		} else {
			child = pid;

			/* make sure that the child process dies when the master process gets interrupted */
			install_signal_handler();

			/* sync with the child process */
			sys_waitpid(pid, &status);

			/* configure the child process to get a message upon a thread start, fork(), etc. */
			sys_ptrace_setup(pid);

			/* initialize stuff */
			init_libpfm();
			/* initialize the trace file here -- we need to record argc and envp */
			open_trace_files();

			/* register thread at the scheduler and start the HPC */
			rec_sched_register_thread(0, pid);

			/* perform the action recording */
			fprintf(stderr, "start recording...\n");
			start_recording();
			fprintf(stderr, "done recording -- cleaning up\n");
			/* cleanup all initialized data-structures */
			close_trace_files();
			close_libpfm();
		}

		/* replayer code comes here */
	} else if (option == REPLAY) {
		init_environment(argv[2], &fake_argc, __argv, __envp);

		copy_executable(__argv[0]);
		if (access(__executable, X_OK)) {
			printf("The specified file '%s' does not exist or is not executable\n", __executable);
			return;
		}

		pid = sys_fork();
		//child process
		if (pid == 0) {
			sys_start_trace(__executable, __argv, __envp);
			/* parent process */
		} else {
			child = pid;
			/* make sure that the child process dies when the master process gets interrupted */
			install_signal_handler();

			sys_waitpid(pid, &status);
			sys_ptrace_setup(pid);


			/* initialize stuff */
			init_libpfm();
			rep_sched_init();
			/* sets the file pointer to the first trace entry */

			read_trace_init(argv[2]);

			pid_t rec_main_thread = get_recorded_main_thread();
			rep_sched_register_thread(pid, rec_main_thread);

			/* main loop */
			replay();
			/* thread wants to exit*/
			close_libpfm();
			read_trace_close();
			rep_sched_close();
		}
	}
}