Continuing on the previous theme of cool Win32 APIs that many people ignore, this week’s entry is one of my favorites: DisableThreadLibraryCalls().
DisableThreadLibraryCalls was added in NT 3.5 as a part of the performance enhancements we added to the system. As we measured the system, it quickly became clear that one major contributor to the overall system working set was the number of pages that were occupied by the DllMain entrypoint in the various system DLL’s.
The reason for this was that a DLL’s DllMain entrypoint is called whenever a thread is created or destroyed in an application. This is critical for DLLs that maintain per-thread state like the C runtime library or Winsock. But for 99% of the DLL’s on the system, the routines simply ignore the DllMain DLL_THREAD_ATTACH and DLL_THREAD_DETACH messages. Since the system couldn’t determine if a DLL ignores the DLL_THREAD_XXX messages, it always called the DllMain entrypoint whenever a thread was created.
This caused the page that contained the DllMain entrypoint for the DLL to be brought into memory, which increased the application’s working set.
The NT loader guys added the DisableThreadLibraryCalls API to the system to fix this problem. When an application calls this routine, it lets the system know that the module specified in it’s parameter doesn’t care about DLL_THREAD_XXX messages, and thus the loader won’t call into the DLL on thread creation.
This API is so useful that ATL’s CAtlDllModule.DllMain() method always calls DisableThreadLibraryCalls(). If your DLL doesn’t rely on thread creation/destruction messages, then it should too.