成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

ChromiumonAndroid:Chromium線程局部存儲系統(tǒng)-創(chuàng)新互聯(lián)

線程局部存儲(Thread Local Storage), 簡稱TLS,提供了一種存儲線程私有數(shù)據(jù)的方式,每個線程的私有數(shù)據(jù)對其他線程均不可見。Chromium是一個多進程多線程架構的瀏覽器,運行時會創(chuàng)建多達30幾個線程,其中很多線程需要擁有自己私有數(shù)據(jù),在TLS數(shù)量有限的系統(tǒng)上,例如Android 4.3或更早的系統(tǒng),可能會因為無法分配足夠的TLS而導致Chromium崩潰。本文將介紹最近在Chromium提交代碼中是如何解決這個問題的。

我們提供的服務有:成都網(wǎng)站建設、成都網(wǎng)站設計、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認證、城子河ssl等。為超過千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務,是有科學管理、有技術的城子河網(wǎng)站制作公司

TLS在Chromium中的使用

Chromium代碼中,有些類提供了一個current()方法用來返回調用線程的私有數(shù)據(jù),最典型的兩個例子是MessageLoop和RenderThread。以MessageLoop為例,因為每個線程可能運行著一個主消息循環(huán),如何能夠獲取與線程相關的主消息循環(huán)呢?為此,MessageLoop提供了current()方法,當線程在創(chuàng)建MessageLoop實例時,會將這個實例設置為線程的私有數(shù)據(jù),當調用current()方法時,再將這個私有數(shù)據(jù)返回給調用者。

每個TLS槽都由一個唯一的鍵值(key)標識,這個鍵值由進程負責向OS申請分配,如果當前進程申請的鍵值數(shù)量超過系統(tǒng)規(guī)定的上限,申請將失敗,即無法獲取一個新的TLS槽。線程可以將TLS槽綁定到一個私有數(shù)據(jù)上,這個私有數(shù)據(jù)實際上是一個指針,指向一塊由調用線程動態(tài)分配的內存塊。

Chromium代碼中,對TLS的使用都抽象在ThreadLocalPointer模板類中(參見base/threading/thread_local.h文件):

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>);
};

其中SlotType是對TLS槽(鍵值)類型的抽象,internal::ThreadLocalPlatform是對特定平臺的TLS實現(xiàn)的抽象。例如,在POSIX系統(tǒng)上,ThreadLocalPlatform::AllocateSlot的實現(xiàn)為:

void ThreadLocalPlatform::AllocateSlot(SlotType& slot) {
  int error = pthread_key_create(&slot, NULL);
  CHECK_EQ(error, 0);
}

一般地,會結合LazyInstance使用ThreadLocalPointer,例如:

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);
}

當創(chuàng)建RenderThread實例時,當前線程會通過訪問lazy_tls設置線程的私有數(shù)據(jù),此后每次調用current()方法時,都會返回線程私有的RenderThread實例。

由于LazyInstance是延遲初始化的,上述代碼中,當首次訪問Pointer()時,會創(chuàng)建一個新的ThreadLocalPointer實例,也就是向OS申請分配一個新的TLS槽。

潛在的問題

在三大桌面操作系統(tǒng)上(Windows/Linux/Mac),上述對ThreadLocalPointer的封裝和實現(xiàn)都能工作的很好,但自從Chromium支持Android之后,潛伏在上述實現(xiàn)中的問題就浮出水面了。

如果一個線程中需要存儲多個私有數(shù)據(jù),比如除了RenderThread實例,還有MessageLoop實例等等,每個都要系統(tǒng)分配給進程的TLS鍵值,那么一旦鍵值的數(shù)據(jù)達到上限,申請失敗導致程序崩潰。這個問題已經(jīng)在Chromium WebView中暴露了,原因是Android 4.3或更老的系統(tǒng),大可用的TLS槽數(shù)量只有64個,除去Android系統(tǒng)庫(opengl,jvm)需要占用一部分之外,留給Chromium使用的數(shù)量已經(jīng)不多了,一旦發(fā)現(xiàn)分配不成功,Chromium會觸發(fā)CHECK,程序立即異常退出。Android 4.4系統(tǒng)上,大可用的TLS槽數(shù)量多達128個,這個問題得到一定的緩解,但仍沒有從根本上杜絕這個問題。

解決方法

Chromium提供了一種新的方式解決上述問題,主要思路是Chromium自己管理TLS。

以POSIX系統(tǒng)為例,通過pthread_key_create創(chuàng)建的key對進程內所有的線程都可見,但每個線程可以綁定不同的私有數(shù)據(jù)到一個相同的key上,這就意味著整個Chromium可以共享同一個TLS槽,創(chuàng)建一個應用層的TLS表來徹底解決系統(tǒng)級別TLS槽的數(shù)量限制。

具體來說,Chromium TLS系統(tǒng)會首先向OS申請一個key,每個線程都將為這個key綁定一張線程私有的TLS表,Chromium設置了這張表可以容納64個表項。當線程需要一個新的TLS槽時,首先會檢查這個線程是否為key已經(jīng)綁定了TLS表,如果沒有,則需要創(chuàng)建這樣一個TLS表并將其設置為線程私有,然后從表中按順序取一個可用項,并設置新的私有數(shù)據(jù)。不難看出,新的TLS槽并不是向OS申請的,而是向Chromium TLS申請的。

ThreadLocalStorage模板類是新的ChromiumTLS系統(tǒng)中對TLS的抽象,StaticSlot和Slot封裝了初始化Chromium TLS系統(tǒng),創(chuàng)建TLS表以及設置和獲取線程私有數(shù)據(jù)的操作。因此,上述ThreadLocalPointer模板類將從直接使用ThreadLocalPlatform操作TLS,應改為使用ThreadLocalStorage::Slot, 如下:

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>);
};

再次強調,ThreadLocalStorage::Slot只是向Chromium TLS系統(tǒng)申請可用的TLS槽,而不是向系統(tǒng)直接申請。

更多信息

  • Chromium項目的bug列表里已經(jīng)報告了這個問題,參見這里。

  • Chromium TLS實現(xiàn)是最近才提交到Chromium代碼庫中的,參見這里。

  • Android源代碼中對TLS槽數(shù)量的定義在BIONIC_TLS_SLOTS宏常量中,見Android 4.3和Android 4.4。

  • 關于Chromium TLS系統(tǒng)實現(xiàn)細節(jié),感興趣的讀者可讀讀base/threading/thread_local_storage.h/cc等源文件。

  • 關于pthread_key_create,參見Linux Man Page。

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。

本文標題:ChromiumonAndroid:Chromium線程局部存儲系統(tǒng)-創(chuàng)新互聯(lián)
分享地址:http://jinyejixie.com/article48/dischp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設計域名注冊、靜態(tài)網(wǎng)站、標簽優(yōu)化、網(wǎng)站設計公司、搜索引擎優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化
河北区| 故城县| 克什克腾旗| 浦北县| 全椒县| 宝丰县| 丹江口市| 信阳市| 英德市| 建瓯市| 苏尼特左旗| 西平县| 东宁县| 伽师县| 金门县| 运城市| 临湘市| 桦甸市| 民乐县| 额尔古纳市| 汽车| 桃江县| 子洲县| 乌兰浩特市| 古交市| 鄢陵县| 乳源| 凤台县| 进贤县| 宜黄县| 宜丰县| 延津县| 濮阳县| 铁岭县| 平顺县| 宣化县| 荃湾区| 荔浦县| 辽源市| 府谷县| 哈尔滨市|