📄 pk_processkey.cxx
字号:
/* * Copyright (C) 1998, 1999, 2001, 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. */#include <kerninc/kernel.hxx>#include <kerninc/Key.hxx>#include <kerninc/Invocation.hxx>#include <kerninc/Node.hxx>#include <kerninc/Process.hxx>#include <kerninc/Thread.hxx>#include <kerninc/CpuReserve.hxx>#include <eros/Invoke.h>#include <eros/StdKeyType.h>#include <eros/ProcessKey.h>#include <eros/machine/Registers.h>/* #define DEBUG */voidMaybeRepairCpuReserveLinkages(Node *theNode, CpuReserve* oldReserve, const Key &newKey) { /* We may have just changed the reserve of a domain. * Unfortunately, reserve pointers are kept in the thread * structure. We only need to check if the previous key was a * schedule key. If so, the thread we want (if any) is * somewhere on the thread chain of the old reserve, else it * doesn't exist. */ Thread *pThrd = 0;#ifdef DEBUG printf("Hunting down threads for cpuReserve %d (0x%08x)\n", oldKey.subType, oldReserve);#endif Link *tlnk = oldReserve->threadChain.next; while (tlnk) { Thread *lThrd = Thread::ThreadFromCpuReserveLinkage(tlnk);#ifdef DEBUG printf("Examine thread 0x%08x (tlnk 0x%08x)\n", lThrd, tlnk);#endif if ( lThrd->IsUser() ) { if (lThrd->context) { if ( ((Process *) lThrd->context)->procRoot == theNode ) { pThrd = lThrd; break; } } else if (lThrd->processKey.GetKeyOid() == theNode->ob.oid) { pThrd = lThrd; break; } } tlnk = tlnk->next; }#ifdef DEBUG printf("Found thread 0x%08x\n", pThrd);#endif if (pThrd) { if ( newKey.IsType(KT_Sched) ) { CpuReserve& newCpuReserve = CpuReserve::GetReserve(newKey); newCpuReserve.AddUserThread(pThrd); } else { pThrd->Unlink(); /* in case sleeping somewhere */ pThrd->MigrateTo(0); } }}voidProcessKey(Invocation& inv){ Node *theNode = (Node *) inv.key->GetObjectPtr(); if (inv.invokee && theNode == inv.invokee->procRoot && OC_Process_Swap == inv.entry.code && inv.entry.w1 != 2 && inv.entry.w1 != 4) dprintf(true, "Modifying invokee domain root\n"); if (inv.invokee && theNode == inv.invokee->keysNode && OC_Process_SwapKeyReg == inv.entry.code) dprintf(true, "Modifying invokee keys node\n"); switch (inv.entry.code) { case OC_KeyType: { COMMIT_POINT(); inv.exit.code = RC_OK; inv.exit.w1 = AKT_Process; return; } case OC_Process_Copy: { uint32_t slot = inv.entry.w1; COMMIT_POINT(); if (slot >= EROS_NODE_SIZE) dprintf(true, "Copy slot out of range\n"); if (slot == ProcBrand || slot >= EROS_NODE_SIZE) { inv.exit.code = RC_RequestError; return; } /* All of these complete ok. */ inv.exit.code = RC_OK; if ((*theNode)[slot].IsRdHazard()) theNode->ClearHazard(slot); inv.SetExitKey(0, theNode->slot[slot]); return; } case OC_Process_Swap: { if (theNode == Thread::CurContext()->keysNode) dprintf(true, "Swap involving sender keys\n"); uint32_t slot = inv.entry.w1; if (slot == ProcBrand || slot >= EROS_NODE_SIZE) { COMMIT_POINT(); inv.exit.code = RC_RequestError; return; } /* All of these complete ok. */ inv.exit.code = RC_OK; theNode->MakeObjectDirty(); COMMIT_POINT(); theNode->ClearHazard(slot); CpuReserve *oldReserve = 0; if ( slot == ProcSched && theNode->slot[slot].IsType(KT_Sched) ) oldReserve = &CpuReserve::GetReserve(theNode->slot[slot]); { Key k; /* temporary in case send and receive */ /* slots are the same. */ k.IKS_Set(theNode->slot[slot]); (*theNode)[slot].NH_Set(*inv.entry.key[0]); inv.SetExitKey(0, k); /* Unchain, but do not unprepare -- the objects do not have * on-disk keys. */ k.NH_Unchain(); } if (oldReserve) MaybeRepairCpuReserveLinkages(theNode, oldReserve, theNode->slot[slot]); Thread::Current()->Prepare(); inv.nextPC = ((Process *) Thread::CurContext())->GetPC(); return; } case OC_Process_CopyKeyReg: { Process* ac = theNode->GetDomainContext(); ac->Prepare(); COMMIT_POINT(); uint32_t slot = inv.entry.w1; if (slot < EROS_NODE_SIZE) { inv.SetExitKey(0, ac->keyReg[slot]); inv.exit.code = RC_OK; } else { inv.exit.code = RC_RequestError; } return; } case OC_Process_SwapKeyReg: { if (theNode == Thread::CurContext()->keysNode) dprintf(true, "Swap involving sender keys\n"); Process* ac = theNode->GetDomainContext(); ac->Prepare(); COMMIT_POINT(); uint32_t slot = inv.entry.w1; if (slot >= EROS_NODE_SIZE) { inv.exit.code = RC_RequestError; return; } inv.SetExitKey(0, ac->keyReg[slot]); if (slot != 0) { /* FIX: verify that the damn thing HAD key registers?? */ ac->keyReg[slot].NH_Set(*inv.entry.key[0]);#if 0 printf("set key reg slot %d to \n", slot); inv.entry.key[0].Print();#endif } inv.exit.code = RC_OK; return; }#if 0 case OC_Process_GetCtrlInfo32: { DomCtlInfo32_s info; Node *domRoot = (Node *) inv.key->GetObjectPtr(); inv.exit.code = RC_OK; ArchContext* ac = domRoot->GetDomainContext(); ac->Prepare(); COMMIT_POINT(); if (ac->GetControlInfo32(info) == false) inv.exit.code = RC_Process_Malformed; inv.CopyOut(sizeof(info), &info); return; }#endif case OC_Process_GetRegs32: { Registers regs; /* GetRegs32 length is machine specific, so it does its own copyout. */ inv.exit.code = RC_OK; assert( inv.invokee->IsRunnable() );#if 0 printf("GetRegs32: invokee is 0x%08x, IsActive? %c\n", inv.invokee, inv.IsActive() ? 'y' : 'n');#endif Process* ac = theNode->GetDomainContext(); ac->Prepare();#ifndef OPTION_PURE_EXIT_STRINGS inv.invokee->SetupExitString(inv, sizeof(regs));#endif COMMIT_POINT(); if (ac->GetRegs32(regs) == false) inv.exit.code = RC_Process_Malformed; inv.CopyOut(sizeof(regs), ®s); return; }#if 0 case OC_Process_SetCtrlInfo32: { DomCtlInfo32_s info; if ( inv.entry.len != sizeof(info) ) { inv.exit.code = RC_RequestError; COMMIT_POINT(); return; } inv.exit.code = RC_OK; ArchContext* ac = theNode->GetDomainContext(); ac->Prepare(); #ifndef OPTION_PURE_ENTRY_STRINGS Thread::CurContext()->SetupEntryString(inv);#endif COMMIT_POINT(); inv.CopyIn(sizeof(info), &info); if (ac->SetControlInfo32(info) == false) inv.exit.code = RC_Process_Malformed; return; }#endif case OC_Process_SetRegs32: { Registers regs; if ( inv.entry.len != sizeof(regs) ) { inv.exit.code = RC_RequestError; COMMIT_POINT(); return; } /* FIX: check embedded length and arch type! */ /* GetRegs32 length is machine specific, so it does its own copyout. */ inv.exit.code = RC_OK; Process* ac = theNode->GetDomainContext(); ac->Prepare();#ifndef OPTION_PURE_ENTRY_STRINGS Thread::CurContext()->SetupEntryString(inv);#endif COMMIT_POINT(); inv.CopyIn(sizeof(regs), ®s); if (ac->SetRegs32(regs) == false) inv.exit.code = RC_Process_Malformed; return; } case OC_Process_SwapMemory32: { inv.exit.w1 = inv.entry.w1; inv.exit.w2 = inv.entry.w2; inv.exit.w3 = inv.entry.w3; /* All of these complete ok. */ inv.exit.code = RC_OK; Process* ac = theNode->GetDomainContext(); ac->Prepare(); COMMIT_POINT(); ac->SetPC(inv.entry.w1); theNode->ClearHazard(ProcAddrSpace); { Key k; k.IKS_Set(theNode->slot[ProcAddrSpace]); (*theNode)[ProcAddrSpace].NH_Set(*inv.entry.key[0]); inv.SetExitKey(0, k); /* Unchain, but do not unprepare -- the objects do not have * on-disk keys. */ k.NH_Unchain(); } inv.nextPC = ((Process *) Thread::CurContext())->GetPC(); return; } case OC_Process_MkStartKey: { Process* p = theNode->GetDomainContext(); p->Prepare(); COMMIT_POINT(); uint32_t keyData = inv.entry.w1; if ( keyData > EROS_KEYDATA_MAX ) { inv.exit.code = RC_RequestError; dprintf(true, "Value 0x%08x is out of range\n", keyData); return; } /* All of these complete ok. */ inv.exit.code = RC_OK; /* AAARRRGGGGGHHHH!!!!! This used to fabricate an unprepared * key, which was making things REALLY slow. We do need to be * careful, as gate keys do not go on the same key chain as * domain keys. Still, it was just never THAT hard to get it * right. Grumble. */ if (inv.exit.pKey[0]) { Key &k = *inv.exit.pKey[0]; k.IKS_Unchain(); k.InitType(KT_Start); k.keyData = keyData; k.gk.pContext = p; k.gk.next = p->kr.next; k.gk.next->prev = (KeyRing *) &k; p->kr.next = (KeyRing *) &k; k.gk.prev = &p->kr; k.SetPrepared(); } return; } /* I'm holding off on these because they require killing the * active thread, and I want to make sure I do that when I'm awake. */ case OC_Process_MkProcessAvailable: case OC_Process_MkProcessWaiting: COMMIT_POINT(); inv.exit.code = RC_UnknownRequest; return; case OC_Process_MkResumeKey: case OC_Process_MkFaultKey: COMMIT_POINT(); inv.SetExitKey(0, *inv.key); if (inv.exit.pKey[0]) { inv.exit.pKey[0]->NH_Unprepare(); inv.exit.pKey[0]->InitType(KT_Resume); inv.exit.pKey[0]->keyData = (inv.entry.code == OC_Process_MkResumeKey) ? KsitResume : KsitFault; } inv.exit.code = RC_OK; return; case OC_Process_GetFloatRegs: case OC_Process_SetFloatRegs: COMMIT_POINT(); fatal("Domain key order %d ot yet implemented\n", inv.entry.code); default: COMMIT_POINT(); inv.exit.code = RC_UnknownRequest; return; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -