The way TLS storage is set up depends on the TLS access model.
In the simpler "Initial executable / static TLS" model, the loader sets up TLS segment before the first instruction of the main executable is run. It computes the size of that segment by adding up TLS requirements of the main executable and all shared libraries it directly depends on.
Once this TLS segment is allocated and set up, the application starts running, and may well store pointers into the TLS segment. Hence it's impossible to realloc()
storage for the segment -- the loader would have no idea which pointers in the application must be updated.
Since you can't realloc the segment, and since there is no space in it for additional variables; how can loader deal with dynamically loaded libraries which require TLS storage of their own?
The glibc loader actually allocates some extra space in the initial TLS, and so it can dynamically load libraries with TLS, provided they don't use too much space. Once this reserve is exhausted, glibc loader will also refuse to load any additional libraries with TLS requirements.
On Solaris and Linux it is possible to dynamically load libraries with arbitrary TLS requirements, using the "General Dynamic TLS model".
It looks like HP-UX v1.6 also supports that model, and in fact makes it the default. But you are probably running an older OS release, where this model is not the default, and may not be supported at all. Check if your compiler version supports +tls=dynamic
option, and if so whether building with it helps.