void svc(SYSTEM_CALL_DATA *SystemCallData) { short call_type; static short do_print = 10; short i; //for hardware interface MEMORY_MAPPED_IO mmio; //for GET_TIME_OF_DAY INT32 Temp_Clock; //for SLEEP long Sleep_Time; struct Process_Control_Block *sleepPCB; //for RESTART_PROCESS long PID_restart; struct Process_Control_Block *restartPCB; struct Process_Control_Block *recreatedPCB; //for CREATE_PROCESS struct Process_Control_Block *newPCB; //for TERMINATE_PROCESS long termPID; struct Process_Control_Block *termPCB; //for GET_PROCESS_ID int ReturnedPID; char* ProcessName; struct Process_Control_Block *PCBbyProcessName; //for SUSPEND_PROCESS int suspendPID; struct Process_Control_Block *suspendPCB; //for RESUME_PROCESS int resumePID; struct Process_Control_Block *resumePCB; //for CHANGE_PRIORITY int changePrioPID; struct Process_Control_Block *changePrioPCB; int newPriority; //for SEND_MESSAGE long TargetPID; char *MessageBuffer; long SendLength; struct Message *MessageCreated; long *ErrorReturned_SendMessage; //for RECEIVE_MESSAGE long SourcePID; char *ReceiveBuffer; long ReceiveLength; long *ActualSendLength; long *ActualSourcePID; long *ErrorReturned_ReceiveMessage; struct Process_Control_Block *Mess_PCB; call_type = (short) SystemCallData->SystemCallNumber; if (do_print > 0) { printf("SVC handler: %s\n", call_names[call_type]); for (i = 0; i < SystemCallData->NumberOfArguments - 1; i++) { //Value = (long)*SystemCallData->Argument[i]; printf("Arg %d: Contents = (Decimal) %8ld, (Hex) %8lX\n", i, (unsigned long) SystemCallData->Argument[i], (unsigned long) SystemCallData->Argument[i]); } do_print--; } switch (call_type) { //get and return current system time case SYSNUM_GET_TIME_OF_DAY: mmio.Mode = Z502ReturnValue; mmio.Field1 = mmio.Field2 = mmio.Field3 = 0; MEM_READ(Z502Clock, &mmio); Temp_Clock = mmio.Field1; *SystemCallData->Argument[0] = Temp_Clock; break; //create a new PCB and put it into pcb table and ready queue case SYSNUM_CREATE_PROCESS: //create a new PCB newPCB = OSCreateProcess(SystemCallData->Argument[0], SystemCallData->Argument[1], SystemCallData->Argument[2], SystemCallData->Argument[3], SystemCallData->Argument[4]); //if create successfully, put it into PCB table and ready queue if (newPCB != NULL) { SchedularPrinter("Create", newPCB->ProcessID);//print states enPCBTable(newPCB); enReadyQueue(newPCB); } break; //return PID regarding process name case SYSNUM_GET_PROCESS_ID: ProcessName = (char*)SystemCallData->Argument[0]; //if no input process name, return the current running PID if (strcmp(ProcessName, "") == 0) { PCBbyProcessName = CurrentPCB(); *SystemCallData->Argument[1] = PCBbyProcessName->ProcessID; *SystemCallData->Argument[2] = ERR_SUCCESS; } //find the PCB in PCB table and return PID if found else { PCBbyProcessName = findPCBbyProcessName(ProcessName); //if found, return PID if (PCBbyProcessName != NULL) { ReturnedPID = PCBbyProcessName->ProcessID; *SystemCallData->Argument[1] = ReturnedPID; *SystemCallData->Argument[2] = ERR_SUCCESS; } //if not found, return error else { *SystemCallData->Argument[2] = ERR_BAD_PARAM; } } break; //if a PCB wanna sleep, put itself into timer queue and start //a new PCB case SYSNUM_SLEEP: //print states SchedularPrinter("Sleep", CurrentPID()); //Calculate WakeUpTime for PCB Sleep_Time = (long)SystemCallData->Argument[0]; sleepPCB = CurrentPCB(); sleepPCB->WakeUpTime = CurrentTime() + Sleep_Time; //Put current running PCB into timer queue and reset time lockTimer(); enTimerQueue(sleepPCB); if (sleepPCB == timerQueue->First_Element->PCB){ SetTimer(Sleep_Time); } unlockTimer(); //in uniprocessor, start a new PCB //in multiprocessor, only suspend itself if (ProcessorMode == Uniprocessor) { //first PCB in Ready Queue starts Dispatcher(); } else { OSSuspendCurrentProcess(); } break; //restart a PCB by terminate itself and created a new PCB with everything the same except PID case SYSNUM_RESTART_PROCESS: //initial return error *SystemCallData->Argument[2] = ERR_BAD_PARAM; PID_restart = (long)SystemCallData->Argument[0]; //if not restart itself if (PID_restart != CurrentPID()){ //find restarted PCB restartPCB = findPCBbyProcessID(PID_restart); //if PCB found, terminate itself and create a new one if (restartPCB != NULL){ TerminateProcess(restartPCB); recreatedPCB = OSCreateProcess(restartPCB->ProcessName, restartPCB->TestToRun, restartPCB->Priority, SystemCallData->Argument[1], SystemCallData->Argument[2]); //if create successfully, put it into PCB table and ready queue if (recreatedPCB != NULL) { *SystemCallData->Argument[2] = ERR_SUCCESS; SchedularPrinter("Create", recreatedPCB->ProcessID);//print states enPCBTable(recreatedPCB); enReadyQueue(recreatedPCB); SchedularPrinter("Restart", restartPCB->ProcessID); } } else{ *SystemCallData->Argument[2] = ERR_BAD_PARAM; } } else{ *SystemCallData->Argument[2] = ERR_BAD_PARAM; } break; //terminate a process case SYSNUM_TERMINATE_PROCESS: termPID = (long)SystemCallData->Argument[0]; //if PID = -1, terminate current running PCB if (termPID == -1) { if (PCBLiveNumber() > 1) { *SystemCallData->Argument[1] = ERR_SUCCESS; //print states SchedularPrinter("Terminate", termPID); //terminate current PCB TerminateProcess(CurrentPCB()); } else { *SystemCallData->Argument[1] = ERR_SUCCESS; HaltProcess(); } } //if PID = -2, terminate OS if (termPID == -2) { *SystemCallData->Argument[1] = ERR_SUCCESS; HaltProcess(); } //if PID positive, terminate specified PID else { termPCB = findPCBbyProcessID((long)SystemCallData->Argument[0]); //if PCB found, terminate it if (termPCB != NULL) { *SystemCallData->Argument[1] = ERR_SUCCESS; //if more than one PCB alive, simply terminate it if (PCBLiveNumber() > 1) { //print states SchedularPrinter("Terminate", termPID); //terminate specified PCB TerminateProcess(termPCB); } //if last alive PCB, terminate OS else { HaltProcess(); } } else { *SystemCallData->Argument[1] = ERR_BAD_PARAM; } } break; //suspend a PCB, which can be resumed case SYSNUM_SUSPEND_PROCESS: suspendPID = (int)SystemCallData->Argument[0]; //if PID = -1, suspend current running PCB if (suspendPID == -1) { //if more than one PCB alive, suspend it if (PCBLiveNumber() > 1) { *SystemCallData->Argument[1] = ERR_SUCCESS; //print states SchedularPrinter("Suspend", suspendPID); //Suspend Current Process SuspendProcess(CurrentPCB()); } //if last one PCB alive, return error else { *SystemCallData->Argument[1] = ERR_BAD_PARAM; } } //if PID positive, suspend specified PCB else { suspendPCB = findPCBbyProcessID((int)suspendPID); //if PCB found if (suspendPCB != NULL) { //if more than one PCB alive, suspend it if (suspendPCB->ProcessState == PCB_STATE_LIVE && PCBLiveNumber() > 1) { *SystemCallData->Argument[1] = ERR_SUCCESS; //print states SchedularPrinter("Suspend", suspendPID); //Suspend specified process SuspendProcess(suspendPCB); } //if last one PCB alive, return error else { *SystemCallData->Argument[1] = ERR_BAD_PARAM; } } else { *SystemCallData->Argument[1] = ERR_BAD_PARAM; } } break; //resumes a previously suspended PCB case SYSNUM_RESUME_PROCESS: resumePID = (int)SystemCallData->Argument[0]; resumePCB = findPCBbyProcessID(resumePID); //if PCB found if (resumePCB != NULL) { //if PCB is previously suspended if (resumePCB->ProcessState == PCB_STATE_SUSPEND) { *SystemCallData->Argument[1] = ERR_SUCCESS; //print states SchedularPrinter("Resume", resumePID); //Resume specified process ResumeProcess(resumePCB); } else { *SystemCallData->Argument[1] = ERR_BAD_PARAM; } } else { *SystemCallData->Argument[1] = ERR_BAD_PARAM; } break; //change the priority of a PCB case SYSNUM_CHANGE_PRIORITY: changePrioPID = (int)SystemCallData->Argument[0]; changePrioPCB = findPCBbyProcessID((int)changePrioPID); newPriority = (int)SystemCallData->Argument[1]; //if legal priority if (newPriority<=40 && newPriority>=0) { if (changePrioPCB != NULL) { *SystemCallData->Argument[2] = ERR_SUCCESS; //print states printf("Before changing Priority\n"); SchedularPrinter("ChangePrio", changePrioPID); //if PCB in ready queue, change order in ready queue if (changePrioPCB->ProcessLocation == PCB_LOCATION_READY_QUEUE && newPriority != changePrioPCB->Priority) { changePrioPCB = deCertainPCBFromReadyQueue(changePrioPID); changePrioPCB->Priority = newPriority; enReadyQueue(changePrioPCB); } else { changePrioPCB->Priority = newPriority; } //print states printf("After changing Priority\n"); SchedularPrinter("ChangePrio", changePrioPID); } else { *SystemCallData->Argument[2] = ERR_BAD_PARAM; } } else { *SystemCallData->Argument[2] = ERR_BAD_PARAM; } break; //PCB stores a message in message table case SYSNUM_SEND_MESSAGE: TargetPID = (long)SystemCallData->Argument[0]; MessageBuffer = (char*)SystemCallData->Argument[1]; SendLength = (long)SystemCallData->Argument[2]; ErrorReturned_SendMessage = SystemCallData->Argument[3]; //create a message MessageCreated = CreateMessage(TargetPID, MessageBuffer, SendLength, ErrorReturned_SendMessage); //if successfully create a message, put it into message table if (MessageCreated != NULL) { SchedularPrinter("SendMsg", TargetPID); enMessageTable(MessageCreated); } break; //retrive a message in message table case SYSNUM_RECEIVE_MESSAGE: SourcePID = (long)SystemCallData->Argument[0]; ReceiveBuffer = (char*)SystemCallData->Argument[1]; ReceiveLength = (long)SystemCallData->Argument[2]; ActualSendLength = SystemCallData->Argument[3]; ActualSourcePID = SystemCallData->Argument[4]; ErrorReturned_ReceiveMessage = SystemCallData->Argument[5]; Mess_PCB = CurrentPCB(); Mess_PCB->ProcessState = PCB_STATE_MSG_SUSPEND; pcbTable->Msg_Suspended_Number += 1; //PCB kept suspended by sleep until find a message while (findMessage(SourcePID, ReceiveBuffer, ReceiveLength, ActualSendLength, ActualSourcePID, ErrorReturned_ReceiveMessage) == 0) { Mess_PCB->WakeUpTime = CurrentTime() + 10; //Put current running PCB into timer queue and reset time enTimerQueue(Mess_PCB); if (Mess_PCB == timerQueue->First_Element->PCB) { SetTimer(10); } //first PCB in Ready Queue starts Dispatcher(); } Mess_PCB->ProcessState = PCB_STATE_LIVE; pcbTable->Msg_Suspended_Number -= 1; SchedularPrinter("ReceiveMsg", CurrentPID()); break; default: printf("ERROR! call_type not recognized!\n"); printf("Call_type is - %i\n", call_type); } } // End of svc
BOOL HandleBPM(DWORD dwThID) { HANDLE hTh; CONTEXT Con = {CON_DRX}; BOOL bHandle = FALSE; DWORD dwEip; char cStatusBuff[50]; hTh = GetThreadHandle(dwThID); if (!hTh) return FALSE; if (!GetThreadContext(hTh, &Con)) return FALSE; // is EIP == a BPM address ? dwEip = Con.Eip; // BPM0 ? if ((Con.Dr6 & BPM0_DETECTED) == BPM0_DETECTED && (dwEip >= Con.Eip && dwEip <= Con.Eip + MAX_RW_OPCODE) && (Con.Dr7 & BPM0_LOCAL_ENABLED) == BPM0_LOCAL_ENABLED) { wsprintf(cStatusBuff, "BPM - %08lXh ", Con.Dr0); // build info string if ((Con.Dr7 & BPM0_RW) == BPM0_RW) lstrcat(cStatusBuff, "RW"); else if ((Con.Dr7 & BPM0_W) == BPM0_W) lstrcat(cStatusBuff, "W"); else // x ! lstrcat(cStatusBuff, "X"); lstrcat(cStatusBuff, " (Dr0)"); lstrcat(cStatusBuff, " reached..."); bHandle = TRUE; } // BPM1 ? if ((Con.Dr6 & BPM1_DETECTED) == BPM1_DETECTED && (dwEip >= Con.Eip && dwEip <= Con.Eip + MAX_RW_OPCODE) && (Con.Dr7 & BPM1_LOCAL_ENABLED) == BPM1_LOCAL_ENABLED) { wsprintf(cStatusBuff, "BPM - %08lXh ", Con.Dr1); // build info string if ((Con.Dr7 & BPM1_RW) == BPM1_RW) lstrcat(cStatusBuff, "RW"); else if ((Con.Dr7 & BPM1_W) == BPM1_W) lstrcat(cStatusBuff, "W"); else // x ! lstrcat(cStatusBuff, "X"); lstrcat(cStatusBuff, " (Dr1)"); lstrcat(cStatusBuff, " reached..."); bHandle = TRUE; } // BPM2 ? if ((Con.Dr6 & BPM2_DETECTED) == BPM2_DETECTED && (dwEip >= Con.Eip && dwEip <= Con.Eip + MAX_RW_OPCODE) && (Con.Dr7 & BPM2_LOCAL_ENABLED) == BPM2_LOCAL_ENABLED) { wsprintf(cStatusBuff, "BPM - %08lXh ", Con.Dr2); // build info string if ((Con.Dr7 & BPM2_RW) == BPM2_RW) lstrcat(cStatusBuff, "RW"); else if ((Con.Dr7 & BPM2_W) == BPM2_W) lstrcat(cStatusBuff, "W"); else // x ! lstrcat(cStatusBuff, "X"); lstrcat(cStatusBuff, " (Dr2)"); lstrcat(cStatusBuff, " reached..."); bHandle = TRUE; } // BPM3 ? if ((Con.Dr6 & BPM3_DETECTED) == BPM3_DETECTED && (dwEip >= Con.Eip && dwEip <= Con.Eip + MAX_RW_OPCODE) && (Con.Dr7 & BPM3_LOCAL_ENABLED) == BPM3_LOCAL_ENABLED) { wsprintf(cStatusBuff, "BPM - %08lXh ", Con.Dr3); // build info string if ((Con.Dr7 & BPM3_RW) == BPM3_RW) lstrcat(cStatusBuff, "RW"); else if ((Con.Dr7 & BPM3_W) == BPM3_W) lstrcat(cStatusBuff, "W"); else // x ! lstrcat(cStatusBuff, "X"); lstrcat(cStatusBuff, " (Dr3)"); lstrcat(cStatusBuff, " reached..."); bHandle = TRUE; } if (bHandle) { SuspendProcess(); UpdateStatus(cStatusBuff); if (Option.bDlgOnBPM) CreateBPMDlg(hInst, hDlg_); // open BPM Menu WaitForUser(); } return bHandle; }