//DeviceRead for WINHD driver. static DWORD DeviceRead(__COMMON_OBJECT* lpDrv, __COMMON_OBJECT* lpDev, __DRCB* lpDrcb) { __PARTITION_EXTENSION* pPe = NULL; __DEVICE_OBJECT* pDevice = (__DEVICE_OBJECT*)lpDev; DWORD dwResult = 0; DWORD dwStart = 0; DWORD dwFlags; if((NULL == lpDev) || (NULL == lpDrcb)) //Invalid parameters. { goto __TERMINAL; } pPe = (__PARTITION_EXTENSION*)pDevice->lpDevExtension; if(NULL == pPe) //Should not occur,or else the OS kernel may have fatal error. { goto __TERMINAL; } //Check the validity of DRCB object transferred. if(DRCB_REQUEST_MODE_READ != lpDrcb->dwRequestMode) //Invalid operation action. { goto __TERMINAL; } if((NULL == lpDrcb->lpOutputBuffer) || (0 == lpDrcb->dwOutputLen)) { goto __TERMINAL; } if(0 != lpDrcb->dwOutputLen % pDevice->dwBlockSize) //Only block size request is //legally. { goto __TERMINAL; } __ENTER_CRITICAL_SECTION(NULL,dwFlags); //Check if current position is in device end. if(pPe->dwCurrPos == pPe->dwSectorNum) { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); goto __TERMINAL; } dwResult = lpDrcb->dwOutputLen / pDevice->dwBlockSize; //Check if exceed the device boundry after read. if(pPe->dwCurrPos + dwResult >= pPe->dwSectorNum) //Exceed end boundry. { dwResult = pPe->dwSectorNum - pPe->dwCurrPos; //Only partial data of the //requested can be read. } dwStart = pPe->dwCurrPos + pPe->dwStartSector; //Read start this position,in sector number. pPe->dwCurrPos += dwResult; //Adjust current pointer. __LEAVE_CRITICAL_SECTION(NULL,dwFlags); //Now issue read command to read data from device. if(!ReadSector(0,dwStart,dwResult,(BYTE*)lpDrcb->lpOutputBuffer)) //Can not read data. { dwResult = 0; goto __TERMINAL; } dwResult *= pDevice->dwBlockSize; //dwResult now is the byte number just read. __TERMINAL: return dwResult; }
//static DWORD kWaitForEventObject(__COMMON_OBJECT* lpThis) { __EVENT* lpEvent = (__EVENT*)lpThis; __KERNEL_THREAD_OBJECT* lpKernelThread = NULL; //__KERNEL_THREAD_CONTEXT* lpContext = NULL; DWORD dwFlags = 0; if(NULL == lpEvent) { return OBJECT_WAIT_FAILED; } __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->dwWaitingStatus &= ~OBJECT_WAIT_MASK; lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_WAITING; lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED; lpEvent->lpWaitingQueue->InsertIntoQueue( (__COMMON_OBJECT*)lpEvent->lpWaitingQueue, (__COMMON_OBJECT*)lpKernelThread, 0); __LEAVE_CRITICAL_SECTION(NULL,dwFlags); //Leave critical section here is safety. KernelThreadManager.ScheduleFromProc(NULL); } return OBJECT_WAIT_RESOURCE; }
static DWORD WaitForEventObject(struct __COMMON_OBJECT* lpThis) { struct __EVENT* lpEvent = NULL; struct __KERNEL_THREAD_OBJECT* lpKernelThread = NULL; __KERNEL_THREAD_CONTEXT* lpContext = NULL; DWORD dwFlags = 0L; if(NULL == lpThis) return OBJECT_WAIT_FAILED; lpEvent = (struct __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( (struct __COMMON_OBJECT*)lpEvent->lpWaitingQueue, (struct __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; }
//The implementation of RegisterFileSystem. static BOOL AddFileSystem(__COMMON_OBJECT* lpThis, __COMMON_OBJECT* lpDevObj, DWORD dwAttribute, CHAR* pVolumeLbl) { BOOL bResult = FALSE; __IO_MANAGER* pMgr = (__IO_MANAGER*)lpThis; __DEVICE_OBJECT* pFileSystem = (__DEVICE_OBJECT*)lpDevObj; BYTE FsIdentifier = 'C'; //First file system identifier. DWORD dwFlags; int i,j,k; if((NULL == pMgr) || (NULL == pFileSystem)) //Invalid parameters. { goto __TERMINAL; } //Seek the empty slot of file system array,if there is. __ENTER_CRITICAL_SECTION(NULL,dwFlags); for(i = 0;i < FILE_SYSTEM_NUM;i ++) { if(0 == pMgr->FsArray[i].FileSystemIdentifier) //Empty slot. { break; } } if(FILE_SYSTEM_NUM == i) //No slot is free. { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); goto __TERMINAL; } //Calculate the file system identifier,if the maximal file system identifier //in current array is x,then use x + 1 as new file system's identifier. for(j = 0;j < FILE_SYSTEM_NUM;j ++) { if(pMgr->FsArray[j].FileSystemIdentifier >= FsIdentifier) { FsIdentifier += 1; //Use next one. } } pMgr->FsArray[i].FileSystemIdentifier = FsIdentifier; pMgr->FsArray[i].pFileSystemObject = (__COMMON_OBJECT*)pFileSystem; pMgr->FsArray[i].dwAttribute = dwAttribute; //Set volume lable. k = 0; for(j = 0;j < VOLUME_LBL_LEN - 1;j ++) { if(' ' == pVolumeLbl[j]) //Skip space. { continue; } pMgr->FsArray[i].VolumeLbl[k] = pVolumeLbl[j]; k += 1; } pMgr->FsArray[i].VolumeLbl[k] = 0; //Set terminator. __LEAVE_CRITICAL_SECTION(NULL,dwFlags); bResult = TRUE; __TERMINAL: return bResult; }
//RegisterFileSystem,this routine add one file system controller into system. static BOOL RegisterFileSystem(__COMMON_OBJECT* lpThis, __COMMON_OBJECT* pFileSystem) { __IO_MANAGER* pManager = (__IO_MANAGER*)lpThis; DWORD dwFlags; int i = 0; if((NULL == pFileSystem) || (NULL == lpThis)) //Invalid parameters. { return FALSE; } __ENTER_CRITICAL_SECTION(NULL,dwFlags); for(i = 0;i < FS_CTRL_NUM;i ++) { if(NULL == pManager->FsCtrlArray[i]) //Find a empty slot. { break; } } if(FS_CTRL_NUM == i) //Can not find a empty slot. { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return FALSE; } //Insert the file system object into this slot. pManager->FsCtrlArray[i] = pFileSystem; __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return TRUE; }
static VOID kVirtualFree(__COMMON_OBJECT* lpThis,LPVOID lpVirtualAddr) { __VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis; __VIRTUAL_AREA_DESCRIPTOR* lpVad = NULL; __PAGE_INDEX_MANAGER* lpIndexMgr = NULL; BOOL bResult = FALSE; DWORD dwFlags = 0; if((NULL == lpThis) || (NULL == lpVirtualAddr)) //Invalidate parameters. return; __ENTER_CRITICAL_SECTION(NULL,dwFlags); if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM) //Should search in the list. lpVad = GetVaByAddr_l(lpThis,lpVirtualAddr); //Get the virtual area descriptor. else lpVad = GetVaByAddr_t(lpThis,lpVirtualAddr); if(NULL == lpVad) //This virtual address is not allocated yet. { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); goto __TERMINAL; } // //Now,we have got the virtual area descriptor object,so, //first delete it from list or tree. // if(lpMemMgr->dwVirtualAreaNum < SWITCH_VA_NUM) //Delete from list. DelVaFromList(lpThis,lpVad); else //Delete from tree. DelVaFromTree(lpThis,lpVad); // //According to different allocating type,to do the different actions. // switch(lpVad->dwAllocFlags) { case VIRTUAL_AREA_ALLOCATE_COMMIT: //The virtual memory area is committed. ReleaseCommit(lpThis,lpVad); KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0); //Release the memory occupied by //virtual area descriptor. break; case VIRTUAL_AREA_ALLOCATE_RESERVE: //Only reserved. KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0); //Only release the memory. break; case VIRTUAL_AREA_ALLOCATE_IO: //Committed,but without physical memory pages. ReleaseIoMap(lpThis,lpVad); KMemFree((LPVOID)lpVad,KMEM_SIZE_TYPE_ANY,0); break; default: break; } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); bResult = TRUE; //Set the completing flags. __TERMINAL: return; }
//Several helper routines used by DeviceCtrl. static DWORD __CtrlSectorRead(__COMMON_OBJECT* lpDrv, __COMMON_OBJECT* lpDev, __DRCB* lpDrcb) { __PARTITION_EXTENSION* pPe = NULL; __DEVICE_OBJECT* pDevice = (__DEVICE_OBJECT*)lpDev; DWORD dwStartSector = 0; DWORD dwSectorNum = 0; int nDiskNum = 0; DWORD i; DWORD dwFlags; //Parameter validity checking. if((NULL == lpDrcb->lpOutputBuffer) || (0 == lpDrcb->dwOutputLen)) { return 0; } if((NULL == lpDrcb->lpInputBuffer) || (0 == lpDrcb->dwInputLen)) { return 0; } //Get start sector and sector number to read. __ENTER_CRITICAL_SECTION(NULL,dwFlags); pPe = (__PARTITION_EXTENSION*)pDevice->lpDevExtension; dwStartSector = *(DWORD*)(lpDrcb->lpInputBuffer); //Input buffer stores the start pos. if(lpDrcb->dwOutputLen % pDevice->dwBlockSize) //Always integral block size times is valid. { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return 0; } dwSectorNum = lpDrcb->dwOutputLen / pDevice->dwBlockSize; //Check if the reading data exceed the device boundry. //if((dwStartSector + dwSectorNum) > (pPe->dwStartSector + pPe->dwSectorNum)) if((dwStartSector + dwSectorNum) > pPe->dwSectorNum) { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return 0; } dwStartSector += pPe->dwStartSector; nDiskNum = pPe->nDiskNum; __LEAVE_CRITICAL_SECTION(NULL,dwFlags); //Now issue the reading command. for(i = 0;i < dwSectorNum;i ++) { if(!ReadSector(nDiskNum,dwStartSector + i,1,((BYTE*)lpDrcb->lpOutputBuffer) + 512*i)) { return FALSE; } } //return ReadSector(nDiskNum,dwStartSector,dwSectorNum,(BYTE*)lpDrcb->lpOutputBuffer); return TRUE; }
static DWORD __CtrlSectorWrite(__COMMON_OBJECT* lpDrv, __COMMON_OBJECT* lpDev, __DRCB* lpDrcb) { __PARTITION_EXTENSION* pPe = NULL; __DEVICE_OBJECT* pDevice = (__DEVICE_OBJECT*)lpDev; __SECTOR_INPUT_INFO* psii = NULL; DWORD dwStartSector = 0; DWORD dwSectorNum = 0; int nDiskNum = 0; DWORD i; DWORD dwFlags; //Parameter validity checking. if((NULL == lpDrcb->lpInputBuffer) || (0 == lpDrcb->dwInputLen)) { return 0; } psii = (__SECTOR_INPUT_INFO*)lpDrcb->lpInputBuffer; //Get start sector and sector number to read. __ENTER_CRITICAL_SECTION(NULL,dwFlags); pPe = (__PARTITION_EXTENSION*)pDevice->lpDevExtension; if(psii->dwBufferLen % pDevice->dwBlockSize) //Always integral block size times is valid. { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return 0; } dwSectorNum = psii->dwBufferLen / pDevice->dwBlockSize; //Check if the reading data exceed the device boundry. if((psii->dwStartSector + dwSectorNum) > (pPe->dwStartSector + pPe->dwSectorNum)) { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return 0; } dwStartSector = psii->dwStartSector + pPe->dwStartSector; nDiskNum = pPe->nDiskNum; __LEAVE_CRITICAL_SECTION(NULL,dwFlags); //Now issue the reading command. for(i = 0;i < dwSectorNum;i ++) { if(!WriteSector(nDiskNum,dwStartSector + i,1,((BYTE*)psii->lpBuffer) + 512*i)) { return FALSE; } } return TRUE; }
VOID MutexUninitialize(struct __COMMON_OBJECT* lpThis) { struct __PRIORITY_QUEUE* lpWaitingQueue = NULL; struct __KERNEL_THREAD_OBJECT* lpKernelThread = NULL; DWORD dwFlags; if(NULL == lpThis) //parameter check. { BUG(); return; } lpWaitingQueue = ((__MUTEX*)lpThis)->lpWaitingQueue; __ENTER_CRITICAL_SECTION(NULL,dwFlags); lpKernelThread = (struct __KERNEL_THREAD_OBJECT*)lpWaitingQueue->GetHeaderElement( (struct __COMMON_OBJECT*)lpWaitingQueue, NULL); while(lpKernelThread) { lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY; lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK; lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_DELETED; KernelThreadManager.AddReadyKernelThread( (struct __COMMON_OBJECT*)&KernelThreadManager, lpKernelThread); lpKernelThread = (struct __KERNEL_THREAD_OBJECT*)lpWaitingQueue->GetHeaderElement( (struct __COMMON_OBJECT*)lpWaitingQueue, NULL); } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); ObjectManager.DestroyObject(&ObjectManager, (struct __COMMON_OBJECT*)lpWaitingQueue); return; }
//OpenDevice operations,it will be called indirectly by CreateFile. static __COMMON_OBJECT* ComDeviceOpen(__COMMON_OBJECT* lpDrv,__COMMON_OBJECT* lpDev, __DRCB* lpDrcb) { __COMMON_OBJECT* pRet = NULL; __COM_CONTROL_BLOCK* pCtrlBlock = NULL; DWORD dwFlags; if(NULL == lpDev) { goto __TERMINAL; } //Get interface control block from device extension. pCtrlBlock = (__COM_CONTROL_BLOCK*)((__DEVICE_OBJECT*)lpDev)->lpDevExtension; if(NULL == pCtrlBlock) { goto __TERMINAL; } //The COM device can noly be opened once. __ENTER_CRITICAL_SECTION(NULL,dwFlags); if(0 == pCtrlBlock->nOpenCount) //Not opened yet. { pCtrlBlock->nOpenCount ++; pRet = lpDev; } else //Opened yet. { pRet = NULL; } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); __TERMINAL: return pRet; }
// //The implementation of InsertIntoQueue. //This routine allocate a queue element object,initialize it,and //put the element object into queue. // static BOOL InsertIntoQueue(__COMMON_OBJECT* lpThis,LPVOID lpObject) { __COMMON_QUEUE* lpCommQueue = (__COMMON_QUEUE*)lpThis; __COMMON_QUEUE_ELEMENT* lpQueueEle = NULL; DWORD dwFlags = 0L; if(NULL == lpThis) //Invalidate parameter. return FALSE; if(CommQueueFull(lpThis)) //The current queue is full. return FALSE; lpQueueEle = ALLOCATE_QUEUE_ELEMENT(); if(NULL == lpQueueEle) //Can not allocate queue element. return FALSE; lpQueueEle->lpObject = lpObject; // //The following code puts the queue element into comnon queue, //and increase current queue element number. // __ENTER_CRITICAL_SECTION(NULL,dwFlags); lpQueueEle->lpNext = lpCommQueue->QueueHdr.lpNext; lpQueueEle->lpPrev = &lpCommQueue->QueueHdr; lpCommQueue->QueueHdr.lpNext->lpPrev = lpQueueEle; lpCommQueue->QueueHdr.lpNext = lpQueueEle; lpCommQueue->dwCurrentLen ++; __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return TRUE; }
//CloseDevice operations,it will be called indirectly by CloseFile. static DWORD ComDeviceClose(__COMMON_OBJECT* lpDrv,__COMMON_OBJECT* lpDev, __DRCB* lpDrcb) { __COM_CONTROL_BLOCK* pCtrlBlock = NULL; DWORD dwFlags; if(NULL == lpDev) { goto __TERMINAL; } //Get interface control block from device extension. pCtrlBlock = (__COM_CONTROL_BLOCK*)((__DEVICE_OBJECT*)lpDev)->lpDevExtension; if(NULL == pCtrlBlock) { goto __TERMINAL; } __ENTER_CRITICAL_SECTION(NULL,dwFlags); if(1 == pCtrlBlock->nOpenCount) { pCtrlBlock->nOpenCount --; } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); __TERMINAL: return 0; }
//Handler to handle the receive(RXNE) interrupt,DA means Data Available here,the name //inherites from COM driver implemented on X86 platform. static VOID DAIntHandler(__USART_CONTROL_BLOCK* pCtrlBlock) { CHAR bt; DWORD dwFlags; //Process data available interrupt. __ENTER_CRITICAL_SECTION(NULL,dwFlags); while(IsDataAvailable(pCtrlBlock->dwUsartBase)) //Data available. { bt = GetUsartByte(pCtrlBlock->dwUsartBase); //Read the byte. pCtrlBlock->Buffer[pCtrlBlock->nBuffTail] = bt; pCtrlBlock->nBuffTail ++; if(COM_BUFF_LENGTH == pCtrlBlock->nBuffTail) //Reach end of buffer. { pCtrlBlock->nBuffTail = 0; } if(pCtrlBlock->nBuffHeader == pCtrlBlock->nBuffTail) //Buffer full. { break; } } while(IsDataAvailable(pCtrlBlock->dwUsartBase)) //Drain out all data from COM interface,since the buffer is full. { GetUsartByte(pCtrlBlock->dwUsartBase); } //Wake up all threads waiting for COM data. while(pCtrlBlock->pReadingList) { pCtrlBlock->pReadingList->OnCompletion((__COMMON_OBJECT*)pCtrlBlock->pReadingList); pCtrlBlock->pReadingList = pCtrlBlock->pReadingList->lpNext; } pCtrlBlock->pReadingListTail = NULL; __LEAVE_CRITICAL_SECTION(NULL,dwFlags); }
// //SetThreadHook routine,this routine sets appropriate hook routine //according to dwHookType, and returns the old one. // __THREAD_HOOK_ROUTINE SetThreadHook(DWORD dwHookType, __THREAD_HOOK_ROUTINE lpRoutine) { __THREAD_HOOK_ROUTINE lpOldRoutine = NULL; DWORD dwFlags; __ENTER_CRITICAL_SECTION(NULL,dwFlags); switch(dwHookType) { case THREAD_HOOK_TYPE_CREATE: lpOldRoutine = KernelThreadManager.lpCreateHook; KernelThreadManager.lpCreateHook = lpRoutine; break; case THREAD_HOOK_TYPE_ENDSCHEDULE: lpOldRoutine = KernelThreadManager.lpEndScheduleHook; KernelThreadManager.lpEndScheduleHook = lpRoutine; break; case THREAD_HOOK_TYPE_BEGINSCHEDULE: lpOldRoutine = KernelThreadManager.lpBeginScheduleHook; KernelThreadManager.lpBeginScheduleHook = lpRoutine; break; case THREAD_HOOK_TYPE_TERMINAL: lpOldRoutine = KernelThreadManager.lpTerminalHook; KernelThreadManager.lpTerminalHook = lpRoutine; break; default: //Should not reach here. BUG(); break; } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return lpOldRoutine; }
// //CancelTimer implementation. //This routine is used to cancel timer. // static VOID CancelTimer(__COMMON_OBJECT* lpThis,__COMMON_OBJECT* lpTimer) { __SYSTEM* lpSystem = NULL; DWORD dwPriority = 0; DWORD dwFlags; __TIMER_OBJECT* lpTimerObject = NULL; if((NULL == lpThis) || (NULL == lpTimer)) { return; } lpSystem = (__SYSTEM*)lpThis; //if(((__TIMER_OBJECT*)lpTimer)->dwTimerFlags != TIMER_FLAGS_ALWAYS) // return; __ENTER_CRITICAL_SECTION(NULL,dwFlags); lpSystem->lpTimerQueue->DeleteFromQueue((__COMMON_OBJECT*)lpSystem->lpTimerQueue, lpTimer); lpTimerObject = (__TIMER_OBJECT*) lpSystem->lpTimerQueue->GetHeaderElement( (__COMMON_OBJECT*)lpSystem->lpTimerQueue, &dwPriority); if(NULL == lpTimerObject) //There is not any timer object to be processed. { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); goto __DESTROY_TIMER; } // //The following code updates the tick counter that timer object should be processed. // dwPriority = MAX_DWORD_VALUE - dwPriority; if(dwPriority > lpSystem->dwNextTimerTick) lpSystem->dwNextTimerTick = dwPriority; dwPriority = MAX_DWORD_VALUE - dwPriority; lpSystem->lpTimerQueue->InsertIntoQueue( (__COMMON_OBJECT*)lpSystem->lpTimerQueue, (__COMMON_OBJECT*)lpTimerObject, dwPriority); //Insert into timer object queue. __LEAVE_CRITICAL_SECTION(NULL,dwFlags); __DESTROY_TIMER: //Destroy the timer object. ObjectManager.DestroyObject(&ObjectManager, lpTimer); return; }
static __COMMON_OBJECT* ConnectInterrupt(__COMMON_OBJECT* lpThis, __INTERRUPT_HANDLER lpInterruptHandler, LPVOID lpHandlerParam, UCHAR ucVector, UCHAR ucReserved1, UCHAR ucReserved2, UCHAR ucInterruptMode, BOOL bIfShared, DWORD dwCPUMask) { __INTERRUPT_OBJECT* lpInterrupt = NULL; __INTERRUPT_OBJECT* lpObjectRoot = NULL; __SYSTEM* lpSystem = &System; //Had as a BUG here!!! DWORD dwFlags = 0; if((NULL == lpThis) || (NULL == lpInterruptHandler)) //Parameters valid check. { return NULL; } if(ucVector >= MAX_INTERRUPT_VECTOR) //Impossible!!! { return NULL; } lpInterrupt = (__INTERRUPT_OBJECT*) ObjectManager.CreateObject(&ObjectManager,NULL,OBJECT_TYPE_INTERRUPT); if(NULL == lpInterrupt) //Failed to create interrupt object. { return FALSE; } if(!lpInterrupt->Initialize((__COMMON_OBJECT*)lpInterrupt)) //Failed to initialize. { return FALSE; } lpInterrupt->lpPrevInterruptObject = NULL; lpInterrupt->lpNextInterruptObject = NULL; lpInterrupt->InterruptHandler = lpInterruptHandler; lpInterrupt->lpHandlerParam = lpHandlerParam; lpInterrupt->ucVector = ucVector; __ENTER_CRITICAL_SECTION(NULL,dwFlags); lpObjectRoot = lpSystem->lpInterruptVector[ucVector]; if(NULL == lpObjectRoot) //If this is the first interrupt object of the vector. { System.lpInterruptVector[ucVector] = lpInterrupt; } else { lpInterrupt->lpNextInterruptObject = lpObjectRoot; lpObjectRoot->lpPrevInterruptObject = lpInterrupt; System.lpInterruptVector[ucVector] = lpInterrupt; } //LEAVE_CRITICAL_SECTION(); __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return (__COMMON_OBJECT*)lpInterrupt; }
// //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; DWORD dwResult = OBJECT_WAIT_FAILED; if(NULL == lpMutex) { 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; lpKernelThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK; lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_WAITING; //Waiting on mutex's waiting queue. lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED; lpMutex->dwWaitingNum ++; //Added in 2015-04-06. lpMutex->lpWaitingQueue->InsertIntoQueue( (__COMMON_OBJECT*)lpMutex->lpWaitingQueue, (__COMMON_OBJECT*)lpKernelThread, 0); __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return TimeOutWaiting((__COMMON_OBJECT*)lpMutex, lpMutex->lpWaitingQueue,lpKernelThread,dwMillionSecond,MutexTimeOutCallback); } }
// //InsertIntoList routine,this routine inserts a virtual area descriptor object into //virtual area list. // static VOID InsertIntoList(__COMMON_OBJECT* lpThis,__VIRTUAL_AREA_DESCRIPTOR* lpVad) { __VIRTUAL_MEMORY_MANAGER* lpMemMgr = (__VIRTUAL_MEMORY_MANAGER*)lpThis; DWORD dwFlags = 0; __VIRTUAL_AREA_DESCRIPTOR* lpFirst = NULL; __VIRTUAL_AREA_DESCRIPTOR* lpSecond = NULL; if((NULL == lpThis) || (NULL == lpVad)) //Invalidate parameters. return; __ENTER_CRITICAL_SECTION(NULL,dwFlags); lpFirst = lpMemMgr->lpListHdr; if(NULL == lpFirst) //There is not any element in the list. { lpMemMgr->lpListHdr = lpVad; lpMemMgr->dwVirtualAreaNum ++; //Increment the reference counter. __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return; } lpSecond = lpFirst; while(lpFirst) { if((DWORD)lpFirst->lpStartAddr > (DWORD)lpVad->lpStartAddr) //Find the proper position. break; lpSecond = lpFirst; lpFirst = lpFirst->lpNext; } if(lpSecond == lpFirst) //Should be the first element in the list. { lpVad->lpNext = lpMemMgr->lpListHdr; lpMemMgr->lpListHdr = lpVad; lpMemMgr->dwVirtualAreaNum ++; __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return; } else //Should not be the first element. { lpVad->lpNext = lpSecond->lpNext; lpSecond->lpNext = lpVad; } lpMemMgr->dwVirtualAreaNum ++; //Increment the virtual area's total number. __LEAVE_CRITICAL_SECTION(NULL,dwFlags); }
// //The implementation of WaitForKernelThreadObject,because this routine calls ScheduleFromproc, //so we implement it here(After the implementation of ScheduleFromProc). //The routine does the following: // 1. Check the current status of the kernel thread object; // 2. If the current status is not KERNEL_THREAD_STATUS_TERMINAL,then block the // current kernel thread(who want to wait),put it into the object's waiting queue; // 3. Call ScheduleFromProc to fetch next kernel thread whose status is READY to run. // DWORD WaitForKernelThreadObject(__COMMON_OBJECT* lpThis) { __KERNEL_THREAD_OBJECT* lpKernelThread = NULL; __KERNEL_THREAD_OBJECT* lpCurrent = NULL; __PRIORITY_QUEUE* lpWaitingQueue = NULL; DWORD dwFlags = 0; if(NULL == lpThis) //Parameter check. { return 0; } lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpThis; __ENTER_CRITICAL_SECTION(NULL,dwFlags); if(KERNEL_THREAD_STATUS_TERMINAL == lpKernelThread->dwThreadStatus) //If the object's //status is TERMINAL, //the wait operation //will secussfully. { __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return OBJECT_WAIT_RESOURCE; } // //If the waited object's status is not TERMINAL,then the waiting operation will //not secussful,the current kernel thread who want to wait will be blocked. // lpWaitingQueue = lpKernelThread->lpWaitingQueue; lpCurrent = KernelThreadManager.lpCurrentKernelThread; lpCurrent->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED; lpWaitingQueue->InsertIntoQueue((__COMMON_OBJECT*)lpWaitingQueue, (__COMMON_OBJECT*)lpCurrent, 0); //Insert into the current kernel thread into waiting queue. __LEAVE_CRITICAL_SECTION(NULL,dwFlags); KernelThreadManager.ScheduleFromProc(NULL); return 0; }
// //The following routine prints out bug's information. // VOID __BUG(LPSTR lpszFileName,DWORD dwLineNum) { DWORD dwFlags; //Print out fatal error information. _hx_printf("\r\nBUG oencountered.\r\nFile name: %s\r\nCode Lines:%d",lpszFileName,dwLineNum); //Enter infinite loop. __ENTER_CRITICAL_SECTION(NULL,dwFlags); while(TRUE); __LEAVE_CRITICAL_SECTION(NULL,dwFlags); }
// //The implementation of ReleaseMutex. // static DWORD kReleaseMutex(__COMMON_OBJECT* lpThis) { __KERNEL_THREAD_OBJECT* lpKernelThread = NULL; __MUTEX* lpMutex = NULL; DWORD dwPreviousStatus = 0; DWORD dwFlags = 0; if(NULL == lpThis) //Parameter check. return 0; 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 no kernel thread waiting for the object. { dwPreviousStatus = lpMutex->dwMutexStatus; lpMutex->dwMutexStatus = MUTEX_STATUS_FREE; //Set to free. __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return 0; } lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpMutex->lpWaitingQueue->GetHeaderElement( (__COMMON_OBJECT*)lpMutex->lpWaitingQueue, 0); //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 CommQueueFull. //This routine checks the current element number of current queue. //If it equals the queue number,then returns TRUE,else, //returns FALSE. // static BOOL CommQueueFull(__COMMON_OBJECT* lpThis) { __COMMON_QUEUE* lpComQueue = (__COMMON_QUEUE*)lpThis; DWORD dwFlags = 0L; BOOL bResult = FALSE; if(NULL == lpThis) return FALSE; __ENTER_CRITICAL_SECTION(NULL,dwFlags); bResult = (lpComQueue->dwCurrentLen == lpComQueue->dwQueueLen); __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return bResult; }
static void Logk(__DEBUG_MANAGER *pThis, char *tag, char *msg) { __DEBUG_MANAGER *pDebugManager = pThis; __LOG_MESSAGE *pMsg = NULL; __KERNEL_THREAD_OBJECT *lpCurrentThread = NULL; int Result = -1; int dwFlags = 0; pMsg = (__LOG_MESSAGE *)KMemAlloc(sizeof(__LOG_MESSAGE),KMEM_SIZE_TYPE_ANY); // //Set to default now // pMsg->code = 0; pMsg->format = 0; pMsg->len = 0; pMsg->pid = 0; pMsg->time = 0; // //*****XXX******* // FIXME // __ENTER_CRITICAL_SECTION(NULL, dwFlags); lpCurrentThread = KernelThreadManager.lpCurrentKernelThread; StrCpy(lpCurrentThread->KernelThreadName,pMsg->name); pMsg->tid = lpCurrentThread->dwThreadID; __LEAVE_CRITICAL_SECTION(NULL, dwFlags); StrCpy(msg, pMsg->msg); StrCpy(tag, pMsg->tag); // //Get the authority to visit the bufferqueue // Result = pDebugManager->pMutexForKRNLBufferQueue->WaitForThisObject((__COMMON_OBJECT*)DebugManager.pMutexForKRNLBufferQueue); if (Result == OBJECT_WAIT_RESOURCE) { pDebugManager->pKRNLBufferQueue->Enqueue( pDebugManager->pKRNLBufferQueue, pMsg); pDebugManager->pMutexForKRNLBufferQueue->ReleaseMutex((__COMMON_OBJECT*)DebugManager.pMutexForKRNLBufferQueue); } KMemFree(pMsg, KMEM_SIZE_TYPE_ANY, 0); return; }
//Implementation of DeviceClose routine. static DWORD FatDeviceClose(__COMMON_OBJECT* lpDrv, __COMMON_OBJECT* lpDev, __DRCB* lpDrcb) { __DEVICE_OBJECT* pDeviceObject = (__DEVICE_OBJECT*)lpDev; __FAT32_FS* pFat32Fs = NULL; __FAT32_FILE* pFileObject = NULL; DWORD _dwFlags; if((NULL == pDeviceObject) || (NULL == lpDrcb)) { return 0; } pFileObject = (__FAT32_FILE*)pDeviceObject->lpDevExtension; pFat32Fs = pFileObject->pFileSystem; //Delete the fat32 file object from file system. __ENTER_CRITICAL_SECTION(NULL, _dwFlags); if((pFileObject->pPrev == NULL) && (pFileObject->pNext == NULL)) { pFat32Fs->pFileList = NULL; } else { if(pFileObject->pPrev == NULL) //This is the first object in file list. { pFat32Fs->pFileList = pFileObject->pNext; pFileObject->pNext->pPrev = NULL; } else //Not the fist file in list. { if(NULL == pFileObject->pNext) //This is the last one in list. { pFileObject->pPrev->pNext = NULL; } else //Neither is the first nor is the last one in list. { pFileObject->pPrev->pNext = pFileObject->pNext; pFileObject->pNext->pPrev = pFileObject->pPrev; } } } __LEAVE_CRITICAL_SECTION(NULL, _dwFlags); //Release the file object. RELEASE_OBJECT(pFileObject); //Destroy file device object. IOManager.DestroyDevice((__COMMON_OBJECT*)&IOManager,pDeviceObject); return 0; }
// //The implementation of SetQueueLength. //This routine sets the queue's length to dwNewLen,and returns the old //value of queue length. // static DWORD SetQueueLength(__COMMON_OBJECT* lpThis,DWORD dwNewLen) { __COMMON_QUEUE* lpComQueue = (__COMMON_QUEUE*)lpThis; DWORD dwFlags = 0L; DWORD dwOldLen = 0L; if(NULL == lpThis) return 0L; __ENTER_CRITICAL_SECTION(NULL,dwFlags); dwOldLen = lpComQueue->dwQueueLen; lpComQueue->dwQueueLen = dwNewLen; __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return dwOldLen; }
static DWORD WaitForMutexObject(__COMMON_OBJECT* lpThis) { __KERNEL_THREAD_OBJECT* lpKernelThread = NULL; __MUTEX* lpMutex = (__MUTEX*)lpThis; DWORD dwFlags = 0; if(NULL == lpMutex) //Parameter check. { return 0; } __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->dwWaitingStatus &= ~OBJECT_WAIT_MASK; lpKernelThread->dwWaitingStatus |= OBJECT_WAIT_WAITING; lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_BLOCKED; lpMutex->dwWaitingNum ++; //Increment the waiting number. lpMutex->lpWaitingQueue->InsertIntoQueue( (__COMMON_OBJECT*)lpMutex->lpWaitingQueue, (__COMMON_OBJECT*)lpKernelThread, 0); __LEAVE_CRITICAL_SECTION(NULL,dwFlags); //Leave critical section here is safety. //Reschedule all kernel thread(s). KernelThreadManager.ScheduleFromProc(NULL); } return OBJECT_WAIT_RESOURCE; }
//Timer handler routine for all synchronous object. static DWORD WaitingTimerHandler(LPVOID lpData) { struct __TIMER_HANDLER_PARAM* lpHandlerParam = (struct __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( (struct __COMMON_OBJECT*)lpHandlerParam->lpWaitingQueue, (struct __COMMON_OBJECT*)lpHandlerParam->lpKernelThread); //Add this kernel thread to ready queue. lpHandlerParam->lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY; KernelThreadManager.AddReadyKernelThread((struct __COMMON_OBJECT*)&KernelThreadManager, lpHandlerParam->lpKernelThread); break; default: __LEAVE_CRITICAL_SECTION(NULL,dwFlags); BUG(); return 0L; } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); return 0L; }
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) if (EVENT_STATUS_FREE != lpEvent->dwEventStatus) { //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); //Clear the kernel object's signature. lpEvent->dwObjectSignature = 0; ObjectManager.DestroyObject(&ObjectManager, (__COMMON_OBJECT*)lpPriorityQueue); //*******CAUTION!!!************ 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 kSetEvent(__COMMON_OBJECT* lpThis) { DWORD dwPreviousStatus = EVENT_STATUS_OCCUPIED; __EVENT* lpEvent = NULL; __KERNEL_THREAD_OBJECT* lpKernelThread = NULL; DWORD dwFlags = 0; 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; }
// //KernelThreadWrapper routine. //The routine is all kernel thread's entry porint. //The routine does the following: // 1. Calles the kernel thread's start routine; // 2. When the start routine is over,put the kernel thread object into terminal queue; // 3. Wakeup all kernel thread(s) waiting for this kernel thread object. // 4. Reschedule all kernel thread(s). //This routine will never return. // VOID KernelThreadWrapper(__COMMON_OBJECT* lpKThread) { __KERNEL_THREAD_OBJECT* lpKernelThread = NULL; __KERNEL_THREAD_OBJECT* lpWaitingThread = NULL; __PRIORITY_QUEUE* lpWaitingQueue = NULL; DWORD dwRetValue = 0; DWORD dwFlags = 0; lpKernelThread = (__KERNEL_THREAD_OBJECT*)lpKThread; //Execute user defined kernel thread function. dwRetValue = lpKernelThread->KernelThreadRoutine(lpKernelThread->lpRoutineParam); __ENTER_CRITICAL_SECTION(NULL,dwFlags); lpKernelThread->dwReturnValue = dwRetValue; //Set the return value of this thread. lpKernelThread->dwThreadStatus = KERNEL_THREAD_STATUS_TERMINAL; //Change the status. //Insert the current kernel thread object into TERMINAL queue. KernelThreadManager.lpTerminalQueue->InsertIntoQueue((__COMMON_OBJECT*)KernelThreadManager.lpTerminalQueue, (__COMMON_OBJECT*)lpKernelThread, 0); // //The following code wakeup all kernel thread(s) who waiting for this kernel thread //object. // lpWaitingQueue = lpKernelThread->lpWaitingQueue; lpWaitingThread = (__KERNEL_THREAD_OBJECT*)lpWaitingQueue->GetHeaderElement( (__COMMON_OBJECT*)lpWaitingQueue, NULL); while(lpWaitingThread) { lpWaitingThread->dwThreadStatus = KERNEL_THREAD_STATUS_READY; lpWaitingThread->dwWaitingStatus &= ~OBJECT_WAIT_MASK; lpWaitingThread->dwWaitingStatus |= OBJECT_WAIT_RESOURCE; KernelThreadManager.AddReadyKernelThread( (__COMMON_OBJECT*)&KernelThreadManager, lpWaitingThread); //Add to ready queue. lpWaitingThread = (__KERNEL_THREAD_OBJECT*)lpWaitingQueue->GetHeaderElement( (__COMMON_OBJECT*)lpWaitingQueue, NULL); } __LEAVE_CRITICAL_SECTION(NULL,dwFlags); KernelThreadManager.ScheduleFromProc(NULL); //Re-schedule kernel thread. return; //***** CAUTION! ***** : This instruction will never reach. }