Гарантирует ли такая обертка что кусок кода будет исполняться исключительно только на первом процессоре? Или всеже лучше вынести кусок кода в отдельный поток и вызывать его на исполнение через ивенты?
Ядро не ковырял, но в MSDN вроде говорится, что установка Affinity для планировщика указывает только предпочтение, т.е. в каких-то одному ему ведомых случаях, он может исполнить "кусок кода" и на другом процессоре.11.05.05 07:53 Автор: HandleX <Александр М.> Статус: The 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.
//
// 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.
//
//
// 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.
//
//
// 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) и возможна ситуация когда поток будет еще некоторое время исполняться на текущем процессоре. Или я чтото пропустил/не так понял?
Исходя из кода похоже на то. Хотя Соломон/Руссинович пишут: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
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.
//
// 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;
}
}
}
//
// 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;
}
//
// 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
//
// 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;
те создаю отдельный поток для этого как 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.
//
// 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->State = Ready; делается только если есть другой тред который хочет исполняться.
Вобщем сделаю у себя проверку на SMP и на SMP буду исполнять код в отдельном потоке, а на обычной системе - как обычно. Так надежнее Ж)