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

📄 synobj.cpp

📁 自己动手写操作系统源代码,不可多得的代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

static DWORD WaitForEventObject(__COMMON_OBJECT* lpThis)
{
	__EVENT*                      lpEvent             = NULL;
	__KERNEL_THREAD_OBJECT*       lpKernelThread      = NULL;
	__KERNEL_THREAD_CONTEXT*      lpContext           = NULL;
	DWORD                         dwFlags             = 0L;

	if(NULL == lpThis)
		return OBJECT_WAIT_FAILED;

	lpEvent = (__EVENT*)lpThis;
	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	if(EVENT_STATUS_FREE == lpEvent->dwEventStatus)
	{
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		return OBJECT_WAIT_RESOURCE;
	}
	else
	{
		lpKernelThread = KernelThreadManager.lpCurrentKernelThread;
		lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED;
		lpEvent->lpWaitingQueue->InsertIntoQueue(
			(__COMMON_OBJECT*)lpEvent->lpWaitingQueue,
			(__COMMON_OBJECT*)lpKernelThread,
			0L);
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);    //Leave critical section here is safety.
		//lpContext = &lpKernelThread->KernelThreadContext;
		KernelThreadManager.ScheduleFromProc(NULL);
	}
	return OBJECT_WAIT_RESOURCE;
}

//
//WaitForEventObjectEx's implementation.
//
static DWORD WaitForEventObjectEx(__COMMON_OBJECT* lpObject,DWORD dwMillionSecond)
{
	__EVENT*                      lpEvent         = (__EVENT*)lpObject;
	__KERNEL_THREAD_OBJECT*       lpKernelThread  = NULL;
	DWORD                         dwFlags;
	DWORD                         dwTimeOutTick;
	DWORD                         dwTimeSpan;

	if(NULL == lpObject)
	{
		BUG();
		return OBJECT_WAIT_FAILED;
	}

	dwTimeOutTick = (dwMillionSecond / SYSTEM_TIME_SLICE) ? 
		(dwMillionSecond / SYSTEM_TIME_SLICE) : 1;
	dwTimeOutTick += System.dwClockTickCounter;

	__ENTER_CRITICAL_SECTION(NULL,dwFlags);  //Acquire event object's spinlock.
	if(EVENT_STATUS_FREE == lpEvent->dwEventStatus)
	{
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		return OBJECT_WAIT_RESOURCE;
	}
	//Should waiting now.
	if(0 == dwMillionSecond)  //Waiting zero time.
	{
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		KernelThreadManager.ScheduleFromProc(NULL);
		return OBJECT_WAIT_TIMEOUT;
	}
	lpKernelThread = KernelThreadManager.lpCurrentKernelThread;
	while(EVENT_STATUS_FREE != lpEvent->dwEventStatus)
	{
		if(dwTimeOutTick <= System.dwClockTickCounter)
		{
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			return OBJECT_WAIT_TIMEOUT;
		}
		dwTimeSpan = (dwTimeOutTick - System.dwClockTickCounter) * SYSTEM_TIME_SLICE;
		lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED;
		//Add to event object's waiting queue.
		lpEvent->lpWaitingQueue->InsertIntoQueue(
			(__COMMON_OBJECT*)lpEvent->lpWaitingQueue,
			(__COMMON_OBJECT*)lpKernelThread,
			0L);
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		
		switch(TimeOutWaiting((__COMMON_OBJECT*)lpEvent,lpEvent->lpWaitingQueue,
			lpKernelThread,dwTimeSpan))
		{
			case OBJECT_WAIT_RESOURCE:  //Should loop to while again to check the status.
				__ENTER_CRITICAL_SECTION(NULL,dwFlags);
				break;
			case OBJECT_WAIT_TIMEOUT:
				return OBJECT_WAIT_TIMEOUT;
			case OBJECT_WAIT_DELETED:
				return OBJECT_WAIT_DELETED;
			default:
				BUG();
				return OBJECT_WAIT_FAILED;
		}
	}
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
	return OBJECT_WAIT_RESOURCE;
}

////////////////////////////////////////////////////////////////////////////////////
//
// ------------------ ** 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(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(NULL,dwFlags);
		return 0L;
	}
	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;
	lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK;
	lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_RESOURCE;
	KernelThreadManager.AddReadyKernelThread(
		(__COMMON_OBJECT*)&KernelThreadManager,
		lpKernelThread);  //Put the kernel thread to ready queue.
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

	KernelThreadManager.ScheduleFromProc(NULL);  //Re-schedule kernel thread.
	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;

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

		lpMutex->lpWaitingQueue->InsertIntoQueue(
			(__COMMON_OBJECT*)lpMutex->lpWaitingQueue,
			(__COMMON_OBJECT*)lpKernelThread,
			0L);

		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);  //Leave critical section here is safety.
		//Reschedule all kernel thread(s).
		KernelThreadManager.ScheduleFromProc(NULL);
	}
	return OBJECT_WAIT_RESOURCE;
}

//
//Implementation of WaitForThisObjectEx routine.
//This routine is a time out waiting routine,caller can give a time value
//to indicate how long want to wait,once exceed the time value,waiting operation
//will return,even in case of the resource is not released.
//If the time value is zero,then this routine will check the current status of
//mutex object,if free,then occupy the object and return RESOURCE,else return
//TIMEOUT,and a re-schedule is triggered.
//
static DWORD WaitForMutexObjectEx(__COMMON_OBJECT* lpThis,DWORD dwMillionSecond)
{
	__MUTEX*                      lpMutex        = (__MUTEX*)lpThis;
	__KERNEL_THREAD_OBJECT*       lpKernelThread = NULL;
	DWORD                         dwFlags;

	if(NULL == lpMutex)
	{
		BUG();
		return OBJECT_WAIT_FAILED;
	}
	
	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	if(MUTEX_STATUS_FREE == lpMutex->dwMutexStatus)  //Free now.
	{
		lpMutex->dwMutexStatus = MUTEX_STATUS_OCCUPIED;
		lpMutex->dwWaitingNum ++;
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
		//KernelThreadManager.ScheduleFromProc(NULL);  //Re-schedule here.
		return OBJECT_WAIT_RESOURCE;
	}
	else  //The mutex is not free now.
	{
		if(0 == dwMillionSecond)
		{
			__LEAVE_CRITICAL_SECTION(NULL,dwFlags);
			KernelThreadManager.ScheduleFromProc(NULL); //Re-schedule here.
			return OBJECT_WAIT_TIMEOUT;
		}
		lpKernelThread = KernelThreadManager.lpCurrentKernelThread;
		//Waiting on mutex's waiting queue.
		lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED;
		lpMutex->lpWaitingQueue->InsertIntoQueue(
			(__COMMON_OBJECT*)lpMutex->lpWaitingQueue,
			(__COMMON_OBJECT*)lpKernelThread,
			0L);
		__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

		return TimeOutWaiting((__COMMON_OBJECT*)lpMutex,
			lpMutex->lpWaitingQueue,
			lpKernelThread,
			dwMillionSecond);
	}
}
//
//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;
	lpMutex->WaitForThisObjectEx = WaitForMutexObjectEx;

	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.
//This object support safety deleted,so in this routine,all kernel thread(s)
//must be waken up before this object is destroyed.
//

VOID MutexUninitialize(__COMMON_OBJECT* lpThis)
{
	__PRIORITY_QUEUE*       lpWaitingQueue  = NULL;
	__KERNEL_THREAD_OBJECT* lpKernelThread  = NULL;
	DWORD                   dwFlags;

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

	lpWaitingQueue = ((__MUTEX*)lpThis)->lpWaitingQueue;
	__ENTER_CRITICAL_SECTION(NULL,dwFlags);
	lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpWaitingQueue->GetHeaderElement(
		(__COMMON_OBJECT*)lpWaitingQueue,
		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*)lpWaitingQueue->GetHeaderElement(
			(__COMMON_OBJECT*)lpWaitingQueue,
			NULL);
	}
	__LEAVE_CRITICAL_SECTION(NULL,dwFlags);

	ObjectManager.DestroyObject(&ObjectManager,
		(__COMMON_OBJECT*)lpWaitingQueue);
	return;
}

⌨️ 快捷键说明

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