📄 exec.cpp
字号:
// RETURNS: TRUE .. process moved// FALSE .. unknown process or not suspended!//BOOL Exec::Resume (UINT16 uTarg){ if (uTarg == PqSusBlock.PqGet(uTarg)) { arrPCB[uTarg].uStatus &= ~PS_Suspended; PqBlocked.PqAdd(arrPCB[uTarg]); MSG msg(ID_Kernel, ANI_SBLK_BLK, uTarg); pTx->SendMsg(ID_ANIM, &msg); return TRUE; } if (uTarg == PqSusReady.PqGet(uTarg)) { arrPCB[uTarg].uStatus &= ~PS_Suspended; PqReady.PqAdd(arrPCB[uTarg]); MSG msg(ID_Kernel, ANI_SRDY_RDY, uTarg); pTx->SendMsg(ID_ANIM, &msg); return TRUE; } return FALSE;}/////////////////// Add the passed message to the reply message queue of process <uProc>// (which will cause it to un-block next time the scheduler runs). In// this release of RCOS, the reply queue is limited to one message for// simplicity. If the process was suspended, move it to the Suspended// Ready queue.//// If the unblocking process is free to run and has a higher priority// than the current process (if any), of the reason for the unblocking// is <KM_Signal> (ie an IPC message), the current process gets pre-empted// by unilaterally clobbering its remaining quantum.//void Exec::PostReply (UINT16 uProc, PMSG pM){ if (arrPCB[uProc].uPid != NO_PROC) { arrPCB[uProc].pReply = new MSG(*pM); arrPCB[uProc].uStatus &= ~PS_Blocked; if (arrPCB[uProc].uStatus & PS_Suspended) { if (uProc == PqSusBlock.PqGet(uProc)) { PqSusReady.PqAdd(arrPCB[uProc]); MSG msg(ID_Kernel, ANI_SBLK_SRDY, uProc); pTx->SendMsg(ID_ANIM, &msg); } } else if ((uCurProc != NO_PROC) && ((arrPCB[uProc].nPriority > arrPCB[uCurProc].nPriority) || (pM->wMsgType == KM_Signal))) { arrPCB[uCurProc].nQuantum = PCD_PREEMPT; MSG msg(ID_Kernel, ANI_PREEMPT, uProc); pTx->SendMsg(ID_ANIM, &msg); } }}//////////////////////// Remove all trace of this process and its memory allocation - including// any shared memory blocks.// NOTE :: This is VERY incomplete - frinstance, we unilaterally dispose// of memory - what if the process is sharing text with another, eh?// RETURNS: TRUE .. process deleted Ok// FALSE .. invalid process ID//BOOL Exec::Kill (UINT16 uTarg){ if (arrPCB[uTarg].uPid != NO_PROC) { MSG msg(ID_Kernel, KM_Close, (UINT16)arrMCB[uTarg].hText); pTx->SendMsg(ID_MMU, &msg); arrMCB[uTarg].hText = (HANDLE)ID_NULL; msg = message(ID_Kernel, KM_Close, arrMCB[uTarg].hStack); pTx->SendMsg(ID_MMU, &msg); arrMCB[uTarg].hStack = (HANDLE)ID_NULL; if (arrPCB[uTarg].pszName) { DELETE_ARRAY arrPCB[uTarg].pszName; arrPCB[uTarg].pszName = NULL; } if (arrPCB[uTarg].pDev) { delete arrPCB[uTarg].pDev; arrPCB[uTarg].pDev = NULL; } UINT16 *pn; while (pn = (UINT16*)arrPCB[uTarg].Share.DblGetHead()) SmClose(uTarg, *pn); if (arrPCB[uTarg].pFile) delete arrPCB[uTarg].pFile; arrPCB[uTarg].pFile = NULL; arrPCB[uTarg].uPid = NO_PROC; --uProcCnt; return TRUE; } return FALSE;}//////////////////////// Create a new process - Only way to do this is for the current process// to fork (are processes like bacteria?), but Process ZERO pulls a trick.// It is not a p-code process, but it has stack and text segments allocated// to it which we will duplicate for its child. Before invoking <fork>, it// has set the p-code to <execl> and loaded the name of the replacement// program onto its stack - so when the new process (Child of Conx) gets// the CPU, it's first action is to load itself. P-code processes that// fork will duplicate their stack and text, retaining any handles to shared// memory, semiphores and open streams. Note that shared memory blocks must// have their usage count increased.//// RETURNS: PID Of child created, or// NO_PROC if process could not be created//UINT16 Exec::Fork (void){ if (uProcCnt < MAX_PROC) { INT16 i; for (i = 1; i < MAX_PROC; i++) if (arrPCB[i].uPid == NO_PROC) break; arrPCB[i].uStatus = PS_Zombie; MSG msg(ID_Kernel, MMU_Duplicate, arrMCB[uCurProc].hText); pTx->SendMsg(ID_MMU, &msg); if (arrMCB[i].hText = (HANDLE)msg.wParam) { msg = message(ID_Kernel, MMU_Duplicate, arrMCB[uCurProc].hStack); pTx->SendMsg(ID_MMU, &msg); if (0 == (arrMCB[i].hStack = (HANDLE)msg.wParam)) { msg = message(ID_Kernel, KM_Close, arrMCB[i].hText); pTx->SendMsg(ID_MMU, &msg); } else { ++uProcCnt; arrPCB[i].uPid = i; arrPCB[i].uPidp = uCurProc; arrPCB[i].nPriority = DEF_PRIORITY; arrPCB[i].pReply = NULL; arrPCB[i].pFile = NULL; arrPCB[i].uIP = arrPCB[uCurProc].uIP; arrPCB[i].uSP = arrPCB[uCurProc].uSP; arrPCB[i].uBP = arrPCB[uCurProc].uBP; arrPCB[i].uStatus = PS_Created; PqIn.PqAdd(arrPCB[i]); UINT16 *pn = (UINT16*)arrPCB[uCurProc].Share.DblGetHead(); while (pn) { ShareMem.QmIncCnt(*pn); arrPCB[i].Share.DblAppend((void*)pn, sizeof(UINT16)); pn = (UINT16*)arrPCB[uCurProc].Share.DblGetNext(); } msg = message(ID_Kernel, ANI_FORKS, i); pTx->SendMsg(ID_ANIM, &msg); return i; } } } return NO_PROC;}////////////// Take a "snapshot" of the current contents for the Animator..//void Exec::GetQcom (UINT16 uWhich, PMSG_ANIQ pUarr){ if (uWhich == 0) { PqIn.PqImage(pUarr->arr[0]); PqReady.PqImage(pUarr->arr[1]); PqBlocked.PqImage(pUarr->arr[2]); PqSusReady.PqImage(pUarr->arr[3]); PqSusBlock.PqImage(pUarr->arr[4]); } else { switch ((uWhich >> 8) & 0xff) { case INPUT_Q: PqIn.PqImage(pUarr->arr[0]); break; case READY_Q: PqReady.PqImage(pUarr->arr[0]); break; case BLOKED_Q: PqBlocked.PqImage(pUarr->arr[0]); break; case SUSRDY_Q: PqSusReady.PqImage(pUarr->arr[0]); break; case SUSBLK_Q: PqSusBlock.PqImage(pUarr->arr[0]); break; } switch (uWhich & 0xff) { case INPUT_Q: PqIn.PqImage(pUarr->arr[1]); break; case READY_Q: PqReady.PqImage(pUarr->arr[1]); break; case BLOKED_Q: PqBlocked.PqImage(pUarr->arr[1]); break; case SUSRDY_Q: PqSusReady.PqImage(pUarr->arr[1]); break; case SUSBLK_Q: PqSusBlock.PqImage(pUarr->arr[1]); break; } }}/////////////// Fill in details of current process for animator..//void Exec::GetPcom (PMSG_ANIP pM){ if (uCurProc == NO_PROC) pM->uNr[0] = NO_PROC; else { pM->uNr[0] = arrPCB[uCurProc].uPid; pM->uNr[1] = arrPCB[uCurProc].uPidp; pM->uNr[2] = arrPCB[uCurProc].uBP; pM->uNr[3] = arrPCB[uCurProc].uIP; pM->uNr[4] = arrPCB[uCurProc].uSP; pM->uNr[5] = arrPCB[uCurProc].uTos; pM->uNr[6] = arrPCB[uCurProc].nQuantum; pM->nPri = arrPCB[uCurProc].nPriority; pM->pszName = arrPCB[uCurProc].pszName; DeCode(arrPCB[uCurProc].lCode, pM->szPCD); }}///////////////////////////////////////////////////////////////////////////// Class Member Functions for the Priority Queue//-------------------------------------------------------------------------// Create a priority queue for processes. No limit placed on size, since// no more than MAX_PROC can ever be created - so even if they all arrive// in this queue at the same time (unlikeley), the total size is limited.// Ordered instatntiations will hold entries in descending priority.//Pque::Pque (BOOL bOrd) : DblList(DESCENDING){ bOrdered = bOrd;}Pque::~Pque (void){ PQMBR pD = (PQMBR)DblGetHead(); while (pD) { DblDelete(); pD = (PQMBR)DblGetNext(); }}//////////// Check for any elements in queue// RETURNS: TRUE .. yes there is// FALSE .. no there 'aint//BOOL Pque::PqEmpty (void){ return ((DblGetHead() == NULL) ? TRUE : FALSE);}///////////// Add a PID to this queue. If the queue is ordered, insert at priority// one less than actual, then adjust back to correct. This ensures that// processes at equal priority are served Round-Robin.//void Pque::PqAdd (PCB& proc){ QMBR temp; temp.uPid = proc.uPid; temp.nKey = proc.nPriority - 1; if (!bOrdered) DblAppend((void*)&temp, sizeof(QMBR)); else { PQMBR pLoc = (PQMBR)DblInsert((void*)&temp, sizeof(QMBR)); pLoc->nKey++; }}/////////////////// Remove member from head queue - use with ordered queue to "get" member// with highest "key" (normally priority, but could be quantum, whatever..)// RETURNS: PID # removed, or// NO_PROC if queue empty//UINT16 Pque::PqGet (void){ PQMBR pD = (PQMBR)DblGetHead(); if (pD) { UINT16 uPid = pD->uPid; DblDelete(); return uPid; } return NO_PROC;}/////////////////// Remove member with passed process ID from queue// RETURNS: PID # removed, or// NO_PROC if queue empty//UINT16 Pque::PqGet (UINT16 uTarg){ PQMBR pD = (PQMBR)DblGetHead(); while (pD) if (pD->uPid != uTarg) pD = (PQMBR)DblGetNext(); else { UINT16 uPid = pD->uPid; DblDelete(); return uPid; } return NO_PROC;}//////////////////// See if passed PID is in this list// RETURNS: TRUE .. yes it is// FALSE .. no it ain't//BOOL Pque::PqFind (UINT16 uTarg){ PQMBR pD = (PQMBR)DblGetHead(); while (pD) { if (pD->uPid == uTarg) return TRUE; pD = (PQMBR)DblGetNext(); } return FALSE;}/////////////// The passed pointer references an array [MAX_PROC] of UINT. This routine// copies the queues PID numbers into the array, setting empty elements to// 0xffff (why didn't I just use signed ints in the first place?).//void Pque::PqImage (UINT16 *p){ PQMBR pD = (PQMBR)DblGetHead(); for (INT16 i = 0; i < MAX_PROC; i++) { *(p + i) = ((pD) ? pD->uPid : NO_PROC); if (pD) pD = (PQMBR)DblGetNext(); }}/////////////////////////////////// eof ////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -