Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Managed C++/CLI
  4. trying to understand DLL and Thread local storage

trying to understand DLL and Thread local storage

Scheduled Pinned Locked Moved Managed C++/CLI
sharepointdatabasedata-structuressecurity
16 Posts 5 Posters 75 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    ForNow
    wrote on last edited by
    #1

    Hi I have been looking at the examples off dll and TLS First thing I noticed that

    DWORD g_dwThreadIndex;

    is in global storage It would be nice as in the IBM manuals would have registers on at entry to DllMain I mean is the SP (register) that of the calling application regardless if the index returned from tlsalloc lets say is 5 and then before the current thread access the storage set by tlssetvalue another thread does a tlsallloc g_dwThreadindex becomes 6 then the first thread then does tlsgetvalue it would be using 6 instead of 5 obviously I am not understanding something I mean if gw_dwThreadindex would be defined in the callers stack I would get it more so is the anyway of knowing the identity of the caller I mean maybe process id or thread guess I could do a call to Startupinfo

    Richard DeemingR L J K 5 Replies Last reply
    0
    • F ForNow

      Hi I have been looking at the examples off dll and TLS First thing I noticed that

      DWORD g_dwThreadIndex;

      is in global storage It would be nice as in the IBM manuals would have registers on at entry to DllMain I mean is the SP (register) that of the calling application regardless if the index returned from tlsalloc lets say is 5 and then before the current thread access the storage set by tlssetvalue another thread does a tlsallloc g_dwThreadindex becomes 6 then the first thread then does tlsgetvalue it would be using 6 instead of 5 obviously I am not understanding something I mean if gw_dwThreadindex would be defined in the callers stack I would get it more so is the anyway of knowing the identity of the caller I mean maybe process id or thread guess I could do a call to Startupinfo

      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #2

      We don't know which examples you've been looking at. But the whole point of thread-local storage is that it's local to the thread; one thread cannot modify a TLS variable for another thread. (At least not without jumping through several flaming hoops whilst drenched in LPG and holding a large firework.) Each thread gets its own copy of the TLS variable. If thread A set it to 5, and thread B sets it to 6, thread A will still see it set to 5. Thread Local Storage | Microsoft Learn[^]


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      F 1 Reply Last reply
      0
      • Richard DeemingR Richard Deeming

        We don't know which examples you've been looking at. But the whole point of thread-local storage is that it's local to the thread; one thread cannot modify a TLS variable for another thread. (At least not without jumping through several flaming hoops whilst drenched in LPG and holding a large firework.) Each thread gets its own copy of the TLS variable. If thread A set it to 5, and thread B sets it to 6, thread A will still see it set to 5. Thread Local Storage | Microsoft Learn[^]


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

        F Offline
        F Offline
        ForNow
        wrote on last edited by
        #3

        I am refering to the following example i found in the codeproject my lack of understanding is due to the fact that gw_dwThreadIndexis defined in global storage not stack/local storage

        Shrink ▲
        struct ThreadData {
        // some thread specific data
        };
        ...
        DWORD g_dwThreadIndex;

        extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance,
        DWORD dwReason, LPVOID /*pReserved*/)
        {
        ThreadData* pData;

        switch (dwReason) {
            case DLL\_PROCESS\_ATTACH:
        
                // allocate a TLS index
        
                g\_dwThreadIndex = ::TlsAlloc();
                if (g\_dwThreadIndex == TLS\_OUT\_OF\_INDEXES)
                    return FALSE;
        
                //break;        // execute the DLL\_THREAD\_ATTACH code
        
            case DLL\_THREAD\_ATTACH:
        
                // allocate memory for this thread
        
                pData = (ThreadData\*) ::LocalAlloc(LPTR, sizeof(ThreadData));
                if (pData == 0)
                    return FALSE;
        
                ::TlsSetValue(g\_dwThreadIndex, (LPVOID) pData);
                break;
        
            case DLL\_THREAD\_DETACH:
        
                // release memory for this thread
        
                pData = (ThreadData\*) ::TlsGetValue(g\_dwThreadIndex);
                if (pData != 0)
                    ::LocalFree((HLOCAL) pData);
                break;
        
            case DLL\_PROCESS\_DETACH:
        
                // release memory for this thread
        
                pData = (ThreadData\*) ::TlsGetValue(g\_dwThreadIndex);
                if (pData != 0)
                    ::LocalFree((HLOCAL) pData);
        
                // release the TLS index
        
                ::TlsFree(g\_dwThreadIndex);
                break;
        }
        
        return TRUE;
        

        }

        ...
        

        };

        Richard DeemingR 1 Reply Last reply
        0
        • F ForNow

          I am refering to the following example i found in the codeproject my lack of understanding is due to the fact that gw_dwThreadIndexis defined in global storage not stack/local storage

          Shrink ▲
          struct ThreadData {
          // some thread specific data
          };
          ...
          DWORD g_dwThreadIndex;

          extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance,
          DWORD dwReason, LPVOID /*pReserved*/)
          {
          ThreadData* pData;

          switch (dwReason) {
              case DLL\_PROCESS\_ATTACH:
          
                  // allocate a TLS index
          
                  g\_dwThreadIndex = ::TlsAlloc();
                  if (g\_dwThreadIndex == TLS\_OUT\_OF\_INDEXES)
                      return FALSE;
          
                  //break;        // execute the DLL\_THREAD\_ATTACH code
          
              case DLL\_THREAD\_ATTACH:
          
                  // allocate memory for this thread
          
                  pData = (ThreadData\*) ::LocalAlloc(LPTR, sizeof(ThreadData));
                  if (pData == 0)
                      return FALSE;
          
                  ::TlsSetValue(g\_dwThreadIndex, (LPVOID) pData);
                  break;
          
              case DLL\_THREAD\_DETACH:
          
                  // release memory for this thread
          
                  pData = (ThreadData\*) ::TlsGetValue(g\_dwThreadIndex);
                  if (pData != 0)
                      ::LocalFree((HLOCAL) pData);
                  break;
          
              case DLL\_PROCESS\_DETACH:
          
                  // release memory for this thread
          
                  pData = (ThreadData\*) ::TlsGetValue(g\_dwThreadIndex);
                  if (pData != 0)
                      ::LocalFree((HLOCAL) pData);
          
                  // release the TLS index
          
                  ::TlsFree(g\_dwThreadIndex);
                  break;
          }
          
          return TRUE;
          

          }

          ...
          

          };

          Richard DeemingR Offline
          Richard DeemingR Offline
          Richard Deeming
          wrote on last edited by
          #4

          I'm not a C++ person, but as far as I can see, the only place you write to the g_dwThreadIndex variable is in the DLL_PROCESS_ATTACH code. According to Microsoft, that means:

          DllMain entry point (Process.h) - Win32 apps | Microsoft Learn[^]

          The DLL is being loaded into the virtual address space of the current process as a result of the process starting up or as a result of a call to LoadLibrary. DLLs can use this opportunity to initialize any instance data or to use the TlsAlloc function to allocate a thread local storage (TLS) index.

          As far as I can see, that will only ever happen once per process. And the documentation explicitly says that this is the correct time to call TlsAlloc.


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

          F 1 Reply Last reply
          0
          • Richard DeemingR Richard Deeming

            I'm not a C++ person, but as far as I can see, the only place you write to the g_dwThreadIndex variable is in the DLL_PROCESS_ATTACH code. According to Microsoft, that means:

            DllMain entry point (Process.h) - Win32 apps | Microsoft Learn[^]

            The DLL is being loaded into the virtual address space of the current process as a result of the process starting up or as a result of a call to LoadLibrary. DLLs can use this opportunity to initialize any instance data or to use the TlsAlloc function to allocate a thread local storage (TLS) index.

            As far as I can see, that will only ever happen once per process. And the documentation explicitly says that this is the correct time to call TlsAlloc.


            "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

            F Offline
            F Offline
            ForNow
            wrote on last edited by
            #5

            Just realized posted to wrong forum however the variable is in static or global storage the next thread that comes by can change its value thats my problem just about all the. examples for TLS and DLL s have it this way

            Richard DeemingR 1 Reply Last reply
            0
            • F ForNow

              Hi I have been looking at the examples off dll and TLS First thing I noticed that

              DWORD g_dwThreadIndex;

              is in global storage It would be nice as in the IBM manuals would have registers on at entry to DllMain I mean is the SP (register) that of the calling application regardless if the index returned from tlsalloc lets say is 5 and then before the current thread access the storage set by tlssetvalue another thread does a tlsallloc g_dwThreadindex becomes 6 then the first thread then does tlsgetvalue it would be using 6 instead of 5 obviously I am not understanding something I mean if gw_dwThreadindex would be defined in the callers stack I would get it more so is the anyway of knowing the identity of the caller I mean maybe process id or thread guess I could do a call to Startupinfo

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #6

              I'm not sure I quite understand what you are asking, but each thread gets its own stack (pointed at by SP) which provides all the thread local storage. It can also allocate its own storage through the normal methods. You have not really explained what g_dwThreadIndex is being used for in relation to the question. Does this all relate to some article, or specific MSDN page?

              F 1 Reply Last reply
              0
              • F ForNow

                Just realized posted to wrong forum however the variable is in static or global storage the next thread that comes by can change its value thats my problem just about all the. examples for TLS and DLL s have it this way

                Richard DeemingR Offline
                Richard DeemingR Offline
                Richard Deeming
                wrote on last edited by
                #7

                ForNow wrote:

                the next thread that comes by can change its value

                Well yes, if you do it wrong you can shoot yourself in the foot. As far as I can see, the example you're looking at is not doing it wrong. The global variable is initialized once, in the place where the documentation says it should be initialized. This seems to be a case of "if I stick a fork in my toaster whilst it's switched on, I can get an electric shock; therefore, all toasters are dangerous and should be banned". :)


                "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

                F 1 Reply Last reply
                0
                • F ForNow

                  Hi I have been looking at the examples off dll and TLS First thing I noticed that

                  DWORD g_dwThreadIndex;

                  is in global storage It would be nice as in the IBM manuals would have registers on at entry to DllMain I mean is the SP (register) that of the calling application regardless if the index returned from tlsalloc lets say is 5 and then before the current thread access the storage set by tlssetvalue another thread does a tlsallloc g_dwThreadindex becomes 6 then the first thread then does tlsgetvalue it would be using 6 instead of 5 obviously I am not understanding something I mean if gw_dwThreadindex would be defined in the callers stack I would get it more so is the anyway of knowing the identity of the caller I mean maybe process id or thread guess I could do a call to Startupinfo

                  J Offline
                  J Offline
                  jschell
                  wrote on last edited by
                  #8

                  The actual source of the code referenced Using Thread Local Storage in a Dynamic-Link Library - Win32 apps | Microsoft Learn[^] Following is also relevant to see the messages. DllMain entry point (Process.h) - Win32 apps | Microsoft Learn[^] The code example is skipping the normal TLS semantics. So in other words it is using the first TLS index for all storage. Within the code provided. This might follow into the following comment...

                  ForNow wrote:

                  and then before the current thread access the storage set by tlssetvalue another thread does a tlsallloc g_dwThreadindex becomes 6

                  Not exactly sure what you are saying there but I think you are presuming that somehow this initialization code is not thread safe. In that it might be called by multiple threads at the same time. This code method will never be called by more than one thread at a time. Additionally the 'DLL_PROCESS_ATTACH' will never be called more than once (within one process space of course.)

                  F 1 Reply Last reply
                  0
                  • L Lost User

                    I'm not sure I quite understand what you are asking, but each thread gets its own stack (pointed at by SP) which provides all the thread local storage. It can also allocate its own storage through the normal methods. You have not really explained what g_dwThreadIndex is being used for in relation to the question. Does this all relate to some article, or specific MSDN page?

                    F Offline
                    F Offline
                    ForNow
                    wrote on last edited by
                    #9

                    Richard I think I’m begging to understand the source of my confusion First it is my understanding there are Two types off DLL one for the entire operating system in my case windows 10 and one servicing threads of one address space if it’s the former I mean that works like USER.DLL then the code example of tls wouldn’t work an I right in this ?

                    L 1 Reply Last reply
                    0
                    • J jschell

                      The actual source of the code referenced Using Thread Local Storage in a Dynamic-Link Library - Win32 apps | Microsoft Learn[^] Following is also relevant to see the messages. DllMain entry point (Process.h) - Win32 apps | Microsoft Learn[^] The code example is skipping the normal TLS semantics. So in other words it is using the first TLS index for all storage. Within the code provided. This might follow into the following comment...

                      ForNow wrote:

                      and then before the current thread access the storage set by tlssetvalue another thread does a tlsallloc g_dwThreadindex becomes 6

                      Not exactly sure what you are saying there but I think you are presuming that somehow this initialization code is not thread safe. In that it might be called by multiple threads at the same time. This code method will never be called by more than one thread at a time. Additionally the 'DLL_PROCESS_ATTACH' will never be called more than once (within one process space of course.)

                      F Offline
                      F Offline
                      ForNow
                      wrote on last edited by
                      #10

                      Hi I think I’m begging to understand the source of my confusion It is my understanding there are two types of dll’s One services the entire os like kerenel.DLL and one just a particular address space if my code is of the former than this example is not PROCESS safe am I correct in my understanding ?

                      J 1 Reply Last reply
                      0
                      • Richard DeemingR Richard Deeming

                        ForNow wrote:

                        the next thread that comes by can change its value

                        Well yes, if you do it wrong you can shoot yourself in the foot. As far as I can see, the example you're looking at is not doing it wrong. The global variable is initialized once, in the place where the documentation says it should be initialized. This seems to be a case of "if I stick a fork in my toaster whilst it's switched on, I can get an electric shock; therefore, all toasters are dangerous and should be banned". :)


                        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

                        F Offline
                        F Offline
                        ForNow
                        wrote on last edited by
                        #11

                        This example works if the DLL is servicing only one address space but if it’s system DLL than I think there would be a problem ?

                        1 Reply Last reply
                        0
                        • F ForNow

                          Richard I think I’m begging to understand the source of my confusion First it is my understanding there are Two types off DLL one for the entire operating system in my case windows 10 and one servicing threads of one address space if it’s the former I mean that works like USER.DLL then the code example of tls wouldn’t work an I right in this ?

                          L Offline
                          L Offline
                          Lost User
                          wrote on last edited by
                          #12

                          No there is only one type of DLL, which is a Dynamically Loadable Library. However, it may, or may not, be thread safe, depending on how it is created. Most (all?) of the Windows provided DLLs are thread safe. And the whole point of having DLLs is that the system only needs to load it once, to service multiple executables (i.e. address spaces). Be that as it may, I am still not sure what your concern is with regard to threads.

                          F 1 Reply Last reply
                          0
                          • L Lost User

                            No there is only one type of DLL, which is a Dynamically Loadable Library. However, it may, or may not, be thread safe, depending on how it is created. Most (all?) of the Windows provided DLLs are thread safe. And the whole point of having DLLs is that the system only needs to load it once, to service multiple executables (i.e. address spaces). Be that as it may, I am still not sure what your concern is with regard to threads.

                            F Offline
                            F Offline
                            ForNow
                            wrote on last edited by
                            #13

                            I’m sure you are right ( or else nothing would work ) I think what I have to do is have 2 exe both load the same DLL run under it under visual studio debugger and look at the address thanks

                            1 Reply Last reply
                            0
                            • F ForNow

                              Hi I think I’m begging to understand the source of my confusion It is my understanding there are two types of dll’s One services the entire os like kerenel.DLL and one just a particular address space if my code is of the former than this example is not PROCESS safe am I correct in my understanding ?

                              J Offline
                              J Offline
                              jschell
                              wrote on last edited by
                              #14

                              ForNow wrote:

                              there are two types of dll’s

                              Sort of true but also not true. When a dll is loaded the whatever loaded it decides how to use it. In one case the defining characteristic of an 'application' is that it must have a defined entry point and other defined behaviors. That is true for every operating system (not just windows and dlls.) The code above provides a defined entry point. Other dlls might just be libraries and they might have many 'entry' points (methods) although how each of those is defined (laid out in the dll) defines whether it can be successfully called and even how it must be called. All of that is rather esoteric though and is almost never going to be an issue.

                              1 Reply Last reply
                              0
                              • F ForNow

                                Hi I have been looking at the examples off dll and TLS First thing I noticed that

                                DWORD g_dwThreadIndex;

                                is in global storage It would be nice as in the IBM manuals would have registers on at entry to DllMain I mean is the SP (register) that of the calling application regardless if the index returned from tlsalloc lets say is 5 and then before the current thread access the storage set by tlssetvalue another thread does a tlsallloc g_dwThreadindex becomes 6 then the first thread then does tlsgetvalue it would be using 6 instead of 5 obviously I am not understanding something I mean if gw_dwThreadindex would be defined in the callers stack I would get it more so is the anyway of knowing the identity of the caller I mean maybe process id or thread guess I could do a call to Startupinfo

                                K Offline
                                K Offline
                                kdbueno
                                wrote on last edited by
                                #15

                                ds thread does do work, and does not manually aperture threads without nomenclatures.

                                1 Reply Last reply
                                0
                                • F ForNow

                                  Hi I have been looking at the examples off dll and TLS First thing I noticed that

                                  DWORD g_dwThreadIndex;

                                  is in global storage It would be nice as in the IBM manuals would have registers on at entry to DllMain I mean is the SP (register) that of the calling application regardless if the index returned from tlsalloc lets say is 5 and then before the current thread access the storage set by tlssetvalue another thread does a tlsallloc g_dwThreadindex becomes 6 then the first thread then does tlsgetvalue it would be using 6 instead of 5 obviously I am not understanding something I mean if gw_dwThreadindex would be defined in the callers stack I would get it more so is the anyway of knowing the identity of the caller I mean maybe process id or thread guess I could do a call to Startupinfo

                                  K Offline
                                  K Offline
                                  kdbueno
                                  wrote on last edited by
                                  #16

                                  glthreads does not collide msride.

                                  1 Reply Last reply
                                  0
                                  Reply
                                  • Reply as topic
                                  Log in to reply
                                  • Oldest to Newest
                                  • Newest to Oldest
                                  • Most Votes


                                  • Login

                                  • Don't have an account? Register

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • World
                                  • Users
                                  • Groups