//초기 프로세스와 쓰레드의 생성과 설정 static BOOL PspCreateSystemProcess(void) { HANDLE process_handle; HANDLE init_thread_handle, idle_thread_handle, process_cutter_handle, thread_cutter_handle; HANDLE tmr_thread_handle, sw_task_sw_handle; //메인 프로세스를 생성해주는 PSCreateProcess 함수 호출 if(!PsCreateProcess(&process_handle)) return FALSE; //프로세스를 생성하기 위해 베이스가 될 메인 쓰레드(init 쓰레드) 생성 if(!PsCreateThread(&init_thread_handle, process_handle, NULL, NULL, DEFAULT_STACK_SIZE, FALSE)) return FALSE; //초기 쓰레드의 백링크(Prev-Link) 설정 HalSetupTaskLink(&PsGetThreadPtr(init_thread_handle)->thread_tss32, TASK_SW_SEG); //초기 쓰레드의 TSS를 GDT내에 설정 HalWriteTssIntoGdt(&PsGetThreadPtr(init_thread_handle)->thread_tss32, sizeof(TSS_32), INIT_TSS_SEG, FALSE); _asm { push ax mov ax, INIT_TSS_SEG ltr ax pop ax } if(!PsCreateIntThread(&tmr_thread_handle, process_handle, Psp_IRQ_SystemTimer, NULL, DEFAULT_STACK_SIZE)) return FALSE; HalWriteTssIntoGdt(&PsGetThreadPtr(tmr_thread_handle)->thread_tss32, sizeof(TSS_32), TMR_TSS_SEG, FALSE); if(!PsCreateIntThread(&sw_task_sw_handle, process_handle, PspSoftTaskSW, NULL, DEFAULT_STACK_SIZE)) return FALSE; HalWriteTssIntoGdt(&PsGetThreadPtr(sw_task_sw_handle)->thread_tss32, sizeof(TSS_32), SOFT_TS_TSS_SEG, FALSE); if(!PsCreateThread(&idle_thread_handle, process_handle, PspIdleThread, NULL, DEFAULT_STACK_SIZE, FALSE)) return FALSE; PsSetThreadStatus(idle_thread_handle, THREAD_STATUS_RUNNING); HalWriteTssIntoGdt(&PsGetThreadPtr(idle_thread_handle)->thread_tss32, sizeof(TSS_32), TASK_SW_SEG, TRUE); m_ProcMgrBlk.pt_current_thread = idle_thread_handle; if(!PsCreateThread(&process_cutter_handle, process_handle, PspProcessCutterThread, NULL, DEFAULT_STACK_SIZE, FALSE)) return FALSE; PsSetThreadStatus(process_cutter_handle, THREAD_STATUS_READY); if(!PsCreateThread(&thread_cutter_handle, process_handle, PspThreadCutterThread, NULL, DEFAULT_STACK_SIZE, FALSE)) return FALSE; PsSetThreadStatus(thread_cutter_handle, THREAD_STATUS_READY); return TRUE; }
static BOOL PspCreateSystemProcess(void) { HANDLE process_handle; HANDLE init_thread_handle, idle_thread_handle, process_cutter_handle, thread_cutter_handle; HANDLE tmr_thread_handle, sw_task_sw_handle; if(!PsCreateProcess(&process_handle)) return FALSE; /* create init_thread. */ if(!PsCreateThread(&init_thread_handle, process_handle, NULL, NULL, DEFAULT_STACK_SIZE, FALSE)) return FALSE; HalSetupTaskLink(&PsGetThreadPtr(init_thread_handle)->thread_tss32, TASK_SW_SEG); HalWriteTssIntoGdt(&PsGetThreadPtr(init_thread_handle)->thread_tss32, sizeof(TSS_32), INIT_TSS_SEG, FALSE); _asm { push ax mov ax, INIT_TSS_SEG ltr ax pop ax } /* create tmr_int_handler_thread. */ if(!PsCreateIntThread(&tmr_thread_handle, process_handle, Psp_IRQ_SystemTimer, NULL, DEFAULT_STACK_SIZE)) return FALSE; HalWriteTssIntoGdt(&PsGetThreadPtr(tmr_thread_handle)->thread_tss32, sizeof(TSS_32), TMR_TSS_SEG, FALSE); /* create soft-task-switching thread */ if(!PsCreateIntThread(&sw_task_sw_handle, process_handle, PspSoftTaskSW, NULL, DEFAULT_STACK_SIZE)) return FALSE; HalWriteTssIntoGdt(&PsGetThreadPtr(sw_task_sw_handle)->thread_tss32, sizeof(TSS_32), SOFT_TS_TSS_SEG, FALSE); /* create idle_thread. */ if(!PsCreateThread(&idle_thread_handle, process_handle, PspIdleThread, NULL, DEFAULT_STACK_SIZE, FALSE)) return FALSE; PsSetThreadStatus(idle_thread_handle, THREAD_STATUS_RUNNING); HalWriteTssIntoGdt(&PsGetThreadPtr(idle_thread_handle)->thread_tss32, sizeof(TSS_32), TASK_SW_SEG, TRUE); /* LAST PARAMETER SHOULD BE SET WITH 'TRUE'. IMPORTANT!! */ m_ProcMgrBlk.pt_current_thread = idle_thread_handle; /* IMPORTANT!! */ /* process cutter & thread cutter */ if(!PsCreateThread(&process_cutter_handle, process_handle, PspProcessCutterThread, NULL, DEFAULT_STACK_SIZE, FALSE)) return FALSE; PsSetThreadStatus(process_cutter_handle, THREAD_STATUS_READY); if(!PsCreateThread(&thread_cutter_handle, process_handle, PspThreadCutterThread, NULL, DEFAULT_STACK_SIZE, FALSE)) return FALSE; PsSetThreadStatus(thread_cutter_handle, THREAD_STATUS_READY); return TRUE; }
//Init 쓰레드의 핸들러 함수 static void PspTaskEntryPoint(void) { PKSTART_ROUTINE start_routine; HANDLE current_thread; DWORD ret_value; current_thread = PsGetCurrentThread(); start_routine = PsGetThreadPtr(current_thread)->start_routine; ret_value = start_routine(PsGetThreadPtr(current_thread)->start_context); PsGetThreadPtr(current_thread)->thread_status = THREAD_STATUS_TERMINATED; HalTaskSwitch(); while(1) ; }
static DWORD PspProcessCutterThread(PVOID StartContext) { HANDLE ProcessHandle; PPROCESS_CONTROL_BLOCK *pt_prev_process, *pt_cur_process; PTHREAD_CONTROL_BLOCK *pt_cur_thread; while(1) { /* check process cutting list */ if(!PspPopCuttingItem(&m_ProcessCuttingList, &ProcessHandle)) { HalTaskSwitch(); continue; } ENTER_CRITICAL_SECTION(); /* if requsted process handle is same with system process handle, then do nothing!! protect system process */ if(ProcessHandle == PsGetThreadPtr(PsGetCurrentThread())->parent_process_handle) { goto $exit; } /* find requested process position in the process list */ pt_prev_process = pt_cur_process = &(m_ProcMgrBlk.pt_head_process); while(*pt_cur_process != PsGetProcessPtr(ProcessHandle)) { /* there is no requested process in the list */ if((*pt_cur_process)->pt_next_process == NULL) { goto $exit; } pt_prev_process = pt_cur_process; pt_cur_process = &((*pt_cur_process)->pt_next_process); } /* change next process pointer */ (*pt_prev_process)->pt_next_process = (*pt_cur_process)->pt_next_process; m_ProcMgrBlk.process_count--; /* dealloc all threads belonged to the requested process */ pt_cur_thread = &(PsGetProcessPtr(ProcessHandle)->pt_head_thread); while(*pt_cur_thread != NULL) { MmFreeNonCachedMemory((PVOID)((*pt_cur_thread)->pt_stack_base_address)); MmFreeNonCachedMemory((PVOID)(*pt_cur_thread)); pt_cur_thread = &((*pt_cur_thread)->pt_next_thread); } /* dealloc the requested process memory */ MmFreeNonCachedMemory((PVOID)ProcessHandle); $exit: EXIT_CRITICAL_SECTION(); } return 0; }
static BOOL PspAddNewThread(HANDLE ProcessHandle, HANDLE ThreadHandle) { PTHREAD_CONTROL_BLOCK *pt_next_thread; ENTER_CRITICAL_SECTION(); pt_next_thread = &PsGetProcessPtr(ProcessHandle)->pt_head_thread; while(*pt_next_thread) pt_next_thread = &(*pt_next_thread)->pt_next_thread; *pt_next_thread = PsGetThreadPtr(ThreadHandle); PsGetProcessPtr(ProcessHandle)->thread_count++; EXIT_CRITICAL_SECTION(); return TRUE; }
static DWORD PspThreadCutterThread(PVOID StartContext) { HANDLE ProcessHandle, ThreadHandle; PTHREAD_CONTROL_BLOCK *pt_prev_thread, *pt_cur_thread; while(1) { /* check thread cutting list */ if(!PspPopCuttingItem(&m_ThreadCuttingList, &ThreadHandle)) { HalTaskSwitch(); continue; } ENTER_CRITICAL_SECTION(); ProcessHandle = PsGetThreadPtr(ThreadHandle)->parent_process_handle; /* if requsted thread's parent process handle is same with system process handle, then do nothing!! protect system thread */ if(ProcessHandle == PsGetThreadPtr(PsGetCurrentThread())->parent_process_handle) { goto $exit; } /* invalid thread */ if(PsGetProcessPtr(ProcessHandle)->thread_count == 0) { goto $exit; } /* check whether there is only one thread exist in the parent process */ else if(PsGetProcessPtr(ProcessHandle)->thread_count == 1) { PsGetProcessPtr(ProcessHandle)->pt_head_thread = NULL; } /* more than 2 threads exist */ else { pt_prev_thread = pt_cur_thread = &(PsGetProcessPtr(ProcessHandle)->pt_head_thread); while(*pt_cur_thread != PsGetThreadPtr(ThreadHandle)) { /* there is no requested thread in the parent process */ if((*pt_cur_thread)->pt_next_thread == NULL) { goto $exit; } pt_prev_thread = pt_cur_thread; pt_cur_thread = &((*pt_cur_thread)->pt_next_thread); } /* change next thread pointer */ (*pt_prev_thread)->pt_next_thread = (*pt_cur_thread)->pt_next_thread; } PsGetProcessPtr(ProcessHandle)->thread_count--; /* except user mode program's stack */ if(PsGetThreadPtr(ThreadHandle)->pt_stack_base_address >= (int *)0x00200000) MmFreeNonCachedMemory((PVOID)(PsGetThreadPtr(ThreadHandle)->pt_stack_base_address)); /* dealloc stack */ MmFreeNonCachedMemory((PVOID)(PsGetThreadPtr(ThreadHandle))); /* dealloc thread */ $exit: EXIT_CRITICAL_SECTION(); } return 0; }
//종료된 프로세스의 삭제 static DWORD PspProcessCutterThread(PVOID StartContext) { HANDLE ProcessHandle; PPROCESS_CONTROL_BLOCK *pt_prev_process, *pt_cur_process; PTHREAD_CONTROL_BLOCK *pt_cur_thread; while(1) { if(!PspPopCuttingItem(&m_ProcessCuttingList, &ProcessHandle)) { HalTaskSwitch(); continue; } ENTER_CRITICAL_SECTION(); if(ProcessHandle == PsGetThreadPtr(PsGetCurrentThread())->parent_process_handle) { goto $exit; } pt_prev_process = pt_cur_process = &(m_ProcMgrBlk.pt_head_process); while(*pt_cur_process != PsGetProcessPtr(ProcessHandle)) { if((*pt_cur_process)->pt_next_process == NULL) { goto $exit; } pt_prev_process = pt_cur_process; pt_cur_process = &((*pt_cur_process)->pt_next_process); } (*pt_prev_process)->pt_next_process = (*pt_cur_process)->pt_next_process; m_ProcMgrBlk.process_count--; pt_cur_thread = &(PsGetProcessPtr(ProcessHandle)->pt_head_thread); while(*pt_cur_thread != NULL) { MmFreeNonCachedMemory((PVOID)((*pt_cur_thread)->pt_stack_base_address)); MmFreeNonCachedMemory((PVOID)(*pt_cur_thread)); pt_cur_thread = &((*pt_cur_thread)->pt_next_thread); } MmFreeNonCachedMemory((PVOID)ProcessHandle); $exit: EXIT_CRITICAL_SECTION(); } return 0; }
//종료된 쓰레드의 삭제 static DWORD PspThreadCutterThread(PVOID StartContext) { HANDLE ProcessHandle, ThreadHandle; PTHREAD_CONTROL_BLOCK *pt_prev_thread, *pt_cur_thread; while(1) { if(!PspPopCuttingItem(&m_ThreadCuttingList, &ThreadHandle)) { HalTaskSwitch(); continue; } ENTER_CRITICAL_SECTION(); ProcessHandle = PsGetThreadPtr(ThreadHandle)->parent_process_handle; if(ProcessHandle == PsGetThreadPtr(PsGetCurrentThread())->parent_process_handle) { goto $exit; } if(PsGetProcessPtr(ProcessHandle)->thread_count == 0) { goto $exit; } else if(PsGetProcessPtr(ProcessHandle)->thread_count == 1) { PsGetProcessPtr(ProcessHandle)->pt_head_thread = NULL; } else { pt_prev_thread = pt_cur_thread = &(PsGetProcessPtr(ProcessHandle)->pt_head_thread); while(*pt_cur_thread != PsGetThreadPtr(ThreadHandle)) { if((*pt_cur_thread)->pt_next_thread == NULL) { goto $exit; } pt_prev_thread = pt_cur_thread; pt_cur_thread = &((*pt_cur_thread)->pt_next_thread); } (*pt_prev_thread)->pt_next_thread = (*pt_cur_thread)->pt_next_thread; } PsGetProcessPtr(ProcessHandle)->thread_count--; if(PsGetThreadPtr(ThreadHandle)->pt_stack_base_address >= (int *)0x00200000) MmFreeNonCachedMemory((PVOID)(PsGetThreadPtr(ThreadHandle)->pt_stack_base_address)); MmFreeNonCachedMemory((PVOID)(PsGetThreadPtr(ThreadHandle))); $exit: EXIT_CRITICAL_SECTION(); } }
//태스크 스위칭 방법 중 하나 static void PspSetupTaskSWEnv(void) { HANDLE current_thread, next_thread; current_thread = PsGetCurrentThread(); next_thread = PspFindNextThreadScheduled(); if(PsGetThreadPtr(current_thread)->thread_status == THREAD_STATUS_TERMINATED) { if(PsGetThreadPtr(current_thread)->auto_delete) { PsDeleteThread(current_thread); } } else if(PsGetThreadPtr(current_thread)->thread_status == THREAD_STATUS_RUNNING) { PsGetThreadPtr(current_thread)->thread_status = THREAD_STATUS_READY; } if(current_thread != next_thread && next_thread != NULL) { HalWriteTssIntoGdt(&PsGetThreadPtr(next_thread)->thread_tss32, sizeof(TSS_32), TASK_SW_SEG, TRUE); PsGetThreadPtr(next_thread)->thread_status = THREAD_STATUS_RUNNING; } }
static void PspSetupTaskSWEnv(void) { HANDLE current_thread, next_thread; /* get threads */ current_thread = PsGetCurrentThread(); next_thread = PspFindNextThreadScheduled(); /* at this time, current thread is changed with new thing */ if(PsGetThreadPtr(current_thread)->thread_status == THREAD_STATUS_TERMINATED) { /* auto delete? */ if(PsGetThreadPtr(current_thread)->auto_delete) { PsDeleteThread(current_thread); } } else if(PsGetThreadPtr(current_thread)->thread_status == THREAD_STATUS_RUNNING) { PsGetThreadPtr(current_thread)->thread_status = THREAD_STATUS_READY; } /* task switching */ if(current_thread != next_thread && next_thread != NULL) { HalWriteTssIntoGdt(&PsGetThreadPtr(next_thread)->thread_tss32, sizeof(TSS_32), TASK_SW_SEG, TRUE); PsGetThreadPtr(next_thread)->thread_status = THREAD_STATUS_RUNNING; } }
KERNELAPI BOOL PsSetThreadStatus(HANDLE ThreadHandle, THREAD_STATUS Status) { PsGetThreadPtr(ThreadHandle)->thread_status = Status; return TRUE; }
//쓰레드 핸들을 가지고 부모 프로세스의 핸들을 얻는 함수 KERNELAPI HANDLE PsGetParentProcess(IN HANDLE ThreadHandle) { return (HANDLE)(PsGetThreadPtr(ThreadHandle)->parent_process_handle); }
//쓰레드 핸들을 가지고 쓰레드의 상태를 얻는 함수 KERNELAPI THREAD_STATUS PsGetThreadStatus(IN HANDLE ThreadHandle) { return (THREAD_STATUS)(PsGetThreadPtr(ThreadHandle)->thread_status); }