информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Все любят медСтрашный баг в WindowsЗа кого нас держат?
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
вот NtSetInformationThread ее и вызыват (см внутри) 11.05.05 16:03  Число просмотров: 6688
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
NTSTATUS
NtSetInformationThread(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength
)

/*++

Routine Description:

This function sets the state of a thread object.

Arguments:

ThreadHandle - Supplies a handle to a thread object.

ThreadInformationClass - Supplies the class of information being
set.

ThreadInformation - Supplies a pointer to a record that contains the
information to set.

ThreadInformationLength - Supplies the length of the record that contains
the information to set.

Return Value:

TBS

--*/

{
PEEVENT_PAIR EventPair;
HANDLE EventPairHandle;
PETHREAD Thread;
PEPROCESS Process;
KPROCESSOR_MODE PreviousMode;
NTSTATUS st;
KAFFINITY Affinity, AffinityWithMasks;
ULONG_PTR BigAffinity;
KPRIORITY Priority;
LONG BasePriority;
ULONG TlsIndex;
PVOID TlsArrayAddress;
PVOID Win32StartAddressValue;
ULONG ProbeAlignment;
BOOLEAN EnableAlignmentFaultFixup;
ULONG IdealProcessor;
ULONG DisableBoost;
PVOID *ExpansionSlots;
HANDLE ImpersonationTokenHandle;
BOOLEAN HasPrivilege;

PAGED_CODE();

//
// Get previous processor mode and probe input argument if necessary.
//

PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode) {
try {

switch (ThreadInformationClass) {

case ThreadPriority :
ProbeAlignment = sizeof(KPRIORITY);
break;
case ThreadAffinityMask :
case ThreadQuerySetWin32StartAddress :
ProbeAlignment = sizeof (ULONG_PTR);
break;
case ThreadEnableAlignmentFaultFixup :
ProbeAlignment = sizeof (BOOLEAN);
break;
default :
ProbeAlignment = sizeof(ULONG);
}

ProbeForRead(
ThreadInformation,
ThreadInformationLength,
ProbeAlignment
);
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
}

//
// Check argument validity.
//

switch ( ThreadInformationClass ) {

case ThreadPriority:

if ( ThreadInformationLength != sizeof(KPRIORITY) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
Priority = *(KPRIORITY *)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

if ( Priority > HIGH_PRIORITY|
Priority <= LOW_PRIORITY ) {

return STATUS_INVALID_PARAMETER;
}

if ( Priority >= LOW_REALTIME_PRIORITY ) {

//
// Increasing the priority of a thread beyond
// LOW_REALTIME_PRIORITY is a privileged operation.
//

HasPrivilege = SeCheckPrivilegedObject(
SeIncreaseBasePriorityPrivilege,
ThreadHandle,
THREAD_SET_INFORMATION,
PreviousMode
);

if (!HasPrivilege) {
return STATUS_PRIVILEGE_NOT_HELD;
}
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Process = THREAD_TO_PROCESS(Thread);

KeSetPriorityThread(&Thread->Tcb,Priority);

ObDereferenceObject(Thread);

return STATUS_SUCCESS;

case ThreadBasePriority:

if ( ThreadInformationLength != sizeof(LONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
BasePriority = *(PLONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}
Process = THREAD_TO_PROCESS(Thread);


if ( BasePriority > THREAD_BASE_PRIORITY_MAX|
BasePriority < THREAD_BASE_PRIORITY_MIN ) {
if ( BasePriority == THREAD_BASE_PRIORITY_LOWRT+1|
BasePriority == THREAD_BASE_PRIORITY_IDLE-1 ) {
;
}
else {

//
// Allow csrss, or realtime processes to select any
// priority
//

if ( PsGetCurrentProcess() == ExpDefaultErrorPortProcess|
Process->PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME ){
;
}
else {
ObDereferenceObject(Thread);
return STATUS_INVALID_PARAMETER;
}
}
}

//
// If the thread is running within a job object, and the job
// object has a priority class limit, do not allow
// priority adjustments that raise the thread's priority, unless
// the priority class is realtime
//

if ( Process->Job && (Process->Job->LimitFlags & JOB_OBJECT_LIMIT_PRIORITY_CLASS) ) {
if ( Process->PriorityClass != PROCESS_PRIORITY_CLASS_REALTIME ){
if ( BasePriority > 0 ) {
ObDereferenceObject(Thread);
return STATUS_SUCCESS;
}
}
}

KeSetBasePriorityThread(&Thread->Tcb,BasePriority);

ObDereferenceObject(Thread);

return STATUS_SUCCESS;

case ThreadEnableAlignmentFaultFixup:

if ( ThreadInformationLength != sizeof(BOOLEAN) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
EnableAlignmentFaultFixup = *(PBOOLEAN)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

KeSetAutoAlignmentThread( &(Thread->Tcb), EnableAlignmentFaultFixup );

ObDereferenceObject(Thread);

return STATUS_SUCCESS;

case ThreadAffinityMask:

if ( ThreadInformationLength != sizeof(ULONG_PTR) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
BigAffinity = *(ULONG_PTR *) ThreadInformation;
Affinity = (KAFFINITY) BigAffinity;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

if ( !Affinity ) {

return STATUS_INVALID_PARAMETER;

}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Process = THREAD_TO_PROCESS(Thread);

//
// the following allows this api to properly if
// called while the exiting process is blocked holding the
// createdeletelock. This can happen during debugger/server
// lpc transactions that occur in pspexitthread
//

st = PsLockProcess(Process,PreviousMode,PsLockPollOnTimeout);

if ( st != STATUS_SUCCESS ) {
ObDereferenceObject(Thread);
return STATUS_PROCESS_IS_TERMINATING;
}

AffinityWithMasks = Affinity & Process->Pcb.Affinity;

if ( AffinityWithMasks != Affinity ) {

st = STATUS_INVALID_PARAMETER;

} else {

KeSetAffinityThread(
&Thread->Tcb,
AffinityWithMasks
);
st = STATUS_SUCCESS;
}

PsUnlockProcess(Process);

ObDereferenceObject(Thread);

return st;

case ThreadImpersonationToken:


if ( ThreadInformationLength != sizeof(HANDLE) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
ImpersonationTokenHandle = *(PHANDLE) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}


st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_THREAD_TOKEN,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

//
// Check for proper access to (and type of) the token, and assign
// it as the thread's impersonation token.
//

st = PsAssignImpersonationToken( Thread, ImpersonationTokenHandle );


ObDereferenceObject(Thread);

return st;

case ThreadQuerySetWin32StartAddress:
if ( ThreadInformationLength != sizeof(ULONG_PTR) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
Win32StartAddressValue = *(PVOID *) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}


st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Thread->Win32StartAddress = (PVOID)Win32StartAddressValue;
ObDereferenceObject(Thread);

return st;


case ThreadIdealProcessor:

if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
IdealProcessor = *(PULONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

if ( IdealProcessor > MAXIMUM_PROCESSORS ) {
return STATUS_INVALID_PARAMETER;
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

//
// this is sort of a slimey way of returning info from this set only
// api
//

st = (NTSTATUS)KeSetIdealProcessorThread(&Thread->Tcb,(CCHAR)IdealProcessor);

ObDereferenceObject(Thread);

return st;


case ThreadPriorityBoost:
if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
DisableBoost = *(PULONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

KeSetDisableBoostThread(&Thread->Tcb,DisableBoost ? TRUE : FALSE);

ObDereferenceObject(Thread);

return st;

case ThreadZeroTlsCell:
if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
TlsIndex = *(PULONG) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

if ( Thread != PsGetCurrentThread() ) {
ObDereferenceObject( Thread );
return STATUS_INVALID_PARAMETER;
}
{
NTSTATUS xst;
PTEB Teb;
PLIST_ENTRY Next;
PETHREAD OriginalThread;

OriginalThread = Thread;

Process = THREAD_TO_PROCESS(Thread);

//
// the following allows this api to properly if
// called while the exiting process is blocked holding the
// createdeletelock. This can happen during debugger/server
// lpc transactions that occur in pspexitthread
//

xst = PsLockProcess(Process,PreviousMode,PsLockPollOnTimeout);

if ( xst != STATUS_SUCCESS ) {
ObDereferenceObject( OriginalThread );
return STATUS_PROCESS_IS_TERMINATING;
}

// The 32bit TEB needs to be set if this is a WOW64 process on a 64BIT system.
// This code isn't 100% correct since threads have a conversion state where they
// are chaning from 64 to 32 and they don't have a TEB32 yet. Fortunatly, the slots
// will be zero when the thread is created so no damage is done by not clearing it here.

// Note that the test for the process type is inside the inner loop. This
// is bad programming, but this function is hardly time constrained and
// fixing this with complex macros would not be worth it due to the loss of clairity.

Next = Process->ThreadListHead.Flink;

while ( Next != &Process->ThreadListHead) {

Thread = (PETHREAD)(CONTAINING_RECORD(Next,ETHREAD,ThreadListEntry));
if ( !IS_SYSTEM_THREAD(Thread) ) {
if ( Thread->Tcb.Teb ) {
Teb = (PTEB)Thread->Tcb.Teb;

if ( TlsIndex > TLS_MINIMUM_AVAILABLE-1 ) {
if ( TlsIndex < (TLS_MINIMUM_AVAILABLE+TLS_EXPANSION_SLOTS) - 1 ) {
//
// This is an expansion slot, so see if the thread
// has an expansion cell
//
try {
#if defined(_WIN64)
if (Process->Wow64Process) { //Wow64 process.
PTEB32 Teb32;
PLONG ExpansionSlots32;

Teb32 = WOW64_GET_TEB32(Teb); //No probing needed on regular TEB.
if (Teb32) {
ExpansionSlots32 = ULongToPtr(ProbeAndReadLong(&(Teb32->TlsExpansionSlots)));
if (ExpansionSlots32) {
ProbeAndWriteLong(ExpansionSlots32 + TlsIndex - TLS_MINIMUM_AVAILABLE, 0);
}
}
}
else
#endif
{
ExpansionSlots = Teb->TlsExpansionSlots;
ProbeForRead(ExpansionSlots,TLS_EXPANSION_SLOTS*4,8);
if ( ExpansionSlots ) {
ExpansionSlots[TlsIndex-TLS_MINIMUM_AVAILABLE] = 0;
}

}
}
except(EXCEPTION_EXECUTE_HANDLER) {
;
}
}
}
else {
try {
#if defined(_WIN64)
if (Process->Wow64Process) { //wow64 process
PTEB32 Teb32;

Teb32 = WOW64_GET_TEB32(Teb); //No probing needed on regular TEB.
if(Teb32) {
ProbeAndWriteLong(Teb32->TlsSlots + TlsIndex, 0);
}
}
else
#endif
{
Teb->TlsSlots[TlsIndex] = NULL;
}
}
except(EXCEPTION_EXECUTE_HANDLER) {
;
}
}

}
}
Next = Next->Flink;
}

PsUnlockProcess(Process);

ObDereferenceObject(OriginalThread);

}
return st;
break;

case ThreadSetTlsArrayAddress:
if ( ThreadInformationLength != sizeof(PVOID) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
TlsArrayAddress = *(PVOID *)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Thread->Tcb.TlsArray = TlsArrayAddress;

#if definedMIPS

if (Thread == PsGetCurrentThread()) {
PCR->TlsArray = TlsArrayAddress;
}

#endif

ObDereferenceObject(Thread);

return st;
break;

case ThreadHideFromDebugger:
if ( ThreadInformationLength != 0 ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Thread->HideFromDebugger = TRUE;

ObDereferenceObject(Thread);

return st;
break;

default:
return STATUS_INVALID_INFO_CLASS;
}
}


+ к этому описалово к
NTSTATUS
PsLockProcess(
IN PEPROCESS Process,
IN KPROCESSOR_MODE WaitMode,
IN PSLOCKPROCESSMODE LockMode
)
/*++

Routine Description:

This function is used to lock the process from create/delete and to
freeze threads from entering/exiting the process.

Arguments:

Process - Pointer to the process to lock

WaitMode - Supplies the processor mode to issue the wait under

LockMode - The type of lock to attempt

PsLockPollOnTimeout - Use a timeout and poll for the lock
bailing if the process exits.

PsLockReturnTimeout - Do not poll, just timeout wait and
return if you can not get the lock.

PsLockWaitForever - Wait without a timeout


Return Value:

STATUS_SUCCESS - You got the lock, you must call PsUnlocProcess later on

STATUS_TIMEOUT - You requested PsLockReturnTimeout, and the lock was not available

STATUS_PROCESS_IS_TERMINATING - The process you are trying to lock is terminating

--*/
<programming>
Вопрос по SetThreadAffinityMask 10.05.05 22:39  
Автор: Killer{R} <Dmitry> Статус: Elderman
Отредактировано 11.05.05 14:22  Количество правок: 2
<"чистая" ссылка>
DWORD dw=SetThreadAffinityMask(GetCurrentThread(),1);
//---
//кусок кода
//---
SetThreadAffinityMask(GetCurrentThread(),dw);

Гарантирует ли такая обертка что кусок кода будет исполняться исключительно только на первом процессоре? Или всеже лучше вынести кусок кода в отдельный поток и вызывать его на исполнение через ивенты?
Ядро не ковырял, но в MSDN вроде говорится, что установка Affinity для планировщика указывает только предпочтение, т.е. в каких-то одному ему ведомых случаях, он может исполнить "кусок кода" и на другом процессоре. 11.05.05 07:53  
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка>
Да вроде жестко указывает выполнять на определенном и баста... 11.05.05 11:33  
Автор: IgorR <Igor Razin> Статус: Member
<"чистая" ссылка>
Да вроде жестко указывает выполнять на определенном и баста. А предпочтительный указывается с помощью SetThreadIdealProcessor.
Ага. Указывается. Интересно как это реализовано - поток... 11.05.05 13:20  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
> Да вроде жестко указывает выполнять на определенном и
> баста.
Ага. Указывается. Интересно как это реализовано - поток приостанавливается, меняется его AffinityMask и он планировщиком заносится на исполнение на нужном процессоре, или просто меняется маска и поток перейдет на тот процессор только при следующем плановом переключении контекста?
вот что накопал в сырцах винды 11.05.05 14:16  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
KAFFINITY
KeSetAffinityThread (
IN PKTHREAD Thread,
IN KAFFINITY Affinity
)

/*++

Routine Description:

This function sets the affinity of a specified thread to a new
value. If the new affinity is not a proper subset of the parent
process affinity, or is null, then an error condition is raised.
If the specified thread is running on, or about to run on, a
processor for which it is no longer able to run, then the target
processor is rescheduled. If the specified thread is in a ready
state and is not in the parent process ready queue, then it is
rereadied to reevaluate any additional processors it may run on.

Arguments:

Thread - Supplies a pointer to a dispatcher object of type thread.

Affinity - Supplies the new of set of processors on which the thread
can run.

Return Value:

The previous affinity of the specified thread.

--*/

{

KAFFINITY OldAffinity;
KIRQL OldIrql;
PKPRCB Prcb;
PKPROCESS Process;
ULONG Processor;
KPRIORITY ThreadPriority;
PRKTHREAD Thread1;

ASSERT_THREAD(Thread);
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);

//
// Raise IRQL to dispatcher level and lock dispatcher database.
//

KiLockDispatcherDatabase(&OldIrql);

//
// Capture the current affinity of the specified thread and get address
// of parent process object;
//

OldAffinity = Thread->UserAffinity;
Process = Thread->ApcStatePointer[0]->Process;

//
// If new affinity is not a proper subset of the parent process affinity,
// or the new affinity is null, then bugcheck.
//

if (((Affinity & Process->Affinity) != (Affinity))|(!Affinity)) {
KeBugCheck(INVALID_AFFINITY_SET);
}

//
// Set the thread user affinity to the specified value.
//
// If the thread is not current executing with system affinity active,
// then set the thread current affinity and switch on the thread state.
//

Thread->UserAffinity = Affinity;
if (Thread->SystemAffinityActive == FALSE) {
Thread->Affinity = Affinity;
switch (Thread->State) {

//
// Ready State.
//
// If the thread is not in the process ready queue, then remove
// it from its current dispatcher ready queue and reready it for
// execution.
//

case Ready:
if (Thread->ProcessReadyQueue == FALSE) {
RemoveEntryList(&Thread->WaitListEntry);
ThreadPriority = Thread->Priority;
if (IsListEmpty(&KiDispatcherReadyListHead[ThreadPriority]) != FALSE) {
ClearMember(ThreadPriority, KiReadySummary);
}

KiReadyThread(Thread);
}

break;

//
// Standby State.
//
// If the target processor is not in the new affinity set, then
// set the next thread to null for the target processor, select
// a new thread to run on the target processor, and reready the
// thread for execution.
//

case Standby:
Processor = Thread->NextProcessor;
Prcb = KiProcessorBlock[Processor];
if ((Prcb->SetMember & Affinity) == 0) {
Prcb->NextThread = NULL;
Thread1 = KiSelectNextThread(Thread);
Thread1->State = Standby;
Prcb->NextThread = Thread1;
KiReadyThread(Thread);
}

break;

//
// Running State.
//
// If the target processor is not in the new affinity set and
// another thread has not already been selected for execution
// on the target processor, then select a new thread for the
// target processor, and cause the target processor to be
// redispatched.
//

case Running:
Processor = Thread->NextProcessor;
Prcb = KiProcessorBlock[Processor];
if (((Prcb->SetMember & Affinity) == 0) &&
(Prcb->NextThread == NULL)) {
Thread1 = KiSelectNextThread(Thread);
Thread1->State = Standby;
Prcb->NextThread = Thread1;
KiRequestDispatchInterrupt(Processor);
}

break;

//
// Initialized, Terminated, Waiting, Transition case - For these
// states it is sufficient to just set the new thread affinity.
//

default:
break;
}
}

//
// Unlock dispatcher database, lower IRQL to its previous value, and
// return the previous user affinity.
//

KiUnlockDispatcherDatabase(OldIrql);
return OldAffinity;
}


я так понимаю мои подозрения оправдались (см. case Running) и возможна ситуация когда поток будет еще некоторое время исполняться на текущем процессоре. Или я чтото пропустил/не так понял?
Исходя из кода похоже на то. Хотя Соломон/Руссинович пишут: 11.05.05 18:17  
Автор: IgorR <Igor Razin> Статус: Member
<"чистая" ссылка>
> я так понимаю мои подозрения оправдались (см. case Running)
> и возможна ситуация когда поток будет еще некоторое время
> исполняться на текущем процессоре.
Исходя из кода похоже на то. Хотя Соломон/Руссинович пишут:
Thread dispatching occurs at DPC/dispatch level and is triggered by any of the following events:
.....
The processor affinity of a running thread changes.
А кто эту функцию вызывает? У меня сырцов нет, я поглядел... 11.05.05 15:12  
Автор: IgorR <Igor Razin> Статус: Member
<"чистая" ссылка>
А кто эту функцию вызывает? У меня сырцов нет, я поглядел IDA SetThreadAffinityMask вызывает NtSetInformationThread. Вот её бы поглядеть.
вот NtSetInformationThread ее и вызыват (см внутри) 11.05.05 16:03  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
NTSTATUS
NtSetInformationThread(
IN HANDLE ThreadHandle,
IN THREADINFOCLASS ThreadInformationClass,
IN PVOID ThreadInformation,
IN ULONG ThreadInformationLength
)

/*++

Routine Description:

This function sets the state of a thread object.

Arguments:

ThreadHandle - Supplies a handle to a thread object.

ThreadInformationClass - Supplies the class of information being
set.

ThreadInformation - Supplies a pointer to a record that contains the
information to set.

ThreadInformationLength - Supplies the length of the record that contains
the information to set.

Return Value:

TBS

--*/

{
PEEVENT_PAIR EventPair;
HANDLE EventPairHandle;
PETHREAD Thread;
PEPROCESS Process;
KPROCESSOR_MODE PreviousMode;
NTSTATUS st;
KAFFINITY Affinity, AffinityWithMasks;
ULONG_PTR BigAffinity;
KPRIORITY Priority;
LONG BasePriority;
ULONG TlsIndex;
PVOID TlsArrayAddress;
PVOID Win32StartAddressValue;
ULONG ProbeAlignment;
BOOLEAN EnableAlignmentFaultFixup;
ULONG IdealProcessor;
ULONG DisableBoost;
PVOID *ExpansionSlots;
HANDLE ImpersonationTokenHandle;
BOOLEAN HasPrivilege;

PAGED_CODE();

//
// Get previous processor mode and probe input argument if necessary.
//

PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode) {
try {

switch (ThreadInformationClass) {

case ThreadPriority :
ProbeAlignment = sizeof(KPRIORITY);
break;
case ThreadAffinityMask :
case ThreadQuerySetWin32StartAddress :
ProbeAlignment = sizeof (ULONG_PTR);
break;
case ThreadEnableAlignmentFaultFixup :
ProbeAlignment = sizeof (BOOLEAN);
break;
default :
ProbeAlignment = sizeof(ULONG);
}

ProbeForRead(
ThreadInformation,
ThreadInformationLength,
ProbeAlignment
);
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}
}

//
// Check argument validity.
//

switch ( ThreadInformationClass ) {

case ThreadPriority:

if ( ThreadInformationLength != sizeof(KPRIORITY) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
Priority = *(KPRIORITY *)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

if ( Priority > HIGH_PRIORITY|
Priority <= LOW_PRIORITY ) {

return STATUS_INVALID_PARAMETER;
}

if ( Priority >= LOW_REALTIME_PRIORITY ) {

//
// Increasing the priority of a thread beyond
// LOW_REALTIME_PRIORITY is a privileged operation.
//

HasPrivilege = SeCheckPrivilegedObject(
SeIncreaseBasePriorityPrivilege,
ThreadHandle,
THREAD_SET_INFORMATION,
PreviousMode
);

if (!HasPrivilege) {
return STATUS_PRIVILEGE_NOT_HELD;
}
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Process = THREAD_TO_PROCESS(Thread);

KeSetPriorityThread(&Thread->Tcb,Priority);

ObDereferenceObject(Thread);

return STATUS_SUCCESS;

case ThreadBasePriority:

if ( ThreadInformationLength != sizeof(LONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
BasePriority = *(PLONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}
Process = THREAD_TO_PROCESS(Thread);


if ( BasePriority > THREAD_BASE_PRIORITY_MAX|
BasePriority < THREAD_BASE_PRIORITY_MIN ) {
if ( BasePriority == THREAD_BASE_PRIORITY_LOWRT+1|
BasePriority == THREAD_BASE_PRIORITY_IDLE-1 ) {
;
}
else {

//
// Allow csrss, or realtime processes to select any
// priority
//

if ( PsGetCurrentProcess() == ExpDefaultErrorPortProcess|
Process->PriorityClass == PROCESS_PRIORITY_CLASS_REALTIME ){
;
}
else {
ObDereferenceObject(Thread);
return STATUS_INVALID_PARAMETER;
}
}
}

//
// If the thread is running within a job object, and the job
// object has a priority class limit, do not allow
// priority adjustments that raise the thread's priority, unless
// the priority class is realtime
//

if ( Process->Job && (Process->Job->LimitFlags & JOB_OBJECT_LIMIT_PRIORITY_CLASS) ) {
if ( Process->PriorityClass != PROCESS_PRIORITY_CLASS_REALTIME ){
if ( BasePriority > 0 ) {
ObDereferenceObject(Thread);
return STATUS_SUCCESS;
}
}
}

KeSetBasePriorityThread(&Thread->Tcb,BasePriority);

ObDereferenceObject(Thread);

return STATUS_SUCCESS;

case ThreadEnableAlignmentFaultFixup:

if ( ThreadInformationLength != sizeof(BOOLEAN) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
EnableAlignmentFaultFixup = *(PBOOLEAN)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

KeSetAutoAlignmentThread( &(Thread->Tcb), EnableAlignmentFaultFixup );

ObDereferenceObject(Thread);

return STATUS_SUCCESS;

case ThreadAffinityMask:

if ( ThreadInformationLength != sizeof(ULONG_PTR) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
BigAffinity = *(ULONG_PTR *) ThreadInformation;
Affinity = (KAFFINITY) BigAffinity;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

if ( !Affinity ) {

return STATUS_INVALID_PARAMETER;

}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Process = THREAD_TO_PROCESS(Thread);

//
// the following allows this api to properly if
// called while the exiting process is blocked holding the
// createdeletelock. This can happen during debugger/server
// lpc transactions that occur in pspexitthread
//

st = PsLockProcess(Process,PreviousMode,PsLockPollOnTimeout);

if ( st != STATUS_SUCCESS ) {
ObDereferenceObject(Thread);
return STATUS_PROCESS_IS_TERMINATING;
}

AffinityWithMasks = Affinity & Process->Pcb.Affinity;

if ( AffinityWithMasks != Affinity ) {

st = STATUS_INVALID_PARAMETER;

} else {

KeSetAffinityThread(
&Thread->Tcb,
AffinityWithMasks
);
st = STATUS_SUCCESS;
}

PsUnlockProcess(Process);

ObDereferenceObject(Thread);

return st;

case ThreadImpersonationToken:


if ( ThreadInformationLength != sizeof(HANDLE) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
ImpersonationTokenHandle = *(PHANDLE) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}


st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_THREAD_TOKEN,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

//
// Check for proper access to (and type of) the token, and assign
// it as the thread's impersonation token.
//

st = PsAssignImpersonationToken( Thread, ImpersonationTokenHandle );


ObDereferenceObject(Thread);

return st;

case ThreadQuerySetWin32StartAddress:
if ( ThreadInformationLength != sizeof(ULONG_PTR) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
Win32StartAddressValue = *(PVOID *) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}


st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Thread->Win32StartAddress = (PVOID)Win32StartAddressValue;
ObDereferenceObject(Thread);

return st;


case ThreadIdealProcessor:

if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
IdealProcessor = *(PULONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

if ( IdealProcessor > MAXIMUM_PROCESSORS ) {
return STATUS_INVALID_PARAMETER;
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

//
// this is sort of a slimey way of returning info from this set only
// api
//

st = (NTSTATUS)KeSetIdealProcessorThread(&Thread->Tcb,(CCHAR)IdealProcessor);

ObDereferenceObject(Thread);

return st;


case ThreadPriorityBoost:
if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

try {
DisableBoost = *(PULONG)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

KeSetDisableBoostThread(&Thread->Tcb,DisableBoost ? TRUE : FALSE);

ObDereferenceObject(Thread);

return st;

case ThreadZeroTlsCell:
if ( ThreadInformationLength != sizeof(ULONG) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
TlsIndex = *(PULONG) ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

if ( Thread != PsGetCurrentThread() ) {
ObDereferenceObject( Thread );
return STATUS_INVALID_PARAMETER;
}
{
NTSTATUS xst;
PTEB Teb;
PLIST_ENTRY Next;
PETHREAD OriginalThread;

OriginalThread = Thread;

Process = THREAD_TO_PROCESS(Thread);

//
// the following allows this api to properly if
// called while the exiting process is blocked holding the
// createdeletelock. This can happen during debugger/server
// lpc transactions that occur in pspexitthread
//

xst = PsLockProcess(Process,PreviousMode,PsLockPollOnTimeout);

if ( xst != STATUS_SUCCESS ) {
ObDereferenceObject( OriginalThread );
return STATUS_PROCESS_IS_TERMINATING;
}

// The 32bit TEB needs to be set if this is a WOW64 process on a 64BIT system.
// This code isn't 100% correct since threads have a conversion state where they
// are chaning from 64 to 32 and they don't have a TEB32 yet. Fortunatly, the slots
// will be zero when the thread is created so no damage is done by not clearing it here.

// Note that the test for the process type is inside the inner loop. This
// is bad programming, but this function is hardly time constrained and
// fixing this with complex macros would not be worth it due to the loss of clairity.

Next = Process->ThreadListHead.Flink;

while ( Next != &Process->ThreadListHead) {

Thread = (PETHREAD)(CONTAINING_RECORD(Next,ETHREAD,ThreadListEntry));
if ( !IS_SYSTEM_THREAD(Thread) ) {
if ( Thread->Tcb.Teb ) {
Teb = (PTEB)Thread->Tcb.Teb;

if ( TlsIndex > TLS_MINIMUM_AVAILABLE-1 ) {
if ( TlsIndex < (TLS_MINIMUM_AVAILABLE+TLS_EXPANSION_SLOTS) - 1 ) {
//
// This is an expansion slot, so see if the thread
// has an expansion cell
//
try {
#if defined(_WIN64)
if (Process->Wow64Process) { //Wow64 process.
PTEB32 Teb32;
PLONG ExpansionSlots32;

Teb32 = WOW64_GET_TEB32(Teb); //No probing needed on regular TEB.
if (Teb32) {
ExpansionSlots32 = ULongToPtr(ProbeAndReadLong(&(Teb32->TlsExpansionSlots)));
if (ExpansionSlots32) {
ProbeAndWriteLong(ExpansionSlots32 + TlsIndex - TLS_MINIMUM_AVAILABLE, 0);
}
}
}
else
#endif
{
ExpansionSlots = Teb->TlsExpansionSlots;
ProbeForRead(ExpansionSlots,TLS_EXPANSION_SLOTS*4,8);
if ( ExpansionSlots ) {
ExpansionSlots[TlsIndex-TLS_MINIMUM_AVAILABLE] = 0;
}

}
}
except(EXCEPTION_EXECUTE_HANDLER) {
;
}
}
}
else {
try {
#if defined(_WIN64)
if (Process->Wow64Process) { //wow64 process
PTEB32 Teb32;

Teb32 = WOW64_GET_TEB32(Teb); //No probing needed on regular TEB.
if(Teb32) {
ProbeAndWriteLong(Teb32->TlsSlots + TlsIndex, 0);
}
}
else
#endif
{
Teb->TlsSlots[TlsIndex] = NULL;
}
}
except(EXCEPTION_EXECUTE_HANDLER) {
;
}
}

}
}
Next = Next->Flink;
}

PsUnlockProcess(Process);

ObDereferenceObject(OriginalThread);

}
return st;
break;

case ThreadSetTlsArrayAddress:
if ( ThreadInformationLength != sizeof(PVOID) ) {
return STATUS_INFO_LENGTH_MISMATCH;
}


try {
TlsArrayAddress = *(PVOID *)ThreadInformation;
} except(EXCEPTION_EXECUTE_HANDLER) {
return GetExceptionCode();
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Thread->Tcb.TlsArray = TlsArrayAddress;

#if definedMIPS

if (Thread == PsGetCurrentThread()) {
PCR->TlsArray = TlsArrayAddress;
}

#endif

ObDereferenceObject(Thread);

return st;
break;

case ThreadHideFromDebugger:
if ( ThreadInformationLength != 0 ) {
return STATUS_INFO_LENGTH_MISMATCH;
}

st = ObReferenceObjectByHandle(
ThreadHandle,
THREAD_SET_INFORMATION,
PsThreadType,
PreviousMode,
(PVOID *)&Thread,
NULL
);

if ( !NT_SUCCESS(st) ) {
return st;
}

Thread->HideFromDebugger = TRUE;

ObDereferenceObject(Thread);

return st;
break;

default:
return STATUS_INVALID_INFO_CLASS;
}
}


+ к этому описалово к
NTSTATUS
PsLockProcess(
IN PEPROCESS Process,
IN KPROCESSOR_MODE WaitMode,
IN PSLOCKPROCESSMODE LockMode
)
/*++

Routine Description:

This function is used to lock the process from create/delete and to
freeze threads from entering/exiting the process.

Arguments:

Process - Pointer to the process to lock

WaitMode - Supplies the processor mode to issue the wait under

LockMode - The type of lock to attempt

PsLockPollOnTimeout - Use a timeout and poll for the lock
bailing if the process exits.

PsLockReturnTimeout - Do not poll, just timeout wait and
return if you can not get the lock.

PsLockWaitForever - Wait without a timeout


Return Value:

STATUS_SUCCESS - You got the lock, you must call PsUnlocProcess later on

STATUS_TIMEOUT - You requested PsLockReturnTimeout, and the lock was not available

STATUS_PROCESS_IS_TERMINATING - The process you are trying to lock is terminating

--*/
Ну я пока из таких соображений и исхожу 11.05.05 10:53  
Автор: Killer{R} <Dmitry> Статус: Elderman
Отредактировано 11.05.05 12:09  Количество правок: 2
<"чистая" ссылка>
те создаю отдельный поток для этого как suspended, устанавливаю ему маску и и запускаю его. Из других потоков на event'ах сделал вызов нужного кода в том потоке. Но просто недавно заценил потери на синхронизацию - по большому счету не так много по сравнению со всей прогой. Но вот по сравнению с временем исполнения требуемого куска кода - раз в 100 больше :\ Ну и фиг с ним :)
Требуемый кусок кода кстати это вызов QueryPerformanceCounter
Насколько я понял по приведенному выше коду поток... 12.05.05 15:46  
Автор: amirul w/o pass Статус: Незарегистрированный пользователь
<"чистая" ссылка>
Насколько я понял по приведенному выше коду поток решедулится сам на новую маску

Но вообще то Sleep(0) вызывает решедулинг потока. Вызвать его сразу за установкой маски и весь последующий код будет выполняться уже на новом процессоре
А если не выполнится условие (((Prcb->SetMember & Affinity)... 12.05.05 16:39  
Автор: IgorR <Igor Razin> Статус: Member
<"чистая" ссылка>
> Насколько я понял по приведенному выше коду поток
> решедулится сам на новую маску
А если не выполнится условие (((Prcb->SetMember & Affinity) == 0) && (Prcb->NextThread == NULL))?
Знать бы что заставляет решедулится. Интересно глянуть сырцы NtYieldExecution.
А если не выполнится условие (((Prcb->SetMember & Affinity)... 12.05.05 20:46  
Автор: Killer{R} <Dmitry> Статус: Elderman
<"чистая" ссылка>
> Знать бы что заставляет решедулится. Интересно глянуть
> сырцы NtYieldExecution.
MSDN про Sleep(0): A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution.
Т.е. видимо вызывается в этом случае SwitchToThread. Это в принципе подтверждаеться сырцами NtYieldExecution внизу.

NTSTATUS
NtYieldExecution (
VOID
)

/*++

Routine Description:

This function yields execution to any ready thread for up to one
quantum.

Arguments:

None.

Return Value:

None.

--*/

{

KIRQL OldIrql;
PRKPRCB Prcb;
KPRIORITY Priority;
NTSTATUS Status;
PRKTHREAD Thread;

//
// If any other threads are ready, then attempt to yield execution.
//

Status = STATUS_NO_YIELD_PERFORMED;
if (KiReadySummary != 0) {

//
// If a thread has not already been selected for execution, then
// attempt to select another thread for execution.
//

Thread = KeGetCurrentThread();
KiLockDispatcherDatabase(&Thread->WaitIrql);
Prcb = KeGetCurrentPrcb();
if (Prcb->NextThread == NULL) {
Prcb->NextThread = KiFindReadyThread(Thread->NextProcessor, 1);
}

//
// If a new thread has been selected for execution, then switch
// immediately to the selected thread.
//

if (Prcb->NextThread != NULL) {

//
// Give the current thread a new quantum, simulate a quantum
// end, insert the current thread in the appropriate ready list,
// and switch context to selected thread.
//

Thread->Quantum = Thread->ApcState.Process->ThreadQuantum;
Thread->State = Ready;
Priority = Thread->Priority;
if (Priority < LOW_REALTIME_PRIORITY) {
Priority = Priority - Thread->PriorityDecrement - 1;
if (Priority < Thread->BasePriority) {
Priority = Thread->BasePriority;
}

Thread->PriorityDecrement = 0;

}

Thread->Priority = (SCHAR)Priority;

InsertTailList(&KiDispatcherReadyListHead[Priority],
&Thread->WaitListEntry);

SetMember(Priority, KiReadySummary);
KiSwapThread();
Status = STATUS_SUCCESS;

} else {
KiUnlockDispatcherDatabase(Thread->WaitIrql);
}
}

return Status;
}

Thread->State = Ready; делается только если есть другой тред который хочет исполняться.
Вобщем сделаю у себя проверку на SMP и на SMP буду исполнять код в отдельном потоке, а на обычной системе - как обычно. Так надежнее Ж)
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach