Why is the maximum number of TLS slots 1088? What a strange number.


Commenter Max noted that the maximum number of TLS slots is 1088 and wondered why such a strange number. "I mean, it does not look like a perfect number in terms of 2-based numeric system."

It looks a little better in base 2. The value is 10001000000 which breaks down as 1024 + 64.

When TLS was first introduced, the number of available TLS slots was 64, and those slots were pre-allocated as part of the thread control block. Over time, 64 slots turn out not to be enough, so the kernel team modified the code to allocate a page of data per thread once the 65th request for a TLS slot was made. A page of data is 4KB, which has enough room for 1024 32-bit values. That's why the total is 1088. It's the original 64 slots, plus an addition 1024 slots.

Note that the statement that "the maximum number of slots is 1088" is a statement of current implementation, not a contractual obligation. The contractual obligation is that there will always be at least TLS_MINIMUM_AVAILABLE slots available. Any more than that is just gravy.

Comments (13)
  1. Darran Rowe says:

    Well, my understanding of the maximum number of TLS slots available is that you know you hit it when you get TLS_OUT_OF_INDEXES or FLS_OUT_OF_INDEXES. It is also hard to put a value on how many slots have been allocated because this is a function that can be called in a DLL's DllMain function.
    After digging through the CRT's source, the CRT uses TLS slots to store per thread data too. So you just can't assume that you will get all of the slots available anyway.

  2. pm100 says:

    aha Thread Local Storage not Transport Layer Security.

    1. JChrisCompton says:

      Thanks for TLS == Thread Local Storage.
      Saved me the trouble of looking it up :-)

  3. IanBoyd says:

    Because 1087 slots is insufficient, and 1089 would just be rediculous.

  4. Antonio Rodríguez says:

    Another case of "if you have to ask what the limit is, you are doing something wrong".

    1. Joshua says:

      64 was enough in the days of shared msvcrt but no more. Each DLL may well have its own libc thus one slot for each, and I have seen 64 DLLs in one process.

      1. Antonio Rodríguez says:

        Right. One slot per DLL (or component, using the broader sense of the word). Using a few tens (or even hundreds) of TLS slots is reasonable. But my point was different: if you have to ask how many slots are available, you are probably allocating more than you need (perhaps allocating several slots from the same component, or some nonsense like that).

  5. Alex Guteniev says:

    If you have already dropped Windows XP support, then you don't much care since you can use static TLS in all the cases.

  6. Neil says:

    Back in the days when virtual address space was a potential limiting factor on the number of threads, I once wondered what sort of issues you would run into if each thread's stack was in its own thread local storage.

    1. Would have some annoying issues attempting to share pointers to objects on the stack between threads. Whether or not you should do this sort of thing in the first place is a different matter but if you can ensure that the object stays in scope in the owner thread until all the other threads are using the object complete their work, it is a relatively safe thing to do. This would obviously break and would need to be replaced with a heap allocation if the stack was in tls.

      1. Antonio Rodríguez says:

        Sharing a pointer to a stack-based object with a different thread is disaster waiting to happen: stack-based objects get freed when the function that allocated them returns, and the other thread can try to access them afterwards.

        1. Joshua says:

          Every time I use a TLS object the code could have been implemented with the MMU handling it -- that is the address is the same across threads. Passing a TLS object to another thread is a bad idea.

          1. Antonio Rodríguez says:

            I agree. Local objects are local. In general, it's often a bad idea to share with another thread or process anything that hasn't been intended and designed explicitly for sharing. Doing so, also, helps to keep interfaces defined and tidy, which, in turn, eases debugging and expanding the system. That's the idea behind the whole objects-communicating-by-message-passing thing implemented in most modern UIs.

Comments are closed.

Skip to main content