Thread-local Storage (thread locally Storage), referred to as TLS, provides a way to store thread-private data that is not visible to other threads by each thread's private data. Chromium is a multi-process multithreaded architecture browser that creates up to 30 threads, many of which require their own private data, on systems with a limited number of TLS, such as Android 4.3 or earlier systems, Chromium may crash due to inability to allocate enough TLS. This article describes how the most recent solution to this problem is in the Chromium submission code.
The use of TLS in chromium
In the chromium code, some classes provide a current () method to return the private data of the calling thread, the most typical two examples being messageloop and renderthread. Take Messageloop as an example, because each thread might run a primary message loop, how can I get a thread-related main message loop? To do this, Messageloop provides the current () method, which, when the thread creates the Messageloop instance, sets the instance to private data for the thread, and returns the private data to the caller when the current () method is called.
Each TLS slot is identified by a unique key value (key) that the process is responsible for assigning to the OS, and if the current process requests a number of key values that exceed the system-imposed limit, the request fails to obtain a new TLS slot. A thread can bind a TLS slot to a private data, which is actually a pointer to a block of memory that is dynamically allocated by the calling thread.
chromium code, the use of TLS is abstracted from the Threadlocalpointer template class (see Base/threading/thread_ local.h file):
template <typename type>class threadlocalpointer { public: Threadlocalpointer () : slot_ () { internal::threadlocalplatform:: Allocateslot (slot_); } ~threadlocalpointer () { internal:: Threadlocalplatform::freeslot (slot_); } type* get () { Return static_cast<type*> ( internal:: Threadlocalplatform::getvaluefromslot (Slot_)); } void set (Type* ptr) { internal::threadlocalplatform::setvalueinslot ( slot_, const_cast<void*> (Static_cast<const void*> (PTR))); } Private: typedef internal::threadlocalplatform::slottype slottype; slottype slot_; disallow_copy_and_assign (Threadlocalpointer<type>);};
Where Slottype is an abstraction of the TLS slot (key value) type, Internal::threadlocalplatform is an abstraction of the TLS implementation of a particular platform. For example, on a POSIX system, the implementation of Threadlocalplatform::allocateslot is:
void Threadlocalplatform::allocateslot (slottype& slot) {int error = Pthread_key_create (&slot, NULL); Check_eq (Error, 0);}
In general, Threadlocalpointer are used in conjunction with lazyinstance, for example:
staticbase::lazyinstance<base::threadlocalpointer<renderthread> >lazy_tls = LAZY_INSTANCE_INITIALIZER ; renderthread* renderthread::current () {return LAZY_TLS. Pointer ()->get ();} Renderthread::renderthread () {Lazy_tls. Pointer ()->set (this);} Renderthread::~renderthread () {Lazy_tls. Pointer ()->set (NULL);}
When the Renderthread instance is created, the current thread sets the private data of the thread by accessing the LAZY_TLS, and each time this method is called, the thread-private Renderthread instance is returned.
Since lazyinstance is deferred initialization, in the preceding code, when the first access to pointer () is made, a new Threadlocalpointer instance is created, that is, a new TLS slot is assigned to the OS request.
Potential Problems
On the three main desktop operating systems (WINDOWS/LINUX/MAC), the above for the Threadlocalpointer package and implementation can work very well, but since chromium support Android, the latent in the above implementation of the problem surfaced.
If you need to store more than one private data in a thread, such as a Renderthread instance, a Messageloop instance, and so on, each of the system assigns the TLS key value to the process, and once the data of the key value reaches the limit, the application failure causes the program to crash. This problem has been exposed in chromium webview because Android 4.3 or older systems, the maximum number of TLS slots available is only 64, removing the Android system library (OPENGL,JVM) needs to occupy a portion Left chromium to use the number is not much, once the allocation is found to be unsuccessful, chromium will trigger the check, the program immediately abnormal exit. On Android 4.4, the maximum number of TLS slots available is up to 128, a problem that has been mitigated, but not fundamentally eliminated.
Workaround
Chromium provides a new way to solve the above problems, the main idea is to chromium own management of TLS.
In the case of POSIX systems, the key created through Pthread_key_create is visible to all threads in the process, but each thread can bind different private data to the same key, which means that the entire chromium can share the same TLS slot. Create an application-tier TLS table to completely resolve the limit on the number of system-level TLS slots.
Specifically, the Chromium TLS system will first request a key to the OS, and each thread will bind a thread-private TLS table for this key, and Chromium set this table to hold 64 table entries. When a thread needs a new TLS slot, it first checks if the thread is a key already bound to the TLS table, and if not, it needs to create a TLS table and set it as thread-private, then take an available item sequentially from the table and set the new private data. It is not difficult to see that the new TLS slot is not applied to the OS, but is applied to chromium TLS.
threadlocalstorage template class is the abstraction of TLS in the new CHROMIUMTLS system, Staticslot and slots encapsulate initialization chromium TLS system, creating a TLS table, and setting up and getting thread-private data operations. Therefore, the above Threadlocalpointer template class will operate TLS from the direct use of threadlocalplatform and should instead use Threadlocalstorage::slot, as follows:
template <typename type>class threadlocalpointer { public: Threadlocalpointer () {} ~threadlocalpointer () { slot_. Free (); } type* get () { return static_cast<Type*> ( Slot_. Get ()); } void set (type* ptr) { slot_. Set (const_cast<void*> (static_cast<const void*> (PTR))); } private: Threadlocalstorage::slot slot_; disallow_copy_and_assign (threadlocalpointer<type>);};
Again, Threadlocalstorage::slot is simply requesting a usable TLS slot from the Chromium TLS system, instead of applying directly to the system.
More Information
This issue has been reported in the bug list of the Chromium project, see here .
Chromium TLS implementations are only recently submitted to the Chromium code base, see here .
The number of TLS slots in the Android source code is defined in the Bionic_tls_slots macro constant, see Android 4.3 and the Android 4.4 .
about Chromium TLS system implementation details, readers of interest can read base/threading/thread_local_storage.h/cc such as source files.
about Pthread_key_create, see Linux Mans Page .
This article is from the "Hong Bo Technical column" blog, please be sure to keep this source http://hongbo.blog.51cto.com/4699661/1548489
Chromium on Android:chromium thread local storage System