Wednesday, August 10, 2011

Android, Linux-ARM and TLS register emulation

TLS or Thread Local Storage

In a multi-threaded application, where all threads in a process share the same address space, there often arises the need to maintain data that is unique to a thread. Use of errno, in a C code, is a classic example of using this type of data which is local to a given thread. TLS or Thread Local Storage, as you can probably figure out from its name now, is a concept used for Threading abstraction. It is a fast and efficient way to store per-thread local data. Offset of thread's local data is accessible via the TLS register(h/w or s/w block) which points to Thread Control Block of respective thread. Check this PDF for more information.

Yesteryears High end ARM cores viz. ARM9 and even some of ARM11 cores do not have this TLS Register physically available. Operating Systems (Linux from here onwards) need to emulate it in software. New generation ARM cores viz. Cortex-Ax onwards, however, do have this TLS register available (CP15).

Why do I being an Android porting/integration guy, need to care about TLS?

Android(till Eclair? I guess) had this unique bug (or feature?) where in, it assumes that TLS register is emulated by the Kernel(Linux) and thus expect Linux to trap it. It worked well for ARM cores which were already emulating TLS register in software.

With the rise of ARM Cortex-Ax cores, people started reporting all sort of errors related to Android mounting or random Android service crashes. It turned out that the error was due to hard dependency of Android on TLS register emulation. Since Cortex-Ax devices do have TLS register available and Linux was not trapping it, that made Android really really mad.

By that time there was no known way to make Android user-space TLS register aware, developers started patching Linux to make it compatible with the emulated TLS register. Here is the relevant TLS patch for 2.6.32 and patch for 2.6.37 ARM kernel.

With Froyo i.e. v2.2, Android introduced a build config variable ARCH_ARM_HAVE_TLS_REGISTER which (you need to set/export during build time) will make Android user-space TLS register aware and you don't need to patch your Linux anymore.

So now you know what else to look for if your Android port is crashing on an unsupported Kernel version.

I'm yet to figure out what ARCH_ARM_HAVE_TLS_REGISTER ends up doing. A quick grep of this variable in AOSP came out with results in bionic/ and frameworks/base/opengl/ projects.

No comments:

Post a Comment