Exemple #1
0
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
Exemple #2
0
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;
}