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

📄 synobj.cpp

📁 小型的操作系统开发的原代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	if(NULL == lpEvent)    //Parameter check.
		return OBJECT_WAIT_FAILED;
	if(0 == dwTimeOut)     //Call this routine with out time out.
		return WaitForEventObject(lpObject);

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	if(EVENT_STATUS_FREE == lpEvent->dwEventStatus)    //Resides signal status.
	{
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		return OBJECT_WAIT_RESOURCE;
	}
	//
	//The event object is not in signal status,so we must wait it.
	//
	lpKernelThread = KernelThreadManager.lpCurrentKernelThread;
	lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED;
	lpParam = (__EVENT_CALLBACK_PARAM*)KMemAlloc(
		sizeof(__EVENT_CALLBACK_PARAM),
		KMEM_SIZE_TYPE_ANY);    //Allocate memory for call back parameter.
	if(NULL == lpParam)    //Can not allocate memory.
	{
		lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		PrintLine("ERROR : Can not allocate memory,in WaitForEventObjectEx routine.");
		return OBJECT_WAIT_FAILED;
	}
	lpParam->dwWakeupReason = OBJECT_WAIT_RESOURCE;
	lpParam->lpEvent        = lpEvent;
	lpParam->lpKernelThread = lpKernelThread;

	lpTimerObject = (__TIMER_OBJECT*)System.SetTimer((__COMMON_OBJECT*)&System,
		lpKernelThread,
#define EVENT_TIMER_ID  0x00000100
		EVENT_TIMER_ID,
		dwTimeOut,
		EventCallback,
		lpParam,
		TIMER_FLAGS_ONCE);
	if(NULL == lpTimerObject)    //Failed to set timer.
	{
		lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_RUNNING;
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		KMemFree((LPVOID)lpParam,KMEM_SIZE_TYPE_ANY,0L);
		PrintLine("ERROR : Can not set timer,in WaitForEventObjectEx routine.");
		return OBJECT_WAIT_FAILED;
	}
	//
	//Now,we should insert the current kernel thread into waiting queue of
	//event object.
	//
	lpEvent->lpWaitingQueue->InsertIntoQueue((__COMMON_OBJECT*)lpEvent->lpWaitingQueue,
		(__COMMON_OBJECT*)lpKernelThread,
		0L);
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
	KernelThreadManager.ScheduleFromProc(&lpKernelThread->KernelThreadContext);

	//
	//The following code will be executed when the current kernel thread be waken up
	//again.
	//
	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	switch(lpParam->dwWakeupReason)
	{
	case OBJECT_WAIT_RESOURCE:    //The kernel thread is waken up for having resource.
		System.CancelTimer((__COMMON_OBJECT*)&System,
			(__COMMON_OBJECT*)lpTimerObject);
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		KMemFree((LPVOID)lpParam,KMEM_SIZE_TYPE_ANY,0L);
		return OBJECT_WAIT_RESOURCE;
	case OBJECT_WAIT_TIMEOUT:
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		KMemFree((LPVOID)lpParam,KMEM_SIZE_TYPE_ANY,0L);
		return OBJECT_WAIT_TIMEOUT;
	default:
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		KMemFree((LPVOID)lpParam,KMEM_SIZE_TYPE_ANY,0L);
		PrintLine("Exeception : In WaitForEventObjectEx routine.");
		return OBJECT_WAIT_FAILED;
	}
	return OBJECT_WAIT_FAILED;    //Should not reach here.
}

//
//One kernel thread can use the following steps to create an event object:
// 1. Create an event object by calling CreateObject;
// 2. Initialize the event object by calling the event object's initialize routine;
// 3. Set the event object's initializing status by calling SetEvent or ResetEvent.
//In order to make this easy,we define a wrap routine,CreatEvent,to wrap these steps
//as one step.
//

__COMMON_OBJECT* CreateEvent(BOOL bInitialState,LPVOID lpReserved)
{
	__COMMON_OBJECT*         lpCommonObject    = NULL;
	__EVENT*                 lpEvent           = NULL;
	DWORD                    dwInitialState    = 0L;

	lpCommonObject = ObjectManager.CreateObject(&ObjectManager,
		NULL,
		OBJECT_TYPE_EVENT);
	if(NULL == lpCommonObject)
		goto __TERMINAL;

	if(!lpCommonObject->Initialize(lpCommonObject))
	{
		ObjectManager.DestroyObject(&ObjectManager,lpCommonObject);
		lpCommonObject = NULL;
		goto __TERMINAL;
	}

	lpEvent = (__EVENT*)lpCommonObject;
	if(bInitialState)
		lpEvent->SetEvent((__COMMON_OBJECT*)lpEvent);

__TERMINAL:
	return lpCommonObject;
}

VOID DestroyEvent(__COMMON_OBJECT* lpThis)
{
	ObjectManager.DestroyObject(&ObjectManager,lpThis);
}


////////////////////////////////////////////////////////////////////////////////////
//
// ------------------ ** The implementation of MUTEX object ** ---------------------
//
///////////////////////////////////////////////////////////////////////////////////

//
//The implementation of ReleaseMutex.
//

static DWORD ReleaseMutex(__COMMON_OBJECT* lpThis)
{
	__KERNEL_THREAD_OBJECT*     lpKernelThread   = NULL;
	__MUTEX*                    lpMutex          = NULL;
	DWORD                       dwPreviousStatus = 0L;
	DWORD                       dwFlags          = 0L;

	if(NULL == lpThis)    //Parameter check.
		return 0L;

	lpMutex = (__MUTEX*)lpThis;
	//ENTER_CRITICAL_SECTION();
	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	if(lpMutex->dwWaitingNum > 0)    //If there are other kernel threads waiting for this object.
		lpMutex->dwWaitingNum --;    //Decrement the counter.
	if(0 == lpMutex->dwWaitingNum)   //There is not kernel thread waiting for the object.
	{
		dwPreviousStatus = lpMutex->dwMutexStatus;
		lpMutex->dwMutexStatus = MUTEX_STATUS_FREE;  //Set to free.
		//LEAVE_CRITICAL_SECTION();
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		return 0L;
	}
	//LEAVE_CRITICAL_SECTION();
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
	lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpMutex->lpWaitingQueue->GetHeaderElement(
		(__COMMON_OBJECT*)lpMutex->lpWaitingQueue,
		0L);  //Get one waiting kernel thread to run.
	lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY;
	KernelThreadManager.lpReadyQueue->InsertIntoQueue(
		(__COMMON_OBJECT*)KernelThreadManager.lpReadyQueue,
		(__COMMON_OBJECT*)lpKernelThread,
		lpKernelThread->dwScheduleCounter);    //Put the kernel thread to ready queue.
	return dwPreviousStatus;
}

//
//The implementation of WaitForMutexObject.
//

static DWORD WaitForMutexObject(__COMMON_OBJECT* lpThis)
{
	__KERNEL_THREAD_OBJECT*        lpKernelThread   = NULL;
	__MUTEX*                       lpMutex          = NULL;
	DWORD                          dwFlags          = 0L;

	if(NULL == lpThis)    //Parameter check.
		return 0L;

	lpMutex = (__MUTEX*)lpThis;

	if(MUTEX_STATUS_FREE == lpMutex->dwMutexStatus)    //If the current mutex is free.
	{
		//ENTER_CRITICAL_SECTION();
		__ENTER_CRITICAL_SECTION(NULL,dwFlags);
		lpMutex->dwMutexStatus = MUTEX_STATUS_OCCUPIED;  //Modify the current status.
		lpMutex->dwWaitingNum  ++;    //Increment the counter.
		//LEAVE_CRITICAL_SECTION();
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		return 1L;                    //The current kernel thread successfully occupy
		                              //the mutex.
	}
	else    //The status of the mutex is occupied.
	{
		lpKernelThread = KernelThreadManager.lpCurrentKernelThread;
		//ENTER_CRITICAL_SECTION();
		__ENTER_CRITICAL_SECTION(NULL,dwFlags);
		lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED;
		lpMutex->dwWaitingNum          ++;    //Increment the waiting number.
		//LEAVE_CRITICAL_SECTION();
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

		lpMutex->lpWaitingQueue->InsertIntoQueue(
			(__COMMON_OBJECT*)lpMutex->lpWaitingQueue,
			(__COMMON_OBJECT*)lpKernelThread,
			0L);
		//Reschedule all kernel thread(s).
		KernelThreadManager.ScheduleFromProc(&lpKernelThread->KernelThreadContext);
	}
	return 0L;
}

//
//The implementation of MutexInitialize.
//

BOOL MutexInitialize(__COMMON_OBJECT* lpThis)
{
	__MUTEX*             lpMutex     = NULL;
	__PRIORITY_QUEUE*    lpQueue     = NULL;
	BOOL                 bResult     = FALSE;

	if(NULL == lpThis) //Parameter check.
		return bResult;

	lpQueue = (__PRIORITY_QUEUE*)ObjectManager.CreateObject(&ObjectManager,
		NULL,
		OBJECT_TYPE_PRIORITY_QUEUE);
	if(NULL == lpQueue)    //Failed to create priority queue.
		return bResult;

	if(!lpQueue->Initialize((__COMMON_OBJECT*)lpQueue))  //Initialize the queue object.
		goto __TERMINAL;

	lpMutex = (__MUTEX*)lpThis;
	lpMutex->dwMutexStatus     = MUTEX_STATUS_FREE;
	lpMutex->lpWaitingQueue    = lpQueue;
	lpMutex->WaitForThisObject = WaitForMutexObject;
	lpMutex->dwWaitingNum      = 0L;
	lpMutex->ReleaseMutex      = ReleaseMutex;

	bResult = TRUE;    //Successful to initialize the mutex object.

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

//
//The implementation of MutexUninitialize.
//

VOID MutexUninitialize(__COMMON_OBJECT* lpThis)
{
	__MUTEX*           lpMutex         = NULL;
	__PRIORITY_QUEUE*  lpWaitingQueue  = NULL;

	if(NULL == lpThis) //parameter check.
		return;

	lpWaitingQueue = ((__MUTEX*)lpThis)->lpWaitingQueue;
	if(NULL != lpWaitingQueue)
	{
		ObjectManager.DestroyObject(&ObjectManager,
			(__COMMON_OBJECT*)lpWaitingQueue);
	}
	return;
}

//
//The implementation of CreateMutex.
//

__COMMON_OBJECT* CreateMutex(LPVOID lpReserved)
{
	return NULL;
}

//
//The implementation of DestroyMutex.
//

VOID DestroyMutex(__COMMON_OBJECT* lpThis)
{
	return;
}

⌨️ 快捷键说明

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