📄 kern_main.cxx
字号:
/* * Copyright (C) 1998, 1999, Jonathan S. Shapiro. * * This file is part of the EROS Operating System. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* main.cxx - initialization and startup for EROS. * * One of the design rules for EROS was that no global class should * require construction. It is assumed that any classes that have * global instances will supply an init() routine that can be directly * called from the EROS main() routine. On entry to main(), * interrupts are disabled. *//* currently, no arguments to the EROS kernel: */#include <kerninc/kernel.hxx>/* #include "lostart.hxx" */#include <kerninc/KernStream.hxx>#include <kerninc/Machine.hxx>#include <kerninc/ObjectCache.hxx>#include <kerninc/util.h>#include <kerninc/Thread.hxx>#include <kerninc/IRQ.hxx>#include <kerninc/Debug.hxx>#include <kerninc/BlockDev.hxx>#include <kerninc/Partition.hxx>#include <kerninc/CpuReserve.hxx>#include <kerninc/Process.hxx>#include <kerninc/Invocation.hxx>#include <disk/DiskKey.hxx>#include <kerninc/BootInfo.h>#include <kerninc/ObjectSource.hxx>extern "C" { int main(int); extern uint32_t StartupStack; extern uint32_t StartupStackTop;}/* NOTE: this is NOT an extern declaration! */extern "C" { BootInfo *BootInfoPtr;}void main_thread_entry();/* Need an initial reserve setup to keep main() running past first * interrupt: */KernThread InitialThread("Initial", main_thread_entry, &StartupStack, &StartupStackTop);intmain(int /* isboot */){ /* Initialize the stuff we don't go anywhere without: */ Thread::curThread = &InitialThread; CpuReserve::Current = &CpuReserve::KernThreadCpuReserve; CpuReserve::Current->AddKernelThread(&InitialThread); Thread::curThread->state = Thread::Running; Machine::BootInit(); SysTimer::BootInit(); Invocation::BootInit(); #ifdef OPTION_DDB extern void ddb_init(); ddb_init();#endif#if 0 Debugger();#endif IRQ::DISABLE(); InitialThread.context->Resume();}extern void StartIdleThread();extern void StartCheckThread();voidmain_thread_entry(){ printf("Continuing from main thread...\n"); #if 0 Debugger();#endif StartIdleThread(); StartCheckThread(); #if 0 { void *malloc(size_t nBytes); void heap_init(); heap_init(); (void) malloc(1025*EROS_PAGE_SIZE); } dprintf(true, "After malloc()\n");#endif /* Allocate all of the boot-time allocated structures: */ CpuReserve::AllocUserCpuReserves(); Process::AllocUserContexts(); /* machine dependent! */ Thread::AllocUserThreads(); extern void AllocReturnerBuffer(); AllocReturnerBuffer(); /* Initialize the object sources, then allocate space for the in-core nodes, pages, and the CoreTable: */ ObjectCache::Init(); printf("Object cache initialized...\n"); printf("main() thread is 0x%x\n", &InitialThread);#if 0 dprintf(true, "main() thread: about to call RunMountDaemon...\n");#endif /* Following should be done before any possibility of a time key * getting prepared: */ SysTimer::InitTimePage(); /* FROM THIS POINT ON IT IS LEGAL TO PERFORM I/O AND TO ENQUEUE THE * CURRENT THREAD */ #if 0 dprintf(true, "Mount daemon ran to completion\n");#endif /* halt(); */ #if 0 Debugger();#endif /* Start the primordial process identified by the IPL key */ Thread* thread = new Thread; assert(thread); assert (thread->processKey.IsUnprepared()); assert( thread->processKey.IsHazard() == false );#ifdef OPTION_DDB if ( Machine::IsDebugBoot() ) dprintf(true, "Stopping before waking up IPL thread.\n");#endif /* Forge a domain key for this thread: */ Key& k = thread->processKey; if(BootInfoPtr->iplKey.IsType(KT_Process)) { k.InitType(KT_Process); k.unprep.oid = BootInfoPtr->iplKey.unprep.oid; k.unprep.count = BootInfoPtr->iplKey.unprep.count; } else { printf("No IPL key!\n"); } /* The process prepare logic will appropriately adjust this priority if it is wrong -- this guess only has to be good enough to get the thread scheduled. */ CpuReserve::GetHighestReserve().AddUserThread(thread); KernStream::BeginUserThreads(); thread->Wakeup();#ifdef OPTION_TEST_PROCS printf( "\n" "- The rapidly moving twiddle is caused by the idle thread, which\n" " is in an infinite loop calling Yield().\n" "- The slower twiddle is driven by the twiddler every 250ms.\n" "- The timer is obvious.\n" "- The slowest twiddle is me ticking every 10 seconds or so.\n"); printf("\nYour cpu type is %d (%s)\n", Machine::GetCpuType(), Machine::GetCpuVendor()); uint64_t startTick = SysTimer::Now(); uint64_t ms = 0ll; uint32_t tick = 0; for(;;) { ms += 10000ll; tick++; uint64_t wakeTick = startTick + Machine::MillisecondsToTicks(ms); IRQ::DISABLE(); Thread::Current()->WakeUpAtTick(wakeTick); Thread::Current()->SleepOn(IdlePile); IRQ::ENABLE(); Thread::Current()->DirectedYield(); }#endif /* We will never wake up again... */ Thread::Current()->SleepOn(IdlePile); Thread::Current()->DirectedYield(); pause(); /* NOTREACHED */ /* At this point, there are no threads running, and we are running * off of the kernel interrupt stack. We now set those threads in * motion in no particular order. Most of them will quickly go to * sleep after doing some brief initializaeion. The one we care * about particularly is the mount daemon, which will mount all of * the disks and set all threads in motion. */ /* In the early test code, the only thread that actually gets woken * up here is the wall clock thread. */ printf("Somehow halted\n"); halt('m'); printf("main(): exit\n");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -