441 void NThread::Diverted() |
441 void NThread::Diverted() |
442 // |
442 // |
443 // This function is called in the context of a thread that is being diverted. |
443 // This function is called in the context of a thread that is being diverted. |
444 // This can be for either of two reasons: if iDivertFn has been set, that |
444 // This can be for either of two reasons: if iDivertFn has been set, that |
445 // function will be called and is not expected to return i.e. it should force |
445 // function will be called and is not expected to return i.e. it should force |
446 // the thread to exit. Otherwise, the thread will make a null trip through the |
446 // the thread to exit (in this case, the thread may already be in the kernel, |
447 // kernel, causing it to run pending user-mode callbacks on the way out. |
447 // but only at a place where it's safe for it to be killed). Otherwise, the |
|
448 // thread must be in user mode, and it's forced to make a null trip through |
|
449 // the kernel, causing it to run pending user-mode callbacks on the way out. |
448 // |
450 // |
449 // On entry, the kernel is locked and interrupts enabled |
451 // On entry, the kernel is locked and interrupts enabled |
450 // |
452 // |
451 { |
453 { |
452 NThread& me = *static_cast<NThread*>(TheScheduler.iCurrentThread); |
454 NThread& me = *static_cast<NThread*>(TheScheduler.iCurrentThread); |
453 __NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 1); |
455 __NK_ASSERT_ALWAYS(TheScheduler.iKernCSLocked == 1); |
454 __NK_ASSERT_ALWAYS(me.iInKernel == 0); |
|
455 __NK_ASSERT_ALWAYS(me.iDiverting); |
456 __NK_ASSERT_ALWAYS(me.iDiverting); |
456 NThread::TDivert divertFn = me.iDivertFn; |
457 NThread::TDivert divertFn = me.iDivertFn; |
457 me.iDivertFn = NULL; |
458 me.iDivertFn = NULL; |
458 me.iDivertReturn = NULL; |
459 me.iDivertReturn = NULL; |
459 me.iDiverting = EFalse; |
460 me.iDiverting = EFalse; |