Is there a Thread-Local Storage (TLS) equivalent for kernel-mode drivers in Windows (Win32 to be exact)?
What I try to achieve:
Eventually from within my driver's dispatch routine it may call many other functions (there may be a deep callstack). I want to supply some context information specific to the request being processed. That is, I have some structure, pointer to which should be visible in all the called functions, without explicitly passing it as a parameter to every function.
Using static/global is not a perfect option (multithreading, sync objects and etc.).
If that was a user-mode code - one would obviously use TLS in such a situation. But AFAIK there are no kernel-mode functions like TlsGetValue
/TlsSetValue
. And this makes sense - for those function to work one has to allocate a process-wide TLS index first. OTOH driver code may be invoked on arbitrary thread, not limited to a specific process.
However I don't actually need a persistent thread-specific storage. I just need a thread-specific storage for my top-level function invocation.
I think I know how to "implement" the TLS, though in a hackish way. Instead of allocating the TLS index I will always use a predefined index (say, index=0). At the top-level function I'll save the stored TLS value, and overwrite it with the needed value. Upon completion the saved value will be restored.
Luckily I know how the TLS is implemented in Win32. There's a TIB
structure (thread information block) for each thread. In every thread it may be accessed using FS:[18h]
selector. The TIB
contains (among other things) an array used by TLS. The rest is pretty straightforward.
However I'd prefer to use an official API to achieve something similar.
- Is there an official kernel-mode API to achieve what I need?
- Are there reasons to avoid what I'm planning to do? I know there may potentially be a problem with re-entrance (i.e. some code invokes me, I overwrite the TLS value and then eventually call the originating code, which may rely on the TLS). But this is not possible in my specific case?
- Are there less dirty ways to solve this?
Thanks in advance.
P.S. One may theoretically use SEH (which also has per-thread information stored). That is, wrap the top-level code by __try/__except
, then where the context information is needed - raise the continuable exception with some parameter, in the __except
block fill the parameter with the context information, and then resume the execution. And this is a 100% valid program flow, without use of the undocumented features. But nevertheless this seems an ugly hack for me, not to mention the performance complications.
KeGetCurrentProcessorNumber
is a very good idea. In my particular case requests may arrive at arvitrary IRQL, and I'm not sure I'm allowed to raise it (I call there other routines), but it definitely worth checking it out. – Melody