Be aware: FLS-Fiber Local Storage

Problem:

In the last several months there were several publications describing usage of fibers.  When covering SQLOS's scheduling I will go into more details about them. Today I would like to touch on the subject on how to make your dlls/libraries more robust in the fiber environment.

 

As you know, when running SQL server in a fiber mode you need to be very careful when using functionality that make heavy usage of TEB, thread environment block, or TLS, thread local storage. During a fiber switch TLS and many other fields in TEB don't get switched. 

 

You will be surprised how many libraries leverage TLS and don't work correctly with Fibers. Even older versions of MSVCRT, c-runtime, leverage TLS to allocate their per thread local data. The list of broken libraries include:

  • COM
  • RPC
  • Side by Side
  • Older versions of CRT
  • Windows synchronization: Critical Section & Mutex
  • ...

 

So how do you protect yourself? Starting with Windows XP/2003, operating system introduced FLS, Fiber local storage: https://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/flssetvalue.asp. It has exactly the same semantics as TLS. However, opposite from TLS, FLS is per a fiber and it does get switched during SwitchToFiber call.

 

This means that if your dll will be used in fiber mode, you might want to consider using FLS instead of TLS. If a thread is not converted to a fiber, FLS is still available and there is no much overhead in using it.

 

If you are running XP, extended stored procedure or dll that will be loaded into SQL Server, you must use FLS. Be careful though FLS is not available on Win2K. Applications that need to run on down level platforms have to use dynamic linking - leveraging GetProcAddress API to make sure that your dll loads correctly there.

 

A bit of history:

FLS was finally introduced in Windows XP and 2003 because latter version of c-runtime made heavy usage of TLS for exception handling. This turned fiber mode completely unusable.

 

How it works:

When a thread is created it doesn't have FLS set up. Windows uses lazy initialization for FLS. When FLSAlloc gets called for the first time, OS allocates FLS for this thread. Once thread is converted to fiber, FLS gets switched during SwitchToFiber call.  You can use FLSCallBack to destroy FLS entries when a fiber/thread exists or FLS gets shrunk.

 

I will be glad to hear your comments!