⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 synobj.cpp

📁 自己动手写操作系统源代码,不可多得的代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//***********************************************************************/
//    Author                    : Garry
//    Original Date             : Sep 21, 2005
//    Module Name               : SYNOBJ.CPP
//    Module Funciton           : 
//                                This module countains synchronization object's implementation
//                                code.
//                                The following synchronization object(s) is(are) defined
//                                in this file:
//                                  1. EVENT
//                                  2. MUTEX
//                                  3. SEMAPHORE
//                                  4. TIMER
//
//                                ************
//                                This file is the most important file of Hello China.
//                                ************
//    Last modified Author      :
//    Last modified Date        :
//    Last modified Content     :
//                                1.
//                                2.
//    Lines number              :
//***********************************************************************/

#ifndef __STDAFX_H__
#include "..\INCLUDE\StdAfx.h"
#endif

//Timer handler's parameter.
typedef struct{
	__COMMON_OBJECT*        lpSynObject;  //Synchronous object.
	__PRIORITY_QUEUE*       lpWaitingQueue; //Waiting queue of the synchronous object.
	__KERNEL_THREAD_OBJECT* lpKernelThread; //Kernel thread who want to wait.
}__TIMER_HANDLER_PARAM;

//Timer handler routine for all synchronous object.
static DWORD WaitingTimerHandler(LPVOID lpData)
{
	__TIMER_HANDLER_PARAM*   lpHandlerParam = (__TIMER_HANDLER_PARAM*)lpData;
	DWORD                    dwFlags;

	if(NULL == lpHandlerParam)
	{
		BUG();
		return 0L;
	}

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);  //Acquire kernel thread object's spinlock.
	switch(lpHandlerParam->lpKernelThread->dwWaitingStatus & OBJECT_WAIT_MASK)
	{
		case OBJECT_WAIT_RESOURCE:
		case OBJECT_WAIT_DELETED:
			break;
		case OBJECT_WAIT_WAITING:
			lpHandlerParam->lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
			lpHandlerParam->lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_TIMEOUT;
			//Delete the lpKernelThread from waiting queue.
			lpHandlerParam->lpWaitingQueue->DeleteFromQueue(
				(__COMMON_OBJECT*)lpHandlerParam->lpWaitingQueue,
				(__COMMON_OBJECT*)lpHandlerParam->lpKernelThread);
			//Add this kernel thread to ready queue.
			lpHandlerParam->lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
			KernelThreadManager.AddReadyKernelThread((__COMMON_OBJECT*)&KernelThreadManager,
				lpHandlerParam->lpKernelThread);
			break;
		default:
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			BUG();
			return 0L;
	}
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
	return 0L;
}

//
//TimeOutWaiting is a global routine used by any synchronous objects' WaitForThisObjectEx
//routine.
//
DWORD TimeOutWaiting(__COMMON_OBJECT* lpSynObject,      //Synchronous object.
					 __PRIORITY_QUEUE* lpWaitingQueue,  //Waiting queue.
					 __KERNEL_THREAD_OBJECT* lpKernelThread,  //Who want to wait.
					 DWORD dwMillionSecond)  //Time out value in millionsecond.
{
	__TIMER_OBJECT*           lpTimerObj;
	__TIMER_HANDLER_PARAM     HandlerParam;

	if((NULL == lpSynObject) || (NULL == lpWaitingQueue) ||
	   (NULL == lpKernelThread) || (0 == dwMillionSecond))  //Invalid parameters.
	{
		BUG();
		return OBJECT_WAIT_FAILED;
	}

	//Initialize HandlerParam.
	HandlerParam.lpKernelThread  = lpKernelThread;
	HandlerParam.lpSynObject     = lpSynObject;
	HandlerParam.lpWaitingQueue  = lpWaitingQueue;

	lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
	lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_WAITING;

	//Set a one time timer.
	lpTimerObj = (__TIMER_OBJECT*)System.SetTimer((__COMMON_OBJECT*)&System,
		lpKernelThread,
#define TIMEOUT_WAITING_TIMER_ID 2048
		TIMEOUT_WAITING_TIMER_ID,
		dwMillionSecond,
		WaitingTimerHandler,
		(LPVOID)&HandlerParam,
		TIMER_FLAGS_ONCE);
	if(NULL == lpTimerObj)
	{
		return OBJECT_WAIT_FAILED;
	}

	KernelThreadManager.ScheduleFromProc(NULL);  //Re-schedule.

	//Once reach here,it means the waiting kernel thread was waken up.
	switch(lpKernelThread->dwWaitingStatus & OBJECT_WAIT_MASK)
	{
		case OBJECT_WAIT_RESOURCE:  //Got resource.
			System.CancelTimer((__COMMON_OBJECT*)&System,
				(__COMMON_OBJECT*)lpTimerObj);  //Cancel timer.
			return OBJECT_WAIT_RESOURCE;

		case OBJECT_WAIT_DELETED:   //Synchronous object was deleted.
			System.CancelTimer((__COMMON_OBJECT*)&System,
				(__COMMON_OBJECT*)lpTimerObj);
			return OBJECT_WAIT_DELETED;

		case OBJECT_WAIT_TIMEOUT:   //Time out.
			return OBJECT_WAIT_TIMEOUT;
		default:
			break;
	}
	//Once reach here,it means error encountered.
	BUG();
	return OBJECT_WAIT_FAILED;
}

//
//Routines pre-declaration.
//
static DWORD WaitForEventObject(__COMMON_OBJECT*);
static DWORD SetEvent(__COMMON_OBJECT*);
static DWORD ResetEvent(__COMMON_OBJECT*);
static DWORD WaitForEventObjectEx(__COMMON_OBJECT*,DWORD);

//---------------------------------------------------------------------------------
//
//                SYNCHRONIZATION OBJECTS
//
//----------------------------------------------------------------------------------

//
//Event object's initializing routine.
//This routine initializes the members of an event object.
//

BOOL EventInitialize(__COMMON_OBJECT* lpThis)
{
	BOOL                  bResult          = FALSE;
	__EVENT*              lpEvent          = NULL;
	__PRIORITY_QUEUE*     lpPriorityQueue  = NULL;

	if(NULL == lpThis)
		goto __TERMINAL;

	lpEvent = (__EVENT*)lpThis;

	lpPriorityQueue = (__PRIORITY_QUEUE*)
		ObjectManager.CreateObject(&ObjectManager,NULL,
		OBJECT_TYPE_PRIORITY_QUEUE);
	if(NULL == lpPriorityQueue)
		goto __TERMINAL;

	bResult = lpPriorityQueue->Initialize((__COMMON_OBJECT*)lpPriorityQueue);
	if(!bResult)
		goto __TERMINAL;

	lpEvent->lpWaitingQueue      = lpPriorityQueue;
	lpEvent->dwEventStatus       = EVENT_STATUS_OCCUPIED;
	lpEvent->SetEvent            = SetEvent;
	lpEvent->ResetEvent          = ResetEvent;
	lpEvent->WaitForThisObjectEx = WaitForEventObjectEx;
	lpEvent->WaitForThisObject   = WaitForEventObject;
	bResult                      = TRUE;

__TERMINAL:
	if(!bResult)
	{
		if(NULL != lpPriorityQueue)    //Release the priority queue.
			ObjectManager.DestroyObject(&ObjectManager,
			(__COMMON_OBJECT*)lpPriorityQueue);
	}
	return bResult;
}

//
//Event object's uninitializing routine.
//Safety deleted is support by EVENT object,so in this routine,
//if there are kernel threads waiting for this object,then wakeup
//all kernel threads,and then destroy the event object.
//

VOID EventUninitialize(__COMMON_OBJECT* lpThis)
{
	__EVENT*                 lpEvent          = NULL;
	__PRIORITY_QUEUE*        lpPriorityQueue  = NULL;
	__KERNEL_THREAD_OBJECT*  lpKernelThread   = NULL;
	DWORD                    dwFlags;

	if(NULL == lpThis)
	{
		BUG();
		return;
	}

	lpEvent = (__EVENT*)lpThis;

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	lpPriorityQueue = lpEvent->lpWaitingQueue;
	if(EVENT_STATUS_FREE != EVENT_STATUS_FREE)
	{
		//Should wake up all kernel thread(s) who waiting for this object.
		lpKernelThread = (__KERNEL_THREAD_OBJECT*)
			lpPriorityQueue->GetHeaderElement(
			(__COMMON_OBJECT*)lpPriorityQueue,
			NULL);
		while(lpKernelThread)
		{
			lpKernelThread->dwThreadStatus   = KERNEL_THREAD_STATUS_READY;
			lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
			lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_DELETED;
			KernelThreadManager.AddReadyKernelThread((__COMMON_OBJECT*)&KernelThreadManager,
				lpKernelThread);
			lpKernelThread = (__KERNEL_THREAD_OBJECT*)
				lpPriorityQueue->GetHeaderElement(
				(__COMMON_OBJECT*)lpPriorityQueue,
				NULL);
		}
	}
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

	ObjectManager.DestroyObject(&ObjectManager,
		(__COMMON_OBJECT*)lpPriorityQueue);          //*******CAUTION!!!************
		//lpPriorityQueue->Uninitialize((__COMMON_OBJECT*)lpPriorityQueue);
	return;
}

//
//The implementation of SetEvent.
//This routine do the following:
// 1. Saves the previous status into a local variable;
// 2. Sets the current status of the event to EVENT_STATUS_FREE;
// 3. Wakes up all kernel thread(s) in it's waiting queue.
// 4. Returns the previous status.
//

static DWORD SetEvent(__COMMON_OBJECT* lpThis)
{
	DWORD                     dwPreviousStatus     = EVENT_STATUS_OCCUPIED;
	__EVENT*                  lpEvent              = NULL;
	__KERNEL_THREAD_OBJECT*   lpKernelThread       = NULL;
	DWORD                     dwFlags              = 0L;

	if(NULL == lpThis)
		return dwPreviousStatus;

	lpEvent = (__EVENT*)lpThis;

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	dwPreviousStatus = lpEvent->dwEventStatus;
	lpEvent->dwEventStatus = EVENT_STATUS_FREE;    //Set the current status to free.

	//Wake up all kernel thread(s) waiting for this event.
	lpKernelThread = (__KERNEL_THREAD_OBJECT*)
		lpEvent->lpWaitingQueue->GetHeaderElement(
		(__COMMON_OBJECT*)lpEvent->lpWaitingQueue,
		NULL);
	while(lpKernelThread)                         //Remove all kernel thread(s) from
		                                          //waiting queue.
	{
		lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
		//Set waiting result bit.
		lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
		lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_RESOURCE;
		KernelThreadManager.AddReadyKernelThread(
			(__COMMON_OBJECT*)&KernelThreadManager,
			lpKernelThread);  //Add to ready queue.
		lpKernelThread = (__KERNEL_THREAD_OBJECT*)
			lpEvent->lpWaitingQueue->GetHeaderElement(
			(__COMMON_OBJECT*)lpEvent->lpWaitingQueue,
			NULL);
	}
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

	if(IN_KERNELTHREAD())  //Current context is in process.
	{
		KernelThreadManager.ScheduleFromProc(NULL);  //Re-schedule.
	}
	return dwPreviousStatus;
}

//
//The implementation of ResetEvent.
//

static DWORD ResetEvent(__COMMON_OBJECT* lpThis)
{
	__EVENT*          lpEvent          = NULL;
	DWORD             dwPreviousStatus = 0L;
	DWORD             dwFlags          = 0L;

	if(NULL == lpThis)
		return dwPreviousStatus;

	lpEvent = (__EVENT*)lpThis;

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	dwPreviousStatus = lpEvent->dwEventStatus;
	lpEvent->dwEventStatus = EVENT_STATUS_OCCUPIED;
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

	return dwPreviousStatus;
}

//
//The implementation of WaitForEventObject.
//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -