线程调度的部分资料

什么是进程调度和线程调度?如何进行调度算法的设计和实现? 进程调度和线程调度是操作系统中的核心概念,涉及到如何有效地利用计算机资源,确保任务能够按照既定的优先级和时间要求执行。不同的应用场景可能需要不同的调度算法,因此在操作系统设计中,选择合适的调度策略对于系统的性能和稳定性至关重要。这个决定的过程就是进程调度。线程调度的主要目标与进程调度相似,但考虑到线程间的共享资源,有时需要更为精细的调度。RR 调度算法给每个任务分配一个固定的时间片,任务在时间片用完后被放到队列的末尾,下一个任务开始执行。系统的吞吐量是一个重要的性能指标,表示在一定时间内完成的任务数量。 阅读详情
PART 1: Kernel Object

//每一位表示对应这个特权级的队列中是否有线程(主要在KiSwapThread用,详细代码见PART3) ULONG KiReadySummary = 0 

 - Referenced by KeSetAffinityThread(),KiFindReadyThread(),KiReadyThread(),    KiScanReadyQueues(),  KiSetPriorityThread(), and NtYieldExecution().

// LIST_ENTRY  KeBugCheckCallbackListHead

// LIST_ENTRY KiDispatcherReadyListHead[MAXIMUM_PRIORITY] 

  - Referenced by KeSetAffinityThread(), KiFindReadyThread(), KiInitSystem(),     KiReadyThread(), KiScanReadyQueues(), KiSetPriorityThread(),     and NtYieldExecution().

// LIST_ENTRY KiProfileListHead 

  - Referenced by KeStartProfile(), and KiInitSystem().

LIST_ENTRY KiProfileSourceListHead 

  - Referenced by KeStartProfile(), KeStopProfile(), and KiInitSystem().

// LIST_ENTRY KiProcessOutSwapListHead 

  - Referenced by KeDetachProcess(), KeSwapProcessOrStack(), KeTerminateThread(),     KeUnstackDetachProcess(), KiInitSystem(), KiOutSwapKernelStacks(), and     KiOutSwapProcesses().

LIST_ENTRY KiProcessInSwapListHead 

  - Referenced by KeSwapProcessOrStack(), KiAttachProcess(), KiInitSystem(),      KiInSwapProcesses(), KiOutSwapProcesses(), and KiReadyThread().

 

LIST_ENTRY KiStackInSwapListHead 

  - Referenced by KeSwapProcessOrStack(), KiInitSystem(), KiInSwapKernelStacks(),     and KiReadyThread().

// LIST_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE] 

  - Referenced by KeCheckForTimer(), KeSetSystemTime(), KiInitSystem(),     KiInsertTimerTable(), KiTimerExpiration(), and VerifierKeInitializeTimerEx().

 

// LIST_ENTRY KiWaitInListHead 

  - Referenced by KiInitSystem(), and KiOutSwapKernelStacks().

LIST_ENTRY KiWaitOutListHead 

  - Referenced by KiInitSystem(), and KiOutSwapKernelStacks().

 

 

PART 2: Kernel Object of KPROCESS

LIST_ENTRY _KPROCESS::ThreadListHead     - Referenced by ExpGetProcessInformation(), KeDetachProcess(), KeFreezeAllThreads(),      KeTerminateThread(), KeThawAllThreads(), and KeUnstackDetachProcess().

 

LIST_ENTRY _KPROCESS::SwapListEntry 

  - Referenced by KeDetachProcess(), KeTerminateThread(), KeUnstackDetachProcess(),     KiOutSwapKernelStacks(), KiOutSwapProcesses(), and KiReadyThread().

 

LIST_ENTRY _KPROCESS::ReadyListHead 

  - Referenced by KiInSwapProcesses(), KiOutSwapProcesses(), and KiReadyThread().

 

PART 3:

/*------------------------- MmInitSystem -------------------------

- MmInitSystem启动两个线程: KeBalanceSetManager 和 KeSwapProcessOrStack;

- 平衡集管理器(balance set manager)

- 交换管理器(KeSwapProcessOrStack)

- 其实它还启动了MiModifiedPageWriter(将某些页面置入pagefile中)

-----------------------------------------------------------------*/ 01337         // 01338         // Start the modified page writer. 01339         // 01340 01341         InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL ); 01342 01343         if (!NT_SUCCESS(PsCreateSystemThread( 01344                         &ThreadHandle, 01345                         THREAD_ALL_ACCESS, 01346                         &ObjectAttributes, 01347                         0L, 01348                         NULL, 01349                         MiModifiedPageWriter, 01350                         NULL 01351                         ))) { 01352             return FALSE; 01353         } 01354         ZwClose (ThreadHandle); 01355 01356         // 01357         // Start the balance set manager. 01358         // 01359         // The balance set manager performs stack swapping and working 01360         // set management and requires two threads. 01361         // 01362 01363         KeInitializeEvent (&MmWorkingSetManagerEvent, 01364                            SynchronizationEvent, 01365                            FALSE); 01366 01367         InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL ); 01368 01369         if (!NT_SUCCESS(PsCreateSystemThread( 01370                         &ThreadHandle, 01371                         THREAD_ALL_ACCESS, 01372                         &ObjectAttributes, 01373                         0L, 01374                         NULL, 01375                         KeBalanceSetManager, 01376                         NULL 01377                         ))) { 01378 01379             return FALSE; 01380         } 01381         ZwClose (ThreadHandle); 01382 01383         if (!NT_SUCCESS(PsCreateSystemThread( 01384                         &ThreadHandle, 01385                         THREAD_ALL_ACCESS, 01386                         &ObjectAttributes, 01387                         0L, 01388                         NULL, 01389                         KeSwapProcessOrStack, 01390                         NULL 01391                         ))) { 01392 01393             return FALSE; 01394         }

 

 

/*---------------------- KeBalanceSetManager ---------------------

-  KeBalanceSetManager也一直循环着并等待着一个MmWorkingSetManagerEvent事件 (当内存低时调整工作集的大小)和另一个定时器.

-  定时器事件处理程序周期性地将KiStackOutSwapRequest设置为TRUE, 并且触发KiSwapEvent信号通知KeSwapProcessOrStack线程, KeSwapProcessOrStack线程 不得不将长时间等待某个东西的线程的内核堆栈交换出去.

-  KeBalanceSetManager也调用KiScanReadyQueues 来提高在就绪队列中线程(KiDispatcherReadyListHead数组)的优先级.

-  对于每一个提高了优先级的线程, KiReadyThread将会被调用, 所以马上将PRCB.NextThread设置为提高了优先级的线程也是很有可能的 (KiReadyThread 会抢占原先的NextThread).

-----------------------------------------------------------------*/

00141 VOID 00142 KeBalanceSetManager ( 00143     IN PVOID Context 00144     ) 00145 00146 /*++ 00147 00148 Routine Description: 00149 00150     This function is the startup code for the balance set manager. The 00151     balance set manager thread is created during system initialization 00152     and begins execution in this function. 00153 00154 Arguments: 00155 00156     Context - Supplies a pointer to an arbitrary data structure (NULL). 00157 00158 Return Value: 00159 00160     None. 00161 00162 --*/ 00163 00164 { 00165 00166     LARGE_INTEGER DueTime; 00167     KTIMER PeriodTimer; 00168     KIRQL OldIrql; 00169     ULONG StackScanPeriod; 00170     ULONG ExecutionTimeLimitPeriod; 00171     NTSTATUS Status; 00172     KWAIT_BLOCK WaitBlockArray[MaximumObject]; 00173     PVOID WaitObjects[MaximumObject]; 00174 00175     // 00176     // Raise the thread priority to the lowest realtime level. 00177     // 00178 00179     KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY); 00180 00181     // 00182     // Initialize the periodic timer, set it to expire one period from 00183     // now, and set the stack scan period. 00184     // 00185 00186     KeInitializeTimer(&PeriodTimer); 00187     DueTime.QuadPart = - PERIODIC_INTERVAL; 00188     KeSetTimer(&PeriodTimer, DueTime, NULL); 00189     StackScanPeriod = STACK_SCAN_PERIOD; 00190     ExecutionTimeLimitPeriod = EXECUTION_TIME_LIMITS_PERIOD; 00191     // 00192     // Compute the stack protect time based on the system size. 00193     // 00194 00195     if (MmQuerySystemSize() == MmSmallSystem) { 00196         KiStackProtectTime = SMALL_SYSTEM_STACK_PROTECT_TIME; 00197 00198     } else { 00199         KiStackProtectTime = STACK_PROTECT_TIME; 00200     } 00201 00202     // 00203     // Initialize the wait objects array. 00204     // 00205 00206     WaitObjects[TimerExpiration] = (PVOID)&PeriodTimer; 00207     WaitObjects[WorkingSetManagerEvent] = (PVOID)&MmWorkingSetManagerEvent; 00208 00209     // 00210     // Loop forever processing balance set manager events. 00211     // 00212 00213     do { 00214 00215         // 00216         // Wait for a memory management memory low event, a swap event, 00217         // or the expiration of the period timout rate that the balance 00218         // set manager runs at. 00219         // 00220 00221         Status = KeWaitForMultipleObjects(MaximumObject, 00222                                           &WaitObjects[0], 00223                                           WaitAny, 00224                                           Executive, 00225                                           KernelMode, 00226                                           FALSE, 00227                                           NULL, 00228                                           &WaitBlockArray[0]); 00229 00230         // 00231         // Switch on the wait status. 00232         // 00233 00234         switch (Status) { 00235 00236             // 00237             // Periodic timer expiration. 00238             // 00239 00240         case TimerExpiration: 00241 00242             // 00243             // Attempt to initiate outswaping of kernel stacks. 00244             // 00245 00246             StackScanPeriod -= 1; 00247             if (StackScanPeriod == 0) { 00248                 StackScanPeriod = STACK_SCAN_PERIOD; 00249                 KiLockDispatcherDatabase(&OldIrql); 00250                 if (KiStackOutSwapRequest == FALSE) { 00251                     KiStackOutSwapRequest = TRUE; 00252                     KiUnlockDispatcherDatabase(OldIrql); 00253                     KeSetEvent(&KiSwapEvent, 0, FALSE); 00254 00255                 } else { 00256                     KiUnlockDispatcherDatabase(OldIrql); 00257                 } 00258             } 00259 00260             // 00261             // Adjust the depth of lookaside lists. 00262             // 00263 00264             ExAdjustLookasideDepth(); 00265 00266             // 00267             // Scan ready queues and boost thread priorities as appropriate. 00268             // 00269 00270             KiScanReadyQueues(); 00271 00272             // 00273             // Execute the virtual memory working set manager. 00274             // 00275 00276             MmWorkingSetManager(); 00277 00278             // 00279             // Enforce execution time limits 00280             // 00281 00282             ExecutionTimeLimitPeriod -= 1; 00283             if (ExecutionTimeLimitPeriod == 0) { 00284                 ExecutionTimeLimitPeriod = EXECUTION_TIME_LIMITS_PERIOD; 00285                 PsEnforceExecutionTimeLimits(); 00286                 } 00287 00288             // 00289             // Set the timer to expire at the next periodic interval. 00290             // 00291 00292             KeSetTimer(&PeriodTimer, DueTime, NULL); 00293             break; 00294 00295             // 00296             // Working set manager event. 00297             // 00298 00299         case WorkingSetManagerEvent: 00300 00301             // 00302             // Call the working set manager to trim working sets. 00303             // 00304 00305             MmWorkingSetManager(); 00306             break; 00307 00308             // 00309             // Illegal return status. 00310             // 00311 00312         default: 00313             KdPrint(("BALMGR: Illegal wait status, %lx =/n", Status)); 00314             break; 00315         } 00316 00317     } while (TRUE); 00318     return; 00319 }

 

 

/*---------------------- KeSwapProcessOrStack ---------------------

-  将内核堆栈交换出去(由BOOLEAN KiStackOutSwapRequest指定) -  将进程交换出去 (需要交换出去的进程存放在KiProcessOutSwapListHead中) -  将进程交换进来  (需要交换出去的进程存放在KiProcessInSwapListHead中) -  将内核堆栈交换进来(需要交换进来的线程存放在KiStackInSwapListHead中).

-----------------------------------------------------------------*/

00321 VOID 00322 KeSwapProcessOrStack ( 00323     IN PVOID Context 00324     ) 00325 00326 /*++ 00327 00328 Routine Description: 00329 00330     This thread controls the swapping of processes and kernel stacks. The 00331     order of evaluation is: 00332 00333         Outswap kernel stacks 00334         Outswap processes 00335         Inswap processes 00336         Inswap kernel stacks 00337 00338 Arguments: 00339 00340     Context - Supplies a pointer to the routine context - not used. 00341 00342 Return Value: 00343 00344     None. 00345 00346 --*/ 00347 00348 { 00349 00350     KIRQL OldIrql; 00351     NTSTATUS Status; 00352 00353     // 00354     // Raise the thread priority to the lowest realtime level + 7 (i.e., 00355     // priority 23). 00356     // 00357 00358     KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY + 7); 00359 00360     // 00361     // Loop for ever processing swap events. 00362     // 00363 00364     do { 00365 00366         // 00367         // Wait for a swap event to occur. 00368         // 00369 00370         Status = KeWaitForSingleObject(&KiSwapEvent, 00371                                        Executive, 00372                                        KernelMode, 00373                                        FALSE, 00374                                        NULL); 00375 00376         // 00377         // Raise IRQL to dispatcher level and lock dispatcher database. 00378         // 00379 00380         KiLockDispatcherDatabase(&OldIrql); 00381 00382         // 00383         // Loop until all of the four possible actions cannot be initiated. 00384         // 00385 00386         do { 00387 00388             // 00389             // If a request has been made to out swap kernel stacks, then 00390             // attempt to outswap kernel stacks. Otherwise, if the process 00391             // out swap list is not empty, then initiate process outswapping. 00392             // Otherwise, if the process inswap list is not empty, then start 00393             // process inswapping. Otherwise, if the kernal stack inswap list 00394             // is not active, then initiate kernel stack inswapping. Otherwise, 00395             // no work is available. 00396             // 00397 00398             if (KiStackOutSwapRequest != FALSE) { 00399                 KiStackOutSwapRequest = FALSE; 00400                 KiOutSwapKernelStacks(OldIrql); 00401                 continue; 00402 00403             } else if (IsListEmpty(&KiProcessOutSwapListHead) == FALSE) { 00404                 KiOutSwapProcesses(OldIrql); 00405                 continue; 00406 00407             } else if (IsListEmpty(&KiProcessInSwapListHead) == FALSE) { 00408                 KiInSwapProcesses(OldIrql); 00409                 continue; 00410 00411             } else if (IsListEmpty(&KiStackInSwapListHead) == FALSE) { 00412                 KiInSwapKernelStacks(OldIrql); 00413                 continue; 00414 00415             } else { 00416                 break; 00417             } 00418         } while (TRUE); 00419 00420         // 00421         // Unlock the dispatcher database and lower IRQL to its previous 00422         // value. 00423         // 00424 00425         KiUnlockDispatcherDatabase(OldIrql); 00426     } while (TRUE); 00427     return; 00428 }

 

 

/*------------------------ KiSwapThread -------------------------

-----------------------------------------------------------------*/ ;++ ; ; VOID ; KiSwapThread ( ;    VOID ;    ) ; ; Routine Description: ; ;    This routine is called to select the next thread to run on the ;    current processor and to perform a context switch to the thread. ; ; Arguments: ; ;    None. ; ; Return Value: ; ;    Wait completion status (eax). ; ;--

cPublicFastCall KiSwapThread, 0 .fpo (0, 0, 0, 4, 1, 0)

; ; N.B. The following registers MUST be saved such that ebp is saved last. ;      This is done so the debugger can find the saved ebp for a thread ;      that is not currently in the running state. ;

        sub     esp, 4*4         mov     [esp+12], ebx           ; save registers         mov     [esp+8], esi            ;         mov     [esp+4], edi            ;         mov     [esp+0], ebp            ;

        mov     ebx, PCR[PcSelfPcr]     ; get address of PCR         mov     edx, [ebx].PcPrcbData.PbNextThread ; get next thread address         or      edx, edx                ; check if next thread selected         jnz     Swt140                  ; if nz, next thread selected

; ; Find the highest nibble in the ready summary that contains a set bit ; and left justify so the nibble is in bits <31:28> ;

        mov     ecx, 16                 ; set base bit number         mov     edi, _KiReadySummary    ; get ready summary         mov     esi, edi                ; copy ready summary         shr     esi, 16                 ; isolate bits <31:16> of summary         jnz     short Swt10             ; if nz, bits <31:16> are nonzero         xor     ecx, ecx                ; set base bit number         mov     esi, edi                ; set bits <15:0> of summary Swt10:  shr     esi, 8                  ; isolate bits <15:8> of low bits         jz      short Swt20             ; if z, bits <15:8> are zero         add     ecx, 8                  ; add offset to nonzero byte Swt20:  mov     esi, edi                ; isolate highest nonzero byte         shr     esi, cl                 ;         add     ecx, 3                  ; adjust to high bit of nibble         cmp     esi, 10h                ; check if high nibble nonzero         jb      short Swt30             ; if b, then high nibble is zero         add     ecx, 4                  ; compute ready queue priority Swt30:  mov     esi, ecx                ; left justify ready summary nibble         not     ecx                     ;         shl     edi, cl                 ;         or      edi, edi                ;

; ; If the next bit is set in the ready summary, then scan the corresponding ; dispatcher ready queue. ;

Swt40:  js      short Swt60             ; if s, queue contains an entry Swt50:  sub     esi, 1                  ; decrement ready queue priority         shl     edi, 1                  ; position next ready summary bit         jnz     short Swt40             ; if nz, more queues to scan

; ; If the next bit is set in the ready summary, then scan the corresponding ; dispatcher ready queue. ;

Swt40:  js      short Swt60             ; if s, queue contains an entry Swt50:  sub     esi, 1                  ; decrement ready queue priority         shl     edi, 1                  ; position next ready summary bit         jnz     short Swt40             ; if nz, more queues to scan

posted on 2007-08-23 17:28 垃圾一堆 阅读(2109) 评论(1)   编辑   收藏
href="http://blog.vckbase.com/windowssky/Services/Pingback.aspx" rel="pingback" />
Comments
垃圾一堆 Posted @ 2007-08-27 11:18

00188 typedef enum _KTHREAD_STATE { 00189     Initialized, 00190     Ready, 00191     Running, 00192     Standby, 00193     Terminated, 00194     Waiting, 00195     Transition 00196     } KTHREAD_STATE; //PS:Transition(转换状态)      处于此状态的线程的内核堆栈不在内存中;      Insert KiStackInSwapListHead 等待平衡集管理器 通知 交换管理器 进行换进动作;

//一般情况下线程处于等待状态,是因为等待的内核对象(当然是可等待对象含有DISPATCH_HEAD & WaitBlock)还未触发;  如果触发了,线程从等待状态 切换的到 准备状态;下面这几个函数实现了这个功能; /*------------------------   KeSetEvent --------------------------

-----------------------------------------------------------------*/

00343 KeSetEvent ( 00344     IN PRKEVENT Event, 00345     IN KPRIORITY Increment, 00346     IN BOOLEAN Wait 00347     ) 00348 00349 /*++ 00350 00351 Routine Description: 00352 00353     This function sets the signal state of an event object to Signaled 00354     and attempts to satisfy as many Waits as possible. The previous 00355     signal state of the event object is returned as the function value. 00356 00357 Arguments: 00358 00359     Event - Supplies a pointer to a dispatcher object of type event. 00360 00361     Increment - Supplies the priority increment that is to be applied 00362        if setting the event causes a Wait to be satisfied. 00363 00364     Wait - Supplies a boolean value that signifies whether the call to 00365        KePulseEvent will be immediately followed by a call to one of the 00366        kernel Wait functions. 00367 00368 Return Value: 00369 00370     The previous signal state of the event object. 00371 00372 --*/ 00373 00374 { 00375 00376     KIRQL OldIrql; 00377     LONG OldState; 00378     PRKTHREAD Thread; 00379     PRKWAIT_BLOCK WaitBlock; 00380 00381     ASSERT_EVENT(Event); 00382     ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL); 00383 00384     // 00385     // Collect call data. 00386     // 00387 00388 #if defined(_COLLECT_SET_EVENT_CALLDATA_) 00389 00390     RECORD_CALL_DATA(&KiSetEventCallData); 00391 00392 #endif 00393 00394     // 00395     // Raise IRQL to dispatcher level and lock dispatcher database. 00396     // 00397 00398     KiLockDispatcherDatabase(&OldIrql); 00399 00400     // 00401     // If the wait list is empty, then set the state of the event to signaled. 00402     // Otherwise, check if the wait can be satisfied immediately. 00403     // 00404 00405     OldState = Event->Header.SignalState; 00406     if (IsListEmpty(&Event->Header.WaitListHead) != FALSE) { 00407         Event->Header.SignalState = 1; 00408 00409     } else { 00410 00411         // 00412         // If the event is a notification event or the wait is not a wait any, 00413         // then set the state of the event to signaled and attempt to satisfy 00414         // as many waits as possible. Otherwise, the wait can be satisfied by 00415         // directly unwaiting the thread. 00416         // 00417 00418         WaitBlock = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, 00419                                       KWAIT_BLOCK, 00420                                       WaitListEntry); 00421 00422         if ((Event->Header.Type == NotificationEvent) || 00423             (WaitBlock->WaitType != WaitAny)) { 00424             if (OldState == 0) { 00425                 Event->Header.SignalState = 1; 00426                 KiWaitTest(Event, Increment); 00427             } 00428 00429         } else { 00430             KiUnwaitThread(WaitBlock->Thread, (NTSTATUS)WaitBlock->WaitKey, Increment); 00431         } 00432     } 00433 00434     // 00435     // If the value of the Wait argument is TRUE, then return to the 00436     // caller with IRQL raised and the dispatcher database locked. Else 00437     // release the dispatcher database lock and lower IRQL to its 00438     // previous value. 00439     // 00440 00441     if (Wait != FALSE) { 00442        Thread = KeGetCurrentThread(); 00443        Thread->WaitNext = Wait; 00444        Thread->WaitIrql = OldIrql; 00445 00446     } else { 00447        KiUnlockDispatcherDatabase(OldIrql); 00448     } 00449 00450     // 00451     // Return previous signal state of event object. 00452     // 00453 00454     return OldState; 00455 }

 

/*------------------------ KiUnwaitThread-------------------------

-----------------------------------------------------------------*/

00029 VOID 00030 FASTCALL 00031 KiUnwaitThread ( 00032     IN PRKTHREAD Thread, 00033     IN LONG_PTR WaitStatus, 00034     IN KPRIORITY Increment 00035     ) 00036 00037 /*++ 00038 00039 Routine Description: 00040 00041     This function unwaits a thread, sets the thread's wait completion status, 00042     calculates the thread's new priority, and readies the thread for execution. 00043 00044 Arguments: 00045 00046     Thread - Supplies a pointer to a dispatcher object of type thread. 00047 00048     WaitStatus - Supplies the wait completion status. 00049 00050     Increment - Supplies the priority increment that is to be applied to 00051         the thread's priority. 00052 00053 Return Value: 00054 00055     None. 00056 00057 --*/ 00058 00059 { 00060 00061     KPRIORITY NewPriority; 00062     PKPROCESS Process; 00063     PKQUEUE Queue; 00064     PKTIMER Timer; 00065     PRKWAIT_BLOCK WaitBlock; 00066 00067     // 00068     // Set wait completion status, remove wait blocks from object wait 00069     // lists, and remove thread from wait list. 00070     // 00071 00072     Thread->WaitStatus |= WaitStatus; 00073     WaitBlock = Thread->WaitBlockList; 00074     do { 00075         RemoveEntryList(&WaitBlock->WaitListEntry); 00076         WaitBlock = WaitBlock->NextWaitBlock; 00077     } while (WaitBlock != Thread->WaitBlockList); 00078 00079     RemoveEntryList(&Thread->WaitListEntry); 00080 00081     // 00082     // If thread timer is still active, then cancel thread timer. 00083     // 00084 00085     Timer = &Thread->Timer; 00086     if (Timer->Header.Inserted != FALSE) { 00087         KiRemoveTreeTimer(Timer); 00088     } 00089 00090     // 00091     // If the thread is processing a queue entry, then increment the 00092     // count of currently active threads. 00093     // 00094 00095     Queue = Thread->Queue; 00096     if (Queue != NULL) { 00097         Queue->CurrentCount += 1; 00098     } 00099 00100     // 00101     // If the thread runs at a realtime priority level, then reset the 00102     // thread quantum. Otherwise, compute the next thread priority and 00103     // charge the thread for the wait operation. 00104     // 00105 00106     Process = Thread->ApcState.Process; 00107     if (Thread->Priority < LOW_REALTIME_PRIORITY) { 00108         if ((Thread->PriorityDecrement == 0) && 00109             (Thread->DisableBoost == FALSE)) { 00110             NewPriority = Thread->BasePriority + Increment; 00111             if (((PEPROCESS)Process)->Vm.MemoryPriority == MEMORY_PRIORITY_FOREGROUND) { 00112                 NewPriority += PsPrioritySeperation; 00113             } 00114 00115             if (NewPriority > Thread->Priority) { 00116                 if (NewPriority >= LOW_REALTIME_PRIORITY) { 00117                     Thread->Priority = LOW_REALTIME_PRIORITY - 1; 00118 00119                 } else { 00120                     Thread->Priority = (SCHAR)NewPriority; 00121                 } 00122             } 00123         } 00124 00125         if (Thread->BasePriority >= TIME_CRITICAL_PRIORITY_BOUND) { 00126             Thread->Quantum = Process->ThreadQuantum; 00127 00128         } else { 00129             Thread->Quantum -= WAIT_QUANTUM_DECREMENT; 00130             if (Thread->Quantum <= 0) { 00131                 Thread->Quantum = Process->ThreadQuantum; 00132                 Thread->Priority -= (Thread->PriorityDecrement + 1); 00133                 if (Thread->Priority < Thread->BasePriority) { 00134                     Thread->Priority = Thread->BasePriority; 00135                 } 00136 00137                 Thread->PriorityDecrement = 0; 00138             } 00139         } 00140 00141     } else { 00142         Thread->Quantum = Process->ThreadQuantum; 00143     } 00144 00145     // 00146     // Reready the thread for execution. 00147     // 00148 00149     KiReadyThread(Thread); 00150     return; 00151 }

 

 

/*------------------------ KiReadyThread -------------------------

-----------------------------------------------------------------*/

00268 VOID 00269 FASTCALL 00270 KiReadyThread ( 00271     IN PRKTHREAD Thread 00272     ) 00273 00274 /*++ 00275 00276 Routine Description: 00277 00278     This function readies a thread for execution and attempts to immediately 00279     dispatch the thread for execution by preempting another lower priority 00280     thread. If a thread can be preempted, then the specified thread enters 00281     the standby state and the target processor is requested to dispatch. If 00282     another thread cannot be preempted, then the specified thread is inserted 00283     either at the head or tail of the dispatcher ready selected by its priority 00284     acccording to whether it was preempted or not. 00285 00286 Arguments: 00287 00288     Thread - Supplies a pointer to a dispatcher object of type thread. 00289 00290 Return Value: 00291 00292     None. 00293 00294 --*/ 00295 00296 { 00297 00298     PRKPRCB Prcb; 00299     BOOLEAN Preempted; 00300     KPRIORITY Priority; 00301     PRKPROCESS Process; 00302     ULONG Processor; 00303     KPRIORITY ThreadPriority; 00304     PRKTHREAD Thread1; 00305     KAFFINITY IdleSet; 00306 00307     // 00308     // Save value of thread's preempted flag, set thread preempted FALSE, 00309     // capture the thread priority, and set clear the read wait time. 00310     // 00311 00312     Preempted = Thread->Preempted; 00313     Thread->Preempted = FALSE; 00314     ThreadPriority = Thread->Priority; 00315     Thread->WaitTime = KiQueryLowTickCount(); 00316 00317     // 00318     // If the thread's process is not in memory, then insert the thread in 00319     // the process ready queue and inswap the process. 00320     // 00321 00322     Process = Thread->ApcState.Process; 00323     if (Process->State != ProcessInMemory) { 00324         Thread->State = Ready; 00325         Thread->ProcessReadyQueue = TRUE; 00326         InsertTailList(&Process->ReadyListHead, &Thread->WaitListEntry); 00327         if (Process->State == ProcessOutOfMemory) { 00328             Process->State = ProcessInTransition; 00329             InsertTailList(&KiProcessInSwapListHead, &Process->SwapListEntry); 00330             KiSwapEvent.Header.SignalState = 1; 00331             if (IsListEmpty(&KiSwapEvent.Header.WaitListHead) == FALSE) { 00332                 KiWaitTest(&KiSwapEvent, BALANCE_INCREMENT); 00333             } 00334         } 00335 00336         return; 00337 00338     } else if (Thread->KernelStackResident == FALSE) { 00339 00340         // 00341         // The thread's kernel stack is not resident. Increment the process 00342         // stack count, set the state of the thread to transition, insert 00343         // the thread in the kernel stack inswap list, and set the kernel 00344         // stack inswap event. 00345         // 00346 00347         Process->StackCount += 1; 00348         Thread->State = Transition; 00349         InsertTailList(&KiStackInSwapListHead, &Thread->WaitListEntry); 00350         KiSwapEvent.Header.SignalState = 1; 00351         if (IsListEmpty(&KiSwapEvent.Header.WaitListHead) == FALSE) { 00352             KiWaitTest(&KiSwapEvent, BALANCE_INCREMENT); 00353         } 00354 00355         return; 00356 00357     } else { 00358 00359         // 00360         // If there is an idle processor, then schedule the thread on an 00361         // idle processor giving preference to the processor the thread 00362         // last ran on. Otherwise, try to preempt either a thread in the 00363         // standby or running state. 00364         // 00365 00366 #if defined(NT_UP) 00367 00368         Prcb = KiProcessorBlock[0]; 00369         if (KiIdleSummary != 0) { 00370             KiIdleSummary = 0; 00371             KiIncrementSwitchCounter(IdleLast); 00372             Prcb->NextThread = Thread; 00373             Thread->State = Standby; 00374 00375 #else 00376 00377         IdleSet = KiIdleSummary & Thread->Affinity; 00378         if (IdleSet != 0) { 00379             Prcb = KeGetCurrentPrcb(); 00380             Processor = Thread->IdealProcessor; 00381             if ((IdleSet & (1 << Processor)) == 0) { 00382                 Processor = Thread->NextProcessor; 00383                 if ((IdleSet & (1 << Processor)) == 0) { 00384                     if ((IdleSet & Prcb->SetMember) == 0) { 00385                         FindFirstSetLeftMember(IdleSet, &Processor); 00386                         KiIncrementSwitchCounter(IdleAny); 00387 00388                     } else { 00389                         Processor = Prcb->Number; 00390                         KiIncrementSwitchCounter(IdleCurrent); 00391                     } 00392 00393                 } else { 00394                     KiIncrementSwitchCounter(IdleLast); 00395                 } 00396 00397             } else { 00398                 KiIncrementSwitchCounter(IdleIdeal); 00399             } 00400 00401             Thread->NextProcessor = (CCHAR)Processor; 00402             ClearMember(Processor, KiIdleSummary); 00403             KiProcessorBlock[Processor]->NextThread = Thread; 00404             Thread->State = Standby; 00405 00406             if ((PoSleepingSummary & (1 << Processor)) && 00407                  Processor != (ULONG) Prcb->Number) { 00408                 KiIpiSend(1 << Processor, IPI_DPC); 00409             } 00410 #endif 00411 00412             return; 00413 00414         } else { 00415 00416 #if !defined(NT_UP) 00417 00418             Processor = Thread->IdealProcessor; 00419             if ((Thread->Affinity & (1 << Processor)) == 0) { 00420                 Processor = Thread->NextProcessor; 00421                 if ((Thread->Affinity & (1 << Processor)) == 0) { 00422                     FindFirstSetLeftMember(Thread->Affinity, &Processor); 00423                 } 00424             } 00425 00426             Thread->NextProcessor = (CCHAR)Processor; 00427             Prcb = KiProcessorBlock[Processor]; 00428 00429 #endif 00430 00431             if (Prcb->NextThread != NULL) { 00432                 Thread1 = Prcb->NextThread; 00433                 if (ThreadPriority > Thread1->Priority) { 00434                     Thread1->Preempted = TRUE; 00435                     Prcb->NextThread = Thread; 00436                     Thread->State = Standby; 00437                     KiReadyThread(Thread1); 00438                     KiIncrementSwitchCounter(PreemptLast); 00439                     return; 00440                 } 00441 00442             } else { 00443                 Thread1 = Prcb->CurrentThread; 00444                 if (ThreadPriority > Thread1->Priority) { 00445                     Thread1->Preempted = TRUE; 00446                     Prcb->NextThread = Thread; 00447                     Thread->State = Standby; 00448                     KiRequestDispatchInterrupt(Thread->NextProcessor); 00449                     KiIncrementSwitchCounter(PreemptLast); 00450                     return; 00451                 } 00452             } 00453         } 00454     } 00455 00456     // 00457     // No thread can be preempted. Insert the thread in the dispatcher 00458     // queue selected by its priority. If the thread was preempted and 00459     // runs at a realtime priority level, then insert the thread at the 00460     // front of the queue. Else insert the thread at the tail of the queue. 00461     // 00462 00463     Thread->State = Ready; 00464     if (Preempted != FALSE) { 00465         InsertHeadList(&KiDispatcherReadyListHead[ThreadPriority], 00466                        &Thread->WaitListEntry); 00467 00468     } else { 00469         InsertTailList(&KiDispatcherReadyListHead[ThreadPriority], 00470                        &Thread->WaitListEntry); 00471     } 00472 00473     SetMember(ThreadPriority, KiReadySummary); 00474     return; 00475 }

# re: 线程调度的部分资料(乱)
Windows系统的线程调度 1. 线程调度的一般过程 一个线程在创建的时候,内核会为其创建一个内核对象,在该内核对象中有一个成员变量叫做上下文结构,其中存储的是CPU最后运行该线程时CPU寄存器的值,这样当该线程再次被调度运行的时候,CPU就读取上下文结构中的数据,实现继续对该线程执行。 大体的调度过程 阅读详情

相关推荐

linux线程调度策略

对于一个autogroup内的进程,其CPU时钟周期为autogroup(相对于其他autogroups)的nice值和进程的nice值(相对于其他进程)的产物(相反的,对于不同会话(如,不同的终端窗口,这些任务都绑定到不同的autogroups)中绑定了唯一的CPU的2个进程,修改一个会话中的进程的nice值不会影响其他会话中的进程的调度。nice值的取值范围根据UNIX系统的不同而不同。在当前的实现下,两个进程的nice差值中,每单位的nice差值对CFS调度的影响因子为1.25 (参见。

m0_74282605的博客 912

Windows内存隐藏技术初探

  Windows内存隐藏技术初探  NetRochttp://www.DbgTech.net/    最早看到Shadow Walker这种隐藏内存数据的技术的时间忘了,呵呵。大约是一年多或者两年以前吧。当时还只是提出了理论性的东西,没有人实现出来。前段时间搞NP玩的时候,对Themida和虚拟机深恶痛绝,遂想,干脆把内存数据隐藏得了,省得挂个钩子还得缩手缩脚

NetRoc的专栏 1750

有限元缺陷:剪切锁死

有限元缺陷:剪切锁死

wsxww11的博客 5191

KeSetSystemAffinityThread

ms文档上说明: KeSetSystemAffinityThread routine The KeSetSystemAffinityThread routine sets the system affinity of the current thread. Syntax C++ VOID KeSetSystemAffinityThread( _In_ KAFFINITY Affinity

qinqin772的博客 2110

DIY nA级源表:从架构到校准的完整实战指南

源表(SMU)是一种在输出或吸收电流的同时精确测量电压,或在输出或吸收电压的同时精确测量电流的仪器。其核心原理基于高精度DAC、ADC及低噪声IV转换电路,技术价值在于实现微电流的高分辨率测量。在传感器暗电流、MOS管亚阈值漏电等测试场景中,nA级源表不可或缺。然而,原厂设备价格高昂,DIY成为可行替代。本文聚焦低电流区间,详细拆解跨阻放大器设计、保护电路、PCB布局及固件校准,分享从选型到实测的完整经验,助你打造一台满足10nA-10mA测试需求的源表。

weixin_29165465的博客 288

CANoe: Panel的上位机控制方法

本文介绍了不同于IG的报文控制方法,实现了Panel面板的控制模式。

Jonsnow3zz的博客 1410

隐藏进程检测

 隐藏进程检测User Mode下的隐藏进程检测我们先来看一些简单的方法,这些方法可以用在ring3下,用不着驱动。检测的原理是每一个进程活动时都会暴露一些痕迹,可以通过这些痕迹检测到它们。这些痕迹包括打开的句柄、窗口和创建的系统对象。针对类似的检测方法来实现进程隐藏并不困难,但需要考虑进程工作时可能暴露出的所有迹象。目前还没有一个公开的rootkit做到了这一点(遗憾的是私有版本我也还没见到)。

Tommy(凌飞)的专栏 3626

山东大学软件工程应用与实践——GMSSL开源库(六)——SM9密钥交换协议

2021SC@SDUSC 文章目录基本概念符号及辅助算法SM9密钥交换协议 基本概念 1976年,Diffie和Hellman在其题为《密码学的新方向》的论文中首次给出了公钥密码学的定义,并提出了Diffie-Hellman密钥交换算法。该算法解决了对称密码体制中的密钥分发问题,使得通信双方可以通过公开信道安全地交换共享密钥。 使用SM9通信的双方通过对方的标识和自身的私钥,经过两次或者可选的三次信息传递过程,计算获取一个由双方共同决定的共享秘密密钥。该密钥可以作为对称密码算法的会话密钥,其中可选步骤用来实

m0_51588039的博客 1988

KPRCB结构之ReadySummary和DispatcherReadyListHead

请参考 _KTHREAD *__fastcall KiSelectReadyThread(ULONG LowPriority, _KPRCB *Prcb)

weixin_43751677的博客 423

vasp计算练习1-Si

si的vasp训练流程

qq_41074165的博客 3302

大模型应用开发面试全流程实录:RAG、上下文工程与多Agent协作技术深度解析

Transformer 依靠多头自注意力和位置编码实现高效序列建模。Prompt Engineering包含多种设计思路,如 Zero-shot、Few-shot、Chain-of-thought,提升模型泛化和推理。Token 和上下文窗口直接影响模型性能与成本,选择需结合实际业务场景(如客服对话需长窗口)。Embedding 技术是 RAG 的基础,决定了语义检索效果。向量数据库如 FAISS、Milvus等分别适用于本地/分布式检索。

m0_52114506的博客 829

Windows Internals学习:Windows 工作集管理(Working Set Management)详解

事件名称含义说明提交量(commit charge)接近最大提交限制时被设置,说明内存使用非常高,物理内存和分页文件里几乎没有空间了,操作系统也无法继续增大分页文件当空闲物理内存数量超过设定阈值时被设置当非分页池数量超过设定阈值时被设置当分页池数量超过设定阈值时被设置提交量相对于当前提交限制较低时被设置,说明内存使用很低,物理内存或分页文件里还有大量空间当空闲物理内存数量低于设定阈值时被设置当空闲非分页池数量低于设定阈值时被设置当空闲分页池数量低于设定阈值时被设置。

虾球 289

Arduino安装图文教程:小白也能轻松上手

手把手带你完成Arduino安装全过程,无论你是编程新手还是硬件小白,都能快速搭建开发环境。结合arduino安装教程与实操步骤,避开常见错误,让创作即刻启程。

weixin_35509395的博客 1107

Java多线程实现之线程调度详解

Java多线程中线程调度是一个核心概念,它决定了线程如何获得CPU资源并执行。合理的线程调度策略能够充分发挥多核处理器的性能,提高程序的执行效率。本文我将深入探讨Java线程调度的原理、机制以及相关的API,带你更好地理解和控制线程的执行

aa_hdkf_vg的博客 1202

【WRF-Urban】使用 CGLC-MODIS-LCZ_100m 数据集运行 WRF 时的城市参数化问题

【WRF-Urban】使用 CGLC-MODIS-LCZ_100m 数据集运行 WRF 时的城市参数化问题

WW、forever的博客 714

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Zephyr线程调度

虽然用户可以创建多个线程来并行执行相关任务,但这些任务并不是真的在同时执行。对于某一个CPU而言,它只能串行执行指令。正因为如此,才有了调度程序。调度程序是Zephyr的一部分,它基于相关的调度算法,在重新调度点确定允许执行哪个线程(即使用 CPU 时间)。

lihongjiehit的专栏 975

贝叶斯统计 [韦来生编]

贝叶斯(Bayes)统计是近几十年来迅速发展起来的数理统计的一个重要分支。贝叶斯方法与经典统计方法的主要不同之处是进行统计推断时除了利用样本信息外,还要利用参数的先验信息,因此可以提高统计推断或统计决策的效果。它在经济、金融、生物、医学、自然科学和社会科学等许多领域具有广泛的应用。贝叶斯方法的研究已渗透到了统计学的几乎所有领域。作者在给中国科学技术大学概率论与数理统计专业本科生开设的“数理统计”课程中有一章专门讲授“贝叶斯方法和统计决策理论”,近十年来也给中国科学技术大学概率统计专业研究生开设过几次“贝叶斯分析”课。本书是在对过去讲稿的内容作了适当的增减和调整的基础上完成的。  本书共分六章。第1章是绪论,介绍了贝叶斯统计的若干基本概念,同时对必要的数理统计的基础知识有重点地作了回顾。第二章介绍了确定先验分布的若干可供选择的方法。第三章介绍了几类常见统计模型参数的后验分布的主要结果和计算方法。第四章和第五章分别介绍了“贝叶斯统计推断”和“贝叶斯统计决策”的内容。第六章介绍了贝叶斯统计计算的若干方法,包括蒙特卡洛方法和马尔可夫链蒙特卡洛(MCMC)方法以及相关统计软件的简介。本书的每一章附右大量的例题和习题,书末附有常用的几个表格和部分习题解答供读者查用。  大约可在54学时内讲授本书的第1章至第六章的主要内容,教师可根据学时需要选讲本书第1章至第六章的部分内容。书中标“*”号的章节可略去不讲,留给读者作为阅读材料。第六章例题中的R代码和部分例题的数据文件等可从作者个人主页下载。  作者在编写本书的过程中参考了J.O.Berger教授的《统计决策论及贝叶斯分析》和茆诗松教授编写的《贝叶斯统计》等书中的一些内容,以及《贝叶斯分析》一书中由张伟平博士编写的有关贝叶斯统计计算的一些内容。在此表示衷心感谢。  本书编写准备过程中,中国科学技术大学统计与金融系的几个研究生帮助完成了本书部分中文的录入和排版,作者对他们的辛勤工作表示真诚的感谢。高等教育出版社为本书的出版给予了大力支持。在此一并致谢。

多线程--线程调度

Java线程调度是操作系统或Java虚拟机(JVM)决定哪个线程执行的过程,是处理程序中多个线程执行顺序的核心部分。

殊途的博客 1837

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

关于Nachos的线程调度实验

我是ZK老师铁粉!!!

m0_72893325的博客 1058

linux 线程的调度策略

调度策略,可分为实时线程调度策略和非实时线程调度策略包括 SCHED_OTHER(正常、非实时)、SCHED_RR(实时、轮 转法)和SCHED_FIFO(实时、先入先出)三种,缺省为 SCHED_OTHER,后两种调度策略仅对超级用户有效。

m0_65731372的博客 4825

线程是如何被调度的?

不过,线程优先级并不是太靠谱,原因是Java的线程是通过映射到系统的原生线程上来实现的,所以线程调度最终还是取决于操作系统,虽然现在很多操作系统都提供线程优先级的概念,但是并不见得能与Java线程的优先级——对应。在Java的多线程程序中,为保证所有线程的执行能按照一定的规则执行,M实现了一个线程调度器,它定义了线程调度模型,对于CPU运算的分配都进行了规定,按照这些特定的机制为多个线程分配CPU的使用权。在这种实现线程调度的方式下,线程的执行时间是系统可控的,也不会有一个线程导致整个进程阻塞的问题。

weixin_51291483的博客 812

cuda 线程调度

硬件描述 从硬件上看,一块显卡的最小单元是GPU核(或者叫做Stream Processor),所有核心平均分配在多个SM中,而多个SM共同构成整块显卡的核心。比如RTX2070有36个Streaming Multiprocessors,而每个SM有64个CUDA Cores,RTX2070具有36*64=2304个CUDA Cores。 软件描述 thread,block,grid,war...

doublewei的专栏 2741

线程调度为什么比进程调度更少开销?

线程调度为什么比进程调度更少开销? 在对比进程调度与线程调度的开销前,我们需要明白两点: 进程与线程的差异 任务调度的开销 进程与线程的差异 我们首先要明白,线程和进程有什么关系?从概念上来讲,线程是进程的一部分,只是任务调度相关的部分,所以我们才说,“线程是调度的最小单位”。进程拥有着资源,这些资源不属于某一个特定线程,因为所有线程共享进程拥有的资源,所以我们才说,“进程是资源分配的最小单位...

GMPY_Tiger的博客 5683

RT_Thread——(二)线程调度与管理

RTT

Lxy_meteor的博客 2707

nachos lab2-线程调度

总体概述本次lab的主要内容是扩展线程调度算法,实现基于优先级的抢占式调度算法我认为,本次lab的关键在于理解Timer、Scheduler和Interrupt之间的关系,从而理解线程之间是如何进行调度的 任务完成情况 Exercise 1 –> Y Exercise 2 –> Y Exercise 3 –> Y Challenge 1 –> Y 具体完成情况如下所示:Exercise 1 调研

dsbwyx's blog 5839

线程调度相关讨论

在Python和Java中的作用完全不同,我们这里并没有明确指出我们讨论的是哪一个。当然了,依照问题提出的场景,我们可以确定这个问题更准确的版本是——在用Python写的爬虫中,如果我不使用。那对于发生IO操作/远程调用是否会自动进入阻塞状态这个问题来说,答案是只要你使用了线程,就会在该线程发生IO操作/远程调用时自动进入阻塞状态,也即会自动进行线程调度。由于这是一个比较复杂的问题,而且撰写这篇文章的时候也比较晚了(2024年10月11日星期五02:59),所以这部分是待补充状态。那就是在Python中。

2402_85491806的博客 1165

linux线程详解:线程概念、线程调度、线程安全、线程模型

(1)线程的组成:线程ID、当前指令指针(PC)、寄存器集合、堆栈;(2)一个进程包含一个或者多个线程,其中进程的大部分资源(代码段、数据段、堆段、打开文件/信号等)都是线程间共享的,线程会保留一部分私有数据(寄存器、栈);

weixin_42031299的博客 3584
上一篇: Recognizer & FS & Filter
下一篇: shellcode 之 JMP ESP 与 JMP EBX
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值