GetThreadID in assembly
Asked Answered
P

2

11

I read the source code of FastMM4, and notice this interesting function

function GetThreadID: Cardinal;
{$ifdef 32Bit}
asm
  mov eax, FS:[$24]
end;
{$else}
begin
  Result := GetCurrentThreadID;
end;
{$endif}

I've tested it, and it works, so my question is any explanation why it works?

Presocratic answered 23/4, 2013 at 15:52 Comment(9)
And another must see link on TEB. MS documentation is useless for this subject.Ceaseless
On the contrary the MS documentation is excellent. Since this is private implementation the correct documentation strategy for private implementation details is to keep it private.Linguist
@DoctorLai, I'm curious, why do you call reading memory with magic displacement an "effecient"?Ceaseless
@David Heffernan, makes sense, but only until these private details published. Since when, it becomes just poorly documented details.Ceaseless
@user539484 you are right, actually i didn't know how the Win32 API GetCurrentThreadID is implemented. maybe they both use the same thing.Presocratic
@Doctor You can step into the winapi call. And of course it uses TEB.Linguist
@user and then ms are probably stuck with the current offsets until the end of time!Linguist
@DoctorLai, yes, Windows implementation reads TEB, but they use helper function NtCurrentTeb/ZwCurrentTeb to attain certain grade of flexibility of private implementation.Ceaseless
@David Heffernan, does "excellent" MS documentation shed at least some light onto discussed subject?Ceaseless
S
10

The x86 register FS points to the Thread Information Block in Windows. The value in TIB at address FS+0x24 contains ID of the current thread. By moving the value to eax, which is used to pass the function return value, GetThreadID returns the current thread ID.

Scapegrace answered 23/4, 2013 at 16:5 Comment(17)
so, it means i can do the same with FS+0x20 that returns the Process ID. this must be more efficient than the one defined in Windows unit.Presocratic
It may be marginally more efficient but I am here to tell you that fetching PID and TID is not the bottleneck in your program.Linguist
@David, Reading other posts from OP, I don't think OP has a bottleneck at all. He's more into extreme optimization kind of thing... perhaps :)Ascent
@Ascent What's funny here, is that the implementation of GetCurrentThreadId simply read the TEB. I mean, what else would it do? I would not accept the code in the question into my codebase.Linguist
@David, "I would not accept the code in the question into my codebase" - I'm with you on this.Ascent
@doctorlai: if you look at how winapi implementa this, it does the same thing really... related stuffCisneros
@kobib can I ask what is 'OP'?Presocratic
@David Heffernan yes I agree with you. getting IDs never is the bottleneck.Presocratic
@Cisneros so the advantage of doing such is to save the function calling overhead ?Presocratic
@DoctorLai Why do you want to save function calling overhead? Why don't you want simple code that is easy to maintain?Linguist
@DoctorLai at the expense of breaking stuff, like in x64 or windows rt. The performance benefit is probably not even measureable so I would stick to winapi! (for play the asm is cool ;-) )Cisneros
@Remko, it is unlikely a "fun", look more like dirty hacks.Ceaseless
@user539484 what is dirty about it, it is 100% confirming to msdn docs and intel specs however limited to current implementationCisneros
@Remko, most assemblers supports structs (including BASM), you are using magic displacements instead, creating the grounds for the questions like this one. This is not cool.Ceaseless
@Samuli Hynönen, a minor, but important correction: FS is x386 register, not just x86.Ceaseless
Do you use FastMM4, @David? If so, then "accept the code in the question into my codebase" is exactly what you've done. The assembler implementation of GetThreadID has existed since revision 1. The conditional call to GetCurrentThreadID was added in revision 36 for 64-bit support of Delphi XE2.Dozy
@Rob Not really. I mean the codebase which I manage. If the code had used GetCurrentThreadId from the start, the change in r36 would not have been needed.Linguist
S
1

This method uses the information stored in the Thread Environment Block

Sis answered 23/4, 2013 at 16:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.