internal static Thread Create(string name, ulong e_point, ulong stack_size, ulong tls_size, Virtual_Regions vreg, SymbolTable stab, object[] parameters) { Thread t = new Thread(); if (e_point == 0) { throw new Exception("Thread entry point is null (" + name + ")"); } t.mt = new System.Threading.Thread(System.Runtime.InteropServices.Marshal.GetDelegateForFunctionPointer <System.Threading.ThreadStart>((IntPtr)e_point)); SetTysosThread(t.mt, t); t.thread_id = next_thread_id++; t.saved_state = Program.arch.CreateTaskSwitchInfo(); t.stack = vreg.AllocRegion(stack_size, 0x1000, name + "_Stack", 0x1000, Virtual_Regions.Region.RegionType.Stack, true); t.tls = vreg.AllocRegion(tls_size, 0x1000, name + "_TLS", 0, Virtual_Regions.Region.RegionType.ModuleSection, true); t.saved_state.Init(new UIntPtr(e_point), t.stack, t.tls, new UIntPtr(stab.GetAddress("__exit")), parameters); t.name = name; t.exit_address = stab.GetAddress("__exit"); return(t); }
public static void KMain(Multiboot.Header mboot) { // Disable profiling until we have enabled the arch.DebugOutput port do_profile = false; // Get the multiboot header mboot_header = mboot; /* Create a temporary heap, then initialize the architecture * which will set up the permanent heap. Then initialize the garbage collector */ ulong arch_data_length = 0; switch (mboot.machine_major_type) { case (uint)Multiboot.MachineMajorType.x86_64: arch_data_length = tysos.x86_64.Arch.GetRecommendedChunkLength(); break; default: return; } ulong heap_start = mboot.heap_start + arch_data_length; //ulong heap_len = mboot.heap_end - heap_start; gc.gc.Heap = gc.gc.HeapType.Startup; gc.simple_heap.Init(heap_start, mboot.heap_end); log_lock = new object(); /* Set up the default startup thread */ StartupThread = new System.Threading.Thread(null_func); /* Initialize the architecture */ UIntPtr chunk_vaddr = new UIntPtr(mboot.heap_start); UIntPtr chunk_length = new UIntPtr(arch_data_length); switch (mboot.machine_major_type) { case (uint)Multiboot.MachineMajorType.x86_64: //libsupcs.OtherOperations.AsmBreakpoint(); arch = new tysos.x86_64.Arch(); break; } arch.Init(chunk_vaddr, chunk_length, mboot); do_profile = true; /* Parse the kernel command line */ kernel_cmd_line = mboot.cmdline.Split(' '); //while (true) ; // test dynamic types //if (test_dynamic() == null) // throw new Exception("test_dynamic failed"); //if (test_dynamic2() == null) // throw new Exception("test_dynamic2 failed"); // Say hi Formatter.WriteLine("Tysos v0.2.0", arch.BootInfoOutput); Formatter.WriteLine("Tysos v0.2.0", arch.DebugOutput); Formatter.Write("mboot @ ", arch.DebugOutput); Formatter.Write(libsupcs.CastOperations.ReinterpretAsUlong(mboot), "X", arch.DebugOutput); Formatter.WriteLine(arch.DebugOutput); Formatter.Write("Loaded by ", arch.DebugOutput); Formatter.WriteLine(mboot.loader_name, arch.DebugOutput); Formatter.Write("Command line: ", arch.DebugOutput); Formatter.WriteLine(mboot.cmdline, arch.DebugOutput); bool do_debug = false; if (GetCmdLine("debug")) { Formatter.Write("Kernel debug: ", arch.BootInfoOutput); Formatter.WriteLine("Kernel debug requested", arch.DebugOutput); if (arch.InitGDBStub()) { Formatter.WriteLine("enabled", arch.BootInfoOutput); Formatter.WriteLine("Kernel debug started", arch.DebugOutput); do_debug = true; } else { Formatter.WriteLine("not supported by current architecture", arch.BootInfoOutput); Formatter.WriteLine("Kernel debug not supported by current architecture", arch.DebugOutput); } } /* Map in the ELF image of the kernel, so we can load its symbols */ ulong tysos_vaddr = map_in(mboot.tysos_paddr, mboot.tysos_size, "tysos binary"); /* Trigger a breakpoint to synchronize with gdb */ if (do_debug) { Formatter.WriteLine("Synchronizing with debugger...", arch.BootInfoOutput); Formatter.WriteLine("Synchronizing with debugger...", arch.DebugOutput); System.Diagnostics.Debugger.Break(); } /* Set up a default environment */ env = new Environment(); env.env_vars.Add("OS", "tysos"); env.env_vars.Add("OSVER", "v0.2.0"); env.env_vars.Add("NUMBER_OF_PROCESSORS", "1"); #if NO_BOEHM gc.heap_arena.debug = true; #endif // NO_BOEHM /* Load up the symbol table for tysos */ if (GetCmdLine("skip_kernel_syms") == false) { ulong sym_vaddr = Program.map_in(mboot.tysos_sym_tab_paddr, mboot.tysos_sym_tab_size, "tysos_sym_tab"); ulong str_vaddr = Program.map_in(mboot.tysos_str_tab_paddr, mboot.tysos_str_tab_size, "tysos_str_tab"); stab = new SymbolTable(); Formatter.Write("Loading kernel symbols... ", arch.BootInfoOutput); Formatter.Write("Loading kernel symbols. Tysos base: ", arch.DebugOutput); Formatter.Write(tysos_vaddr, "X", arch.DebugOutput); Formatter.WriteLine(arch.DebugOutput); var hr = new ElfReader.ElfHashTable((ulong)tysos_hash, sym_vaddr, mboot.tysos_sym_tab_entsize, str_vaddr, null, 0, mboot.tysos_sym_tab_size); stab.symbol_providers.Add(hr); Formatter.WriteLine("done", arch.BootInfoOutput); } /* Test the garbage collector */ if (GetCmdLine("skip_test_gc") == false) { Formatter.Write("Testing garbage collector... ", arch.BootInfoOutput); gc.gc.DoCollection(); Formatter.WriteLine("done", arch.BootInfoOutput); } /* Start the scheduler */ Formatter.Write("Starting scheduler... ", arch.DebugOutput); arch.CurrentCpu.CurrentScheduler = new Scheduler(); if (GetCmdLine("ignore_timer") == false) { arch.SchedulerTimer.Callback = new Timer.TimerCallback(Scheduler.TimerProc); } Formatter.WriteLine("done", arch.DebugOutput); /* Store the process info */ running_processes = new Dictionary <string, Process>(new MyGenericEqualityComparer <string>()); /* Add in threads for GC collections */ Formatter.Write("Starting GC collection threads... ", arch.DebugOutput); Thread t_max = Thread.Create("gc_max_alloc", new System.Threading.ThreadStart(gc.gengc.MaxAllocCollectThreadProc), new object[] { }); t_max.priority = 10; arch.CurrentCpu.CurrentScheduler.Reschedule(t_max); Thread t_min = Thread.Create("gc_min_alloc", new System.Threading.ThreadStart(gc.gengc.MinAllocCollectThreadProc), new object[] { }); t_min.priority = 0; arch.CurrentCpu.CurrentScheduler.Reschedule(t_min); Thread t_request = Thread.Create("gc_request", new System.Threading.ThreadStart(gc.gengc.OnRequestCollectThreadProc), new object[] { }); t_min.priority = 10; arch.CurrentCpu.CurrentScheduler.Reschedule(t_request); Formatter.WriteLine("done", arch.DebugOutput); /* Init vfs signatures */ lib.File.InitSigs(); /* Load the logger */ Formatter.Write("Starting logger... ", arch.DebugOutput); Process logger = LoadELFModule("logger", mboot, stab, running_processes, 0x8000, new object[] { }); Process debugprint = LoadELFModule("debugprint", mboot, stab, running_processes, 0x8000, new object[] { }); logger.Start(); //debugprint.Start(); Formatter.WriteLine("done", arch.DebugOutput); /* Load the vfs */ Formatter.Write("Starting vfs... ", arch.DebugOutput); Process vfs = LoadELFModule("vfs", mboot, stab, running_processes, 0x8000, new object[] { }); vfs.Start(); Formatter.WriteLine("done", arch.DebugOutput); /* Load the gui */ Formatter.Write("Starting gui... ", arch.DebugOutput); Process gui = LoadELFModule("gui", mboot, stab, running_processes, 0x8000, new object[] { }); gui.Start(); Formatter.WriteLine("done", arch.DebugOutput); /* Load the network subsystem */ Formatter.Write("Starting net... ", arch.DebugOutput); Process net = LoadELFModule("net", mboot, stab, running_processes, 0x8000, new object[] { }); net.Start(); Formatter.WriteLine("done", arch.DebugOutput); /* Startup thread does the rest as we need to wait for the Vfs to come up */ Process kernel_startup = Process.Create("kernel_startup", stab.GetAddress("_ZN11tysos#2Edll5tysos7Program_11SetupThread_Rv_P0"), 0x1000, arch.VirtualRegions, stab, new object[] { }, Program.arch.tysos_tls_length); arch.CurrentCpu.CurrentScheduler.Reschedule(kernel_startup.startup_thread); kernel_startup.started = true; if (do_debug) { System.Diagnostics.Debugger.Break(); } //libsupcs.OtherOperations.AsmBreakpoint(); //arch.EnableMultitasking(); Syscalls.SchedulerFunctions.Yield(); while (true) { ; } // Halt here libsupcs.OtherOperations.Halt(); /* Create kernel threads */ CreateKernelThreads(); /* Dump the current virtual region table */ arch.VirtualRegions.Dump(arch.DebugOutput); /* Start the processes */ Formatter.WriteLine("Going multitasking...", arch.BootInfoOutput); arch.EnableMultitasking(); while (true) { ; } }