2012-10-01 5 views
7

Próbuję dodać debug Sprawdzanie kodu odblokowującego CRITICAL_SECTION i próbowałem następujące:Dlaczego człon OwingsThread z CRITICAL_SECTION typu HANDLE, kiedy oznacza identyfikator wątku?

... 
    if (m_pCritSect) { 
    ASSERT(m_pCritSect->OwningThread == GetCurrentThreadId()); 
    LeaveCriticalSection(m_pCritSect); 
    } 
} 

Od debugowania CRITICAL_SECTIONS (z VS 2005, głównie na WindowsXP) I „wiedzieć”, że wartość OwningThread (element struktury RTL_CRITICAL_SECTION zdefiniowany w winnt.h) to wartość th ID wątku z blokadą.

jednak gwint identyfikatory są przedstawione DWORD (typedef do unsigned long) wartości w trakcie tej zmiennej typu HANDLE (typedef dla void*) wymagających reinterpret_cast do zastosowanie HandleToULong makro z basetsd.h na powyższy kod do pracy.

Nawet stan MSDN docs:

Kiedy pierwszy wątek wywołuje procedurę EnterCriticalSection, (...) OwningThread staje się gwint ID dzwoniącego.

Dlaczego więc, na ziemi, jest to zdefiniowane jako HANDLE?


Edit Uwaga: znalazłem a statement gdzie plakat sugeruje, że uchwyt/DWORD-Id niedopasowanie jest jakiś znany misfeature niektórych wewnętrznych Windows. Więc może to jest w tym przypadku zbyt:

GetCurrentThreadId zwraca DWORD, które wysyłam do jądra w wiadomości . PsLookupThreadByThreadId zajmuje identyfikator wątku w obsłudze, ... ...

Jest to znany bug API systemu Windows („wiadomo”, że rozmawiałem z odpowiedniego menedżera filtr DEV o tym, jak to przedstawia się w Filtruj także Menedżera z powodu problemu z interfejsem API I/O Managera). Tak długo, jak nie ma więcej niż pół miliarda wątków i procesów (one używają jednej udostępnionej tabeli uchwytów) będzie dobrze . Być może do czasu to prawdziwy problem, będziemy prowadzić coś innego. [RE: ThreadId do UCHWYTU na 64-bitowy?, 08 sie 08 14:21, Tony Mason]

+1

W każdym przypadku reinterpret_cast jest przesadą. Wystąpiłby static_cast. Oba HANDLE i DWORD są typami integralnymi. –

+0

@ArmenTsirunyan - NIE, w VS2005 nie można użyć static_cast do rzutowania UCHWYTU na DWORD: 'error C2440: 'static_cast': nie można przekonwertować z 'HANDLE' na 'DWORD'' –

+0

To dziwne. Czy możesz mi powiedzieć, o co im chodzi? –

Odpowiedz

8

Każdy identyfikator w SDK, którego nazwa zaczyna się od RTL lub RTL kod lub deklaracje, które są częścią środowiska wykonawczego layer, klej, który łączy dobrze udokumentowany Winapi z nieudokumentowanym natywnym api systemu operacyjnego. Winapi jest w kamieniu, natywny system operacyjny zmienia się mocno w każdym wydaniu Windows. Nieuchronnie zmienia się również klej.

Winapi jest dokumentowaną warstwą, natywny system operacyjny jest nieudokumentowany. Warstwa środowiska wykonawczego również była nieudokumentowana, ale z czasem ujawniono jej część. Albo dlatego, że ponownie wypełnia brakującą funkcję w winapi. Lub w tym przypadku, ponieważ jest naprawdę przydatny do rozwiązywania problemów. Jednym z podstawowych problemów jest jednak to, że po ujawnieniu deklaracji Microsoft nie może jej już nigdy zmienić. Ponieważ spowoduje to zerwanie istniejących programów, co będzie dużym obciążeniem dla klientów.

Z pewnością pole ThreadOwner naprawdę trzymało uchwyt wątku w poprzedniej wersji Windows. Zwróć uwagę, że LockSemaphore również wprowadza w błąd, w rzeczywistości jest to zdarzenie automatycznego resetowania. Zbyt późno, by to naprawić, kot jest poza workiem.

4

Uważam, że głównym powodem jest to, że jest to szczegół wdrożenia. Nie zdziwiłbym się, gdyby kiedyś w historii był to uchwyt lub coś w tym rodzaju.

Dodatkowo, zdecydowanie sugeruję nie używać wewnętrznych elementów w kodzie produkcyjnym i I am not alone. Jeśli przyjrzeć się bliżej, API synchronizacji używać CRITICAL_SECTION który nie znajdzie udokumentowane jako struktura w MSDN i nie RTL_CRITICAL_SECTION (co jest typedef'ed do CRITICAL_SECTION)

wartość, która jest przechowywana w OwningThread członka jest pobierana z CLIENT_ID część Thread Information Block.W CLIENT_ID on prezentowany jako PVOID który prawdopodobnie dlatego jest modelowana w taki sam sposób w ciągu CRITICAL_SECTION:

typedef struct _CLIENT_ID 
{ 
    PVOID UniqueProcess; 
    PVOID UniqueThread; 
} CLIENT_ID, *PCLIENT_ID; 
+0

Dostarczyłem łącze MSDN, które przechodzi przez tę strukturę (przyznano, że jest w sekcji * Zaawansowane zadania debugowania *), więc myślę, że to całkiem OK, aby użyć tego * w kodzie kontroli debugowania *. –

+0

Nie zostanie on jeszcze skompilowany, jeśli zmieni się struktura, a także nie uwzględnię kodu rzeczywistego kodu programu ASSERT, ponieważ nie jest on wdrażany dla użytkownika końcowego (tj. W wersji wydania) –

Powiązane problemy