Пример #1
0
int
main(int argc, char *argv[])
{
	int port = 2344;
	const char *config = "sys161.conf";
	const char *kernel = NULL;
	int usetcp=0;
	char *argstr = NULL;
	int j, opt;
	size_t argsize=0;
	int debugwait=0;
	int pass_signals=0;
#ifdef USE_TRACE
	int profiling=0;
#endif
	int use_second_console=0;
	const char *second_console = NULL;
	unsigned ncpus;

	/* This must come absolutely first so msg() can be used. */
	console_earlyinit();
	
	if (sizeof(u_int32_t)!=4) {
		/*
		 * Just in case.
		 */
		msg("sys161 requires sizeof(u_int32_t)==4");
		die();
	}

	while ((opt = mygetopt(argc, argv, "c:f:p:Pst:wk:"))!=-1) {
		switch (opt) {
		    case 'c': config = myoptarg; break;
		    case 'f':
#ifdef USE_TRACE
			set_tracefile(myoptarg);
#endif
			break;
		    case 'p': port = atoi(myoptarg); usetcp=1; break;
		    case 'P':
#ifdef USE_TRACE
			profiling = 1;
#endif
			break;
		    case 's': pass_signals = 1; break;
		    case 't': 
#ifdef USE_TRACE
			set_traceflags(myoptarg); 
#endif
			break;
		    case 'w': debugwait = 1; break;
		    case 'k':
		    use_second_console = 1;
		    second_console = myoptarg;
		    break;
		    default: usage(); break;
		}
	}
	if (myoptind==argc) {
		usage();
	}
	kernel = argv[myoptind++];
	
	for (j=myoptind; j<argc; j++) {
		argsize += strlen(argv[j])+1;
	}
	argstr = malloc(argsize+1);
	if (!argstr) {
		msg("malloc failed");
		die();
	}
	*argstr = 0;
	for (j=myoptind; j<argc; j++) {
		strcat(argstr, argv[j]);
		if (j<argc-1) strcat(argstr, " ");
	}

	/* This must come before bus_config in case a network card needs it */
	mkdir(".sockets", 0700);
	
	console_init(pass_signals, use_second_console, second_console);
	clock_init();
	ncpus = bus_config(config);

	initstats(ncpus);
	cpu_init(ncpus);

	if (usetcp) {
		gdb_inet_init(port);
	}
	else {
		unlink(".sockets/gdb");
		gdb_unix_init(".sockets/gdb");
	}

	unlink(".sockets/meter");
	meter_init(".sockets/meter");

	load_kernel(kernel, argstr);

	msg("System/161 %s, compiled %s %s", VERSION, __DATE__, __TIME__);
#ifdef USE_TRACE
	print_traceflags();
	if (profiling) {
		prof_setup();
	}
#endif

	if (debugwait) {
		stoploop();
	}
	
	run();

#ifdef USE_TRACE
	if (profiling) {
		prof_write();
	}
#endif

	bus_cleanup();
	console_cleanup();
	clock_cleanup();
	
	return 0;
}
Пример #2
0
void dirq_free (dirq_t dirq)
{
  clock_cleanup(dirq);
  free((void *)dirq->buffer);
  free((void *)dirq);
}
Пример #3
0
static gsize
sampling_thread_func (gpointer unused)
{
	MonoInternalThread *thread = mono_thread_internal_current ();

	thread->flags |= MONO_THREAD_FLAG_DONT_MANAGE;

	ERROR_DECL (error);

	MonoString *name = mono_string_new_checked (mono_get_root_domain (), "Profiler Sampler", error);
	mono_error_assert_ok (error);
	mono_thread_set_name_internal (thread, name, FALSE, FALSE, error);
	mono_error_assert_ok (error);

	mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE);

	int old_policy;
	struct sched_param old_sched;
	pthread_getschedparam (pthread_self (), &old_policy, &old_sched);

	/*
	 * Attempt to switch the thread to real time scheduling. This will not
	 * necessarily work on all OSs; for example, most Linux systems will give
	 * us EPERM here unless configured to allow this.
	 *
	 * TODO: This does not work on Mac (and maybe some other OSs). On Mac, we
	 * have to use the Mach thread policy routines to switch to real-time
	 * scheduling. This is quite tricky as we need to specify how often we'll
	 * be doing work (easy), the normal processing time needed (also easy),
	 * and the maximum amount of processing time needed (hard). This is
	 * further complicated by the fact that if we misbehave and take too long
	 * to do our work, the kernel may knock us back down to the normal thread
	 * scheduling policy without telling us.
	 */
	struct sched_param sched = { .sched_priority = sched_get_priority_max (SCHED_FIFO) };
	pthread_setschedparam (pthread_self (), SCHED_FIFO, &sched);

	MonoProfilerSampleMode mode;

init:
	mono_profiler_get_sample_mode (NULL, &mode, NULL);

	if (mode == MONO_PROFILER_SAMPLE_MODE_NONE) {
		mono_profiler_sampling_thread_wait ();

		if (!mono_atomic_load_i32 (&sampling_thread_running))
			goto done;

		goto init;
	}

	clock_init (mode);

	for (guint64 sleep = clock_get_time_ns (); mono_atomic_load_i32 (&sampling_thread_running); clock_sleep_ns_abs (sleep)) {
		uint32_t freq;
		MonoProfilerSampleMode new_mode;

		mono_profiler_get_sample_mode (NULL, &new_mode, &freq);

		if (new_mode != mode) {
			clock_cleanup ();
			goto init;
		}

		sleep += 1000000000 / freq;

		FOREACH_THREAD_SAFE_EXCLUDE (info, MONO_THREAD_INFO_FLAGS_NO_SAMPLE) {
			g_assert (mono_thread_info_get_tid (info) != sampling_thread);

			/*
			 * Require an ack for the last sampling signal sent to the thread
			 * so that we don't overflow the signal queue, leading to all sorts
			 * of problems (e.g. GC STW failing).
			 */
			if (profiler_signal != SIGPROF && !mono_atomic_cas_i32 (&info->profiler_signal_ack, 0, 1))
				continue;

			mono_threads_pthread_kill (info, profiler_signal);
			mono_atomic_inc_i32 (&profiler_signals_sent);
		} FOREACH_THREAD_SAFE_END
	}