Implementing Fiber-Local Storage Callbacks: sharing data between DLLs

John Sheu sheu at google.com
Wed Aug 31 17:31:28 CDT 2016


On Wed, Aug 31, 2016 at 12:21 PM, Andrew Eikum <aeikum at codeweavers.com> wrote:
> On Wed, Aug 31, 2016 at 02:12:23AM -0700, John Sheu wrote:
>> TL;WR: I'd like to share a struct definition between ntdll and
>> kernel32, passed through the PEB.  Is this kosher according to Wine
>> style/design, and if so, which header should I stick it in?
>>
>
> I don't know anything about the particular issue you're working on, so
> I can just speak generally.
>
> We try to avoid creating internal, Wine-only APIs. Sometimes it's
> necessary, and when we do that, the header goes in <include/wine/>.
> One example is "gdi_driver.h" which defines the interface between e.g.
> user32 and the graphics drivers.
>
> Are the structures you need declared publicly in the win32 API, even
> as opaque pointers? If so, they may belong in <include/winternl.h>.
>
> A specific proposal about what changes you'd like might bring more
> detailed responses.

Thanks Andrew!

A little more elaboration, on what I already wrote:

ntdll and kernel32 will have to jointly manage ownership of the
storage array that FLS data is stored in, because it can be deleted
either

1. When a thread is shutdown, in the LdrShutdownThread path.
2. When a fiber is deleted, in when DeleteFiber is called.

In addition, (3) if the thread is aborted (through
NtTerminateProcess), the storage array isn't deleted on thread abort,
since (behavior confirmed by conformance tests) the FLS data is used
later when FlsFree is called.

So we have cases where in (1) ntdll deletes the FLS data array, (2)
kernel32 deletes the FLS data array, and (3) ntdll passes ownership of
the data array to kernel32.  Thus both dlls will have to have to
jointly manage ownership of the array.

--

The question is how we manage this.  One option is to introduce
additional function call entry points to either ntdll or kernel32,
called by the other, to manages FLS lifetime.  I see though that the
list of entry points is pretty tightly defined in the .spec files for
each DLL, and the convention may be (correct me if I'm wrong) not to
introduce "weird" private Wine-only APIs to the list.  The other
option is to use some internal structs, pointed to by the PEB and TEB
structures.  That's the approach I'd like to go with.

My proposal would be:

1.  Define a common struct to hold the FLS data array, that would be:
      struct FlsSlots {
        LIST_ENTRY fls_link;
        void fls_slots[SLOT_COUNT];
      };
2.  TEB.FlsSlots right now is a void** member; make this a struct
FlsSlots* member instead.
3.  Link the FlsSlots struct into PEB.FlsListHead.

This would require that struct FlsSlots be defined somewhere -- either
in wine/include, as mentioned, or in <include/winternl.h>.  Since it
isn't declared publicly in the win32 API, even as an opaque pointer --
I'm leaning toward the former.  Maybe in "wine/include/fls.h" ?

Thanks,
-John Sheu



More information about the wine-devel mailing list