From: Gabe Black Date: Sun, 30 Oct 2011 07:33:02 +0000 (-0700) Subject: SE/FS: Make getProcessPtr available in both modes, and get rid of FULL_SYSTEMs. X-Git-Tag: stable_2012_06_28~306 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=facb40f3ffce30cd9bc3b904eed5761d2d8b91c9;p=gem5.git SE/FS: Make getProcessPtr available in both modes, and get rid of FULL_SYSTEMs. --- diff --git a/src/arch/mips/tlb.cc b/src/arch/mips/tlb.cc index e35ac6d4a..52e13dfc3 100644 --- a/src/arch/mips/tlb.cc +++ b/src/arch/mips/tlb.cc @@ -295,182 +295,45 @@ TLB::regStats() Fault TLB::translateInst(RequestPtr req, ThreadContext *tc) { -#if !FULL_SYSTEM - Process * p = tc->getProcessPtr(); + if (!FullSystem) { + Process * p = tc->getProcessPtr(); - Fault fault = p->pTable->translate(req); - if (fault != NoFault) - return fault; + Fault fault = p->pTable->translate(req); + if (fault != NoFault) + return fault; - return NoFault; -#else - Addr vaddr = req->getVaddr(); - - bool misaligned = (req->getSize() - 1) & vaddr; - - if (IsKSeg0(vaddr)) { - // Address will not be translated through TLB, set response, and go! - req->setPaddr(KSeg02Phys(vaddr)); - if (getOperatingMode(tc->readMiscReg(MISCREG_STATUS)) != mode_kernel || - misaligned) { - return new AddressErrorFault(vaddr, false); - } - } else if(IsKSeg1(vaddr)) { - // Address will not be translated through TLB, set response, and go! - req->setPaddr(KSeg02Phys(vaddr)); + return NoFault; } else { - /* - * This is an optimization - smallPages is updated every time a TLB - * operation is performed. That way, we don't need to look at - * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup - */ - Addr VPN; - if (smallPages == 1) { - VPN = (vaddr >> 11); - } else { - VPN = ((vaddr >> 11) & 0xFFFFFFFC); - } - uint8_t Asid = req->getAsid(); - if (misaligned) { - // Unaligned address! - return new AddressErrorFault(vaddr, false); - } - PTE *pte = lookup(VPN,Asid); - if (pte != NULL) { - // Ok, found something - /* Check for valid bits */ - int EvenOdd; - bool Valid; - if ((((vaddr) >> pte->AddrShiftAmount) & 1) == 0) { - // Check even bits - Valid = pte->V0; - EvenOdd = 0; - } else { - // Check odd bits - Valid = pte->V1; - EvenOdd = 1; - } - - if (Valid == false) { - return new InvalidFault(Asid, vaddr, vpn, false); - } else { - // Ok, this is really a match, set paddr - Addr PAddr; - if (EvenOdd == 0) { - PAddr = pte->PFN0; - } else { - PAddr = pte->PFN1; - } - PAddr >>= (pte->AddrShiftAmount - 12); - PAddr <<= pte->AddrShiftAmount; - PAddr |= (vaddr & pte->OffsetMask); - req->setPaddr(PAddr); - } - } else { - // Didn't find any match, return a TLB Refill Exception - return new RefillFault(Asid, vaddr, vpn, false); - } + panic("translateInst not implemented in MIPS.\n"); } - return checkCacheability(req); -#endif } Fault TLB::translateData(RequestPtr req, ThreadContext *tc, bool write) { -#if !FULL_SYSTEM - //@TODO: This should actually use TLB instead of going directly - // to the page table in syscall mode. - /** - * Check for alignment faults - */ - if (req->getVaddr() & (req->getSize() - 1)) { - DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(), - req->getSize()); - return new AddressErrorFault(req->getVaddr(), write); - } - - - Process * p = tc->getProcessPtr(); + if (!FullSystem) { + //@TODO: This should actually use TLB instead of going directly + // to the page table in syscall mode. + /** + * Check for alignment faults + */ + if (req->getVaddr() & (req->getSize() - 1)) { + DPRINTF(TLB, "Alignment Fault on %#x, size = %d", req->getVaddr(), + req->getSize()); + return new AddressErrorFault(req->getVaddr(), write); + } - Fault fault = p->pTable->translate(req); - if (fault != NoFault) - return fault; - return NoFault; -#else - Addr vaddr = req->getVaddr(); + Process * p = tc->getProcessPtr(); - bool misaligned = (req->getSize() - 1) & vaddr; + Fault fault = p->pTable->translate(req); + if (fault != NoFault) + return fault; - if (IsKSeg0(vaddr)) { - // Address will not be translated through TLB, set response, and go! - req->setPaddr(KSeg02Phys(vaddr)); - if (getOperatingMode(tc->readMiscReg(MISCREG_STATUS)) != mode_kernel || - misaligned) { - return new AddressErrorFault(vaddr, true); - } - } else if(IsKSeg1(vaddr)) { - // Address will not be translated through TLB, set response, and go! - req->setPaddr(KSeg02Phys(vaddr)); + return NoFault; } else { - /* - * This is an optimization - smallPages is updated every time a TLB - * operation is performed. That way, we don't need to look at - * Config3 _ SP and PageGrain _ ESP every time we do a TLB lookup - */ - Addr VPN = (vaddr >> 11) & 0xFFFFFFFC; - if (smallPages == 1) { - VPN = vaddr >> 11; - } - uint8_t Asid = req->getAsid(); - PTE *pte = lookup(VPN, Asid); - if (misaligned) { - return new AddressErrorFault(vaddr, true); - } - if (pte != NULL) { - // Ok, found something - /* Check for valid bits */ - int EvenOdd; - bool Valid; - bool Dirty; - if ((((vaddr >> pte->AddrShiftAmount) & 1)) == 0) { - // Check even bits - Valid = pte->V0; - Dirty = pte->D0; - EvenOdd = 0; - } else { - // Check odd bits - Valid = pte->V1; - Dirty = pte->D1; - EvenOdd = 1; - } - - if (Valid == false) { - return new InvalidFault(Asid, vaddr, VPN, true); - } else { - // Ok, this is really a match, set paddr - if (!Dirty) { - return new TlbModifiedFault(Asid, vaddr, VPN); - } - Addr PAddr; - if (EvenOdd == 0) { - PAddr = pte->PFN0; - } else { - PAddr = pte->PFN1; - } - PAddr >>= (pte->AddrShiftAmount - 12); - PAddr <<= pte->AddrShiftAmount; - PAddr |= (vaddr & pte->OffsetMask); - req->setPaddr(PAddr); - } - } else { - // Didn't find any match, return a TLB Refill Exception - return new RefillFault(Asid, vaddr, VPN, true); - } + panic("translateData not implemented in MIPS.\n"); } - return checkCacheability(req); -#endif } Fault diff --git a/src/arch/sparc/faults.cc b/src/arch/sparc/faults.cc index fb0f6acb1..584b8299c 100644 --- a/src/arch/sparc/faults.cc +++ b/src/arch/sparc/faults.cc @@ -41,9 +41,9 @@ #include "cpu/thread_context.hh" #if !FULL_SYSTEM #include "arch/sparc/process.hh" +#endif #include "mem/page_table.hh" #include "sim/process.hh" -#endif #include "sim/full_system.hh" using namespace std; @@ -624,43 +624,43 @@ PowerOnReset::invoke(ThreadContext *tc, StaticInstPtr inst) void FastInstructionAccessMMUMiss::invoke(ThreadContext *tc, StaticInstPtr inst) { -#if !FULL_SYSTEM - Process *p = tc->getProcessPtr(); - TlbEntry entry; - bool success = p->pTable->lookup(vaddr, entry); - if (!success) { - panic("Tried to execute unmapped address %#x.\n", vaddr); + if (FullSystem) { + SparcFaultBase::invoke(tc, inst); } else { - Addr alignedVaddr = p->pTable->pageAlign(vaddr); - tc->getITBPtr()->insert(alignedVaddr, 0 /*partition id*/, - p->M5_pid /*context id*/, false, entry.pte); + Process *p = tc->getProcessPtr(); + TlbEntry entry; + bool success = p->pTable->lookup(vaddr, entry); + if (!success) { + panic("Tried to execute unmapped address %#x.\n", vaddr); + } else { + Addr alignedVaddr = p->pTable->pageAlign(vaddr); + tc->getITBPtr()->insert(alignedVaddr, 0 /*partition id*/, + p->M5_pid /*context id*/, false, entry.pte); + } } -#else - SparcFaultBase::invoke(tc, inst); -#endif } void FastDataAccessMMUMiss::invoke(ThreadContext *tc, StaticInstPtr inst) { -#if !FULL_SYSTEM - Process *p = tc->getProcessPtr(); - TlbEntry entry; - bool success = p->pTable->lookup(vaddr, entry); - if (!success) { - if (p->fixupStackFault(vaddr)) - success = p->pTable->lookup(vaddr, entry); - } - if (!success) { - panic("Tried to access unmapped address %#x.\n", vaddr); + if (FullSystem) { + SparcFaultBase::invoke(tc, inst); } else { - Addr alignedVaddr = p->pTable->pageAlign(vaddr); - tc->getDTBPtr()->insert(alignedVaddr, 0 /*partition id*/, - p->M5_pid /*context id*/, false, entry.pte); + Process *p = tc->getProcessPtr(); + TlbEntry entry; + bool success = p->pTable->lookup(vaddr, entry); + if (!success) { + if (p->fixupStackFault(vaddr)) + success = p->pTable->lookup(vaddr, entry); + } + if (!success) { + panic("Tried to access unmapped address %#x.\n", vaddr); + } else { + Addr alignedVaddr = p->pTable->pageAlign(vaddr); + tc->getDTBPtr()->insert(alignedVaddr, 0 /*partition id*/, + p->M5_pid /*context id*/, false, entry.pte); + } } -#else - SparcFaultBase::invoke(tc, inst); -#endif } void diff --git a/src/arch/sparc/remote_gdb.cc b/src/arch/sparc/remote_gdb.cc index 712314e01..ed77000fe 100644 --- a/src/arch/sparc/remote_gdb.cc +++ b/src/arch/sparc/remote_gdb.cc @@ -135,6 +135,7 @@ #include "mem/physical.hh" #include "mem/port.hh" #include "sim/byteswap.hh" +#include "sim/full_system.hh" #include "sim/process.hh" #include "sim/system.hh" @@ -156,18 +157,18 @@ RemoteGDB::acc(Addr va, size_t len) //@Todo In NetBSD, this function checks if all addresses // from va to va + len have valid page map entries. Not // sure how this will work for other OSes or in general. -#if FULL_SYSTEM - if (va) - return true; - return false; -#else - TlbEntry entry; - // Check to make sure the first byte is mapped into the processes address - // space. - if (context->getProcessPtr()->pTable->lookup(va, entry)) - return true; - return false; -#endif + if (FullSystem) { + if (va) + return true; + return false; + } else { + TlbEntry entry; + // Check to make sure the first byte is mapped into the processes + // address space. + if (context->getProcessPtr()->pTable->lookup(va, entry)) + return true; + return false; + } } /////////////////////////////////////////////////////////// diff --git a/src/arch/sparc/utility.cc b/src/arch/sparc/utility.cc index c6616f43e..63b8e7960 100644 --- a/src/arch/sparc/utility.cc +++ b/src/arch/sparc/utility.cc @@ -31,10 +31,8 @@ #include "arch/sparc/faults.hh" #include "arch/sparc/utility.hh" -#if FULL_SYSTEM #include "arch/sparc/vtophys.hh" #include "mem/vport.hh" -#endif namespace SparcISA { @@ -48,21 +46,21 @@ namespace SparcISA { uint64_t getArgument(ThreadContext *tc, int &number, uint16_t size, bool fp) { -#if FULL_SYSTEM - const int NumArgumentRegs = 6; - if (number < NumArgumentRegs) { - return tc->readIntReg(8 + number); + if (FullSystem) { + const int NumArgumentRegs = 6; + if (number < NumArgumentRegs) { + return tc->readIntReg(8 + number); + } else { + Addr sp = tc->readIntReg(StackPointerReg); + VirtualPort *vp = tc->getVirtPort(); + uint64_t arg = vp->read(sp + 92 + + (number-NumArgumentRegs) * sizeof(uint64_t)); + return arg; + } } else { - Addr sp = tc->readIntReg(StackPointerReg); - VirtualPort *vp = tc->getVirtPort(); - uint64_t arg = vp->read(sp + 92 + - (number-NumArgumentRegs) * sizeof(uint64_t)); - return arg; + panic("getArgument() only implemented for full system\n"); + M5_DUMMY_RETURN } -#else - panic("getArgument() only implemented for FULL_SYSTEM\n"); - M5_DUMMY_RETURN -#endif } void diff --git a/src/arch/sparc/utility.hh b/src/arch/sparc/utility.hh index 76b551ac8..ee94ef29a 100644 --- a/src/arch/sparc/utility.hh +++ b/src/arch/sparc/utility.hh @@ -39,6 +39,7 @@ #include "cpu/static_inst.hh" #include "cpu/thread_context.hh" #include "sim/fault_fwd.hh" +#include "sim/full_system.hh" namespace SparcISA { @@ -73,13 +74,9 @@ void initCPU(ThreadContext *tc, int cpuId); inline void startupCPU(ThreadContext *tc, int cpuId) { -#if FULL_SYSTEM // Other CPUs will get activated by IPIs - if (cpuId == 0) + if (cpuId == 0 || !FullSystem) tc->activate(0); -#else - tc->activate(0); -#endif } void copyRegs(ThreadContext *src, ThreadContext *dest); diff --git a/src/arch/x86/tlb.cc b/src/arch/x86/tlb.cc index 88eb19b54..ff30697e5 100644 --- a/src/arch/x86/tlb.cc +++ b/src/arch/x86/tlb.cc @@ -54,14 +54,10 @@ #include "cpu/thread_context.hh" #include "debug/TLB.hh" #include "mem/packet_access.hh" -#include "mem/request.hh" - -#if !FULL_SYSTEM #include "mem/page_table.hh" -#include "sim/process.hh" -#endif - +#include "mem/request.hh" #include "sim/full_system.hh" +#include "sim/process.hh" namespace X86ISA { @@ -302,7 +298,6 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, entry = lookup(vaddr); assert(entry); } else { -#if !FULL_SYSTEM DPRINTF(TLB, "Handling a TLB miss for " "address %#x at pc %#x.\n", vaddr, tc->instAddr()); @@ -326,7 +321,6 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, entry = insert(alignedVaddr, newEntry); } DPRINTF(TLB, "Miss was serviced.\n"); -#endif } } // Do paging protection checks. @@ -367,27 +361,29 @@ TLB::translate(RequestPtr req, ThreadContext *tc, Translation *translation, req->setPaddr(vaddr); } // Check for an access to the local APIC -#if FULL_SYSTEM - LocalApicBase localApicBase = tc->readMiscRegNoEffect(MISCREG_APIC_BASE); - Addr baseAddr = localApicBase.base * PageBytes; - Addr paddr = req->getPaddr(); - if (baseAddr <= paddr && baseAddr + PageBytes > paddr) { - // The Intel developer's manuals say the below restrictions apply, - // but the linux kernel, because of a compiler optimization, breaks - // them. - /* - // Check alignment - if (paddr & ((32/8) - 1)) - return new GeneralProtection(0); - // Check access size - if (req->getSize() != (32/8)) - return new GeneralProtection(0); - */ - // Force the access to be uncacheable. - req->setFlags(Request::UNCACHEABLE); - req->setPaddr(x86LocalAPICAddress(tc->contextId(), paddr - baseAddr)); + if (FullSystem) { + LocalApicBase localApicBase = + tc->readMiscRegNoEffect(MISCREG_APIC_BASE); + Addr baseAddr = localApicBase.base * PageBytes; + Addr paddr = req->getPaddr(); + if (baseAddr <= paddr && baseAddr + PageBytes > paddr) { + // The Intel developer's manuals say the below restrictions apply, + // but the linux kernel, because of a compiler optimization, breaks + // them. + /* + // Check alignment + if (paddr & ((32/8) - 1)) + return new GeneralProtection(0); + // Check access size + if (req->getSize() != (32/8)) + return new GeneralProtection(0); + */ + // Force the access to be uncacheable. + req->setFlags(Request::UNCACHEABLE); + req->setPaddr(x86LocalAPICAddress(tc->contextId(), + paddr - baseAddr)); + } } -#endif return NoFault; }; diff --git a/src/cpu/checker/thread_context.hh b/src/cpu/checker/thread_context.hh index 94ba561f0..8b741080b 100644 --- a/src/cpu/checker/thread_context.hh +++ b/src/cpu/checker/thread_context.hh @@ -96,9 +96,8 @@ class CheckerThreadContext : public ThreadContext TheISA::Kernel::Statistics *getKernelStats() { return actualTC->getKernelStats(); } -#else - Process *getProcessPtr() { return actualTC->getProcessPtr(); } #endif + Process *getProcessPtr() { return actualTC->getProcessPtr(); } TranslatingPort *getMemPort() { return actualTC->getMemPort(); } diff --git a/src/cpu/inorder/thread_context.cc b/src/cpu/inorder/thread_context.cc index f5e55627c..8fc6ac75f 100644 --- a/src/cpu/inorder/thread_context.cc +++ b/src/cpu/inorder/thread_context.cc @@ -85,11 +85,7 @@ InOrderThreadContext::takeOverFrom(ThreadContext *old_context) { // some things should already be set up assert(getSystemPtr() == old_context->getSystemPtr()); -#if !FULL_SYSTEM assert(getProcessPtr() == old_context->getProcessPtr()); -#endif - - // copy over functional state setStatus(old_context->status()); diff --git a/src/cpu/inorder/thread_context.hh b/src/cpu/inorder/thread_context.hh index 9b071ee5d..95338c05c 100644 --- a/src/cpu/inorder/thread_context.hh +++ b/src/cpu/inorder/thread_context.hh @@ -142,10 +142,9 @@ class InOrderThreadContext : public ThreadContext { return this->thread->quiesceEvent; } -#else +#endif /** Returns a pointer to this thread's process. */ Process *getProcessPtr() { return thread->getProcessPtr(); } -#endif TranslatingPort *getMemPort() { return thread->getMemPort(); } diff --git a/src/cpu/o3/thread_context.hh b/src/cpu/o3/thread_context.hh index 2688e75e1..145d6fd29 100755 --- a/src/cpu/o3/thread_context.hh +++ b/src/cpu/o3/thread_context.hh @@ -98,10 +98,9 @@ class O3ThreadContext : public ThreadContext { return thread->kernelStats; } virtual void connectMemPorts(ThreadContext *tc) { thread->connectMemPorts(tc); } -#else +#endif /** Returns a pointer to this thread's process. */ virtual Process *getProcessPtr() { return thread->getProcessPtr(); } -#endif virtual TranslatingPort *getMemPort() { return thread->getMemPort(); } diff --git a/src/cpu/o3/thread_context_impl.hh b/src/cpu/o3/thread_context_impl.hh index 515fa5a50..0952465d4 100755 --- a/src/cpu/o3/thread_context_impl.hh +++ b/src/cpu/o3/thread_context_impl.hh @@ -70,9 +70,8 @@ O3ThreadContext::takeOverFrom(ThreadContext *old_context) // some things should already be set up #if FULL_SYSTEM assert(getSystemPtr() == old_context->getSystemPtr()); -#else - assert(getProcessPtr() == old_context->getProcessPtr()); #endif + assert(getProcessPtr() == old_context->getProcessPtr()); // copy over functional state setStatus(old_context->status()); diff --git a/src/cpu/ozone/cpu.hh b/src/cpu/ozone/cpu.hh index 4860dd271..70b46ec5f 100644 --- a/src/cpu/ozone/cpu.hh +++ b/src/cpu/ozone/cpu.hh @@ -123,9 +123,8 @@ class OzoneCPU : public BaseCPU TheISA::Kernel::Statistics *getKernelStats() { return thread->getKernelStats(); } -#else - Process *getProcessPtr() { return thread->getProcessPtr(); } #endif + Process *getProcessPtr() { return thread->getProcessPtr(); } TranslatingPort *getMemPort() { return thread->getMemPort(); } diff --git a/src/cpu/ozone/cpu_impl.hh b/src/cpu/ozone/cpu_impl.hh index bb6e96ecc..724bd99a4 100644 --- a/src/cpu/ozone/cpu_impl.hh +++ b/src/cpu/ozone/cpu_impl.hh @@ -671,9 +671,8 @@ OzoneCPU::OzoneTC::takeOverFrom(ThreadContext *old_context) // some things should already be set up #if FULL_SYSTEM assert(getSystemPtr() == old_context->getSystemPtr()); -#else - assert(getProcessPtr() == old_context->getProcessPtr()); #endif + assert(getProcessPtr() == old_context->getProcessPtr()); // copy over functional state setStatus(old_context->status()); diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc index 6b9f60402..53534a4f3 100644 --- a/src/cpu/simple_thread.cc +++ b/src/cpu/simple_thread.cc @@ -41,6 +41,7 @@ #include "cpu/thread_context.hh" #include "mem/vport.hh" #include "params/BaseCPU.hh" +#include "sim/process.hh" #if FULL_SYSTEM #include "arch/kernel_stats.hh" @@ -55,7 +56,6 @@ #include "sim/sim_exit.hh" #else #include "mem/translating_port.hh" -#include "sim/process.hh" #include "sim/system.hh" #endif @@ -123,9 +123,8 @@ SimpleThread::takeOverFrom(ThreadContext *oldContext) // some things should already be set up #if FULL_SYSTEM assert(system == oldContext->getSystemPtr()); -#else - assert(process == oldContext->getProcessPtr()); #endif + assert(process == oldContext->getProcessPtr()); copyState(oldContext); #if FULL_SYSTEM diff --git a/src/cpu/thread_context.hh b/src/cpu/thread_context.hh index f43940fe3..e4e26d03c 100644 --- a/src/cpu/thread_context.hh +++ b/src/cpu/thread_context.hh @@ -129,9 +129,8 @@ class ThreadContext virtual TheISA::Kernel::Statistics *getKernelStats() = 0; virtual void connectMemPorts(ThreadContext *tc) = 0; -#else - virtual Process *getProcessPtr() = 0; #endif + virtual Process *getProcessPtr() = 0; virtual TranslatingPort *getMemPort() = 0; @@ -299,9 +298,8 @@ class ProxyThreadContext : public ThreadContext { return actualTC->getKernelStats(); } void connectMemPorts(ThreadContext *tc) { actualTC->connectMemPorts(tc); } -#else - Process *getProcessPtr() { return actualTC->getProcessPtr(); } #endif + Process *getProcessPtr() { return actualTC->getProcessPtr(); } TranslatingPort *getMemPort() { return actualTC->getMemPort(); } diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh index 10b87f02c..bc16b4f98 100644 --- a/src/cpu/thread_state.hh +++ b/src/cpu/thread_state.hh @@ -101,9 +101,8 @@ struct ThreadState { void profileSample(); TheISA::Kernel::Statistics *getKernelStats() { return kernelStats; } -#else - Process *getProcessPtr() { return process; } #endif + Process *getProcessPtr() { return process; } TranslatingPort *getMemPort(); diff --git a/src/kern/linux/linux.hh b/src/kern/linux/linux.hh index 7fe107139..d816a0932 100644 --- a/src/kern/linux/linux.hh +++ b/src/kern/linux/linux.hh @@ -34,12 +34,6 @@ #include "base/types.hh" #include "config/full_system.hh" -#if FULL_SYSTEM - -class Linux {}; - -#else //!FULL_SYSTEM - #include #include "kern/operatingsystem.hh" @@ -180,7 +174,4 @@ class Linux : public OperatingSystem }; // class Linux - -#endif // FULL_SYSTEM - #endif // __LINUX_HH__ diff --git a/src/kern/operatingsystem.hh b/src/kern/operatingsystem.hh index 6574e3c6b..fd5899cf8 100644 --- a/src/kern/operatingsystem.hh +++ b/src/kern/operatingsystem.hh @@ -32,13 +32,7 @@ #define __KERN_OPERATINGSYSTEM_HH__ #include "base/types.hh" -#include "config/full_system.hh" -#if FULL_SYSTEM - -class OperatingSystem {}; - -#else //!FULL_SYSTEM #include class LiveProcess; @@ -128,7 +122,4 @@ class OperatingSystem { }; // class OperatingSystem - -#endif // FULL_SYSTEM - #endif // __OPERATINGSYSTEM_HH__