mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 13:56:29 +00:00
Bug 1121269 - Use a LinkedList to store TLS keys for Nuwa, and allocate the first element in a static buffer. r=thinker
This commit is contained in:
parent
c18398b98d
commit
49deb404a9
@ -23,6 +23,7 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <vector>
|
||||
|
||||
#include "mozilla/Alignment.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/TaggedAnonymousMemory.h"
|
||||
#include "Nuwa.h"
|
||||
@ -215,8 +216,41 @@ RunCustomRecreation() {
|
||||
static std::vector<nuwa_construct_t> sConstructors;
|
||||
static std::vector<nuwa_construct_t> sFinalConstructors;
|
||||
|
||||
typedef std::map<pthread_key_t, void (*)(void *)> TLSKeySet;
|
||||
static TLSKeySet sTLSKeys;
|
||||
class TLSKey
|
||||
: public std::pair<pthread_key_t, void (*)(void*)>
|
||||
, public LinkedListElement<TLSKey>
|
||||
{
|
||||
public:
|
||||
TLSKey() {}
|
||||
|
||||
TLSKey(pthread_key_t aKey, void (*aDestructor)(void*))
|
||||
: std::pair<pthread_key_t, void (*)(void*)>(aKey, aDestructor)
|
||||
{}
|
||||
|
||||
static void* operator new(size_t size) {
|
||||
if (sUsed)
|
||||
return ::operator new(size);
|
||||
sUsed = true;
|
||||
return sFirstElement.addr();
|
||||
}
|
||||
|
||||
static void operator delete(void* ptr) {
|
||||
if (ptr == sFirstElement.addr()) {
|
||||
sUsed = false;
|
||||
return;
|
||||
}
|
||||
::operator delete(ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
static bool sUsed;
|
||||
static AlignedStorage2<TLSKey> sFirstElement;
|
||||
};
|
||||
|
||||
bool TLSKey::sUsed = false;
|
||||
AlignedStorage2<TLSKey> TLSKey::sFirstElement;
|
||||
|
||||
static AutoCleanLinkedList<TLSKey> sTLSKeys;
|
||||
|
||||
/**
|
||||
* This mutex is used to block the running threads and freeze their contexts.
|
||||
@ -232,13 +266,13 @@ static int sThreadFreezeCount = 0;
|
||||
|
||||
// Bug 1008254: LinkedList's destructor asserts that the list is empty.
|
||||
// But here, on exit, when the global sAllThreads list
|
||||
// is destroyed, it may or may be empty. Bug 1008254 comment 395 has a log
|
||||
// is destroyed, it may or may not be empty. Bug 1008254 comment 395 has a log
|
||||
// when there were 8 threads remaining on exit. So this assertion was
|
||||
// intermittently (almost every second time) failing.
|
||||
// As a work-around to avoid this intermittent failure, we clear the list on
|
||||
// exit just before it gets destroyed. This is the only purpose of that
|
||||
// AllThreadsListType subclass.
|
||||
struct AllThreadsListType : public LinkedList<thread_info_t>
|
||||
struct AllThreadsListType : public AutoCleanLinkedList<thread_info_t>
|
||||
{
|
||||
~AllThreadsListType()
|
||||
{
|
||||
@ -263,7 +297,6 @@ struct AllThreadsListType : public LinkedList<thread_info_t>
|
||||
sThreadCount,
|
||||
sThreadFreezeCount);
|
||||
}
|
||||
clear();
|
||||
}
|
||||
};
|
||||
static AllThreadsListType sAllThreads;
|
||||
@ -297,7 +330,7 @@ static bool sForkWaitCondChanged = false;
|
||||
* This mutex protects the access to sTLSKeys, which keeps track of existing
|
||||
* TLS Keys.
|
||||
*/
|
||||
static pthread_mutex_t sTLSKeyLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static pthread_mutex_t sTLSKeyLock = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
|
||||
static int sThreadSkipCount = 0;
|
||||
|
||||
static thread_info_t *
|
||||
@ -684,11 +717,9 @@ __wrap_pthread_create(pthread_t *thread,
|
||||
*/
|
||||
static void
|
||||
SaveTLSInfo(thread_info_t *tinfo) {
|
||||
REAL(pthread_mutex_lock)(&sTLSKeyLock);
|
||||
MOZ_RELEASE_ASSERT(REAL(pthread_mutex_lock)(&sTLSKeyLock) == 0);
|
||||
tinfo->tlsInfo.clear();
|
||||
for (TLSKeySet::const_iterator it = sTLSKeys.begin();
|
||||
it != sTLSKeys.end();
|
||||
it++) {
|
||||
for (TLSKey *it = sTLSKeys.getFirst(); it != nullptr; it = it->getNext()) {
|
||||
void *value = pthread_getspecific(it->first);
|
||||
if (value == nullptr) {
|
||||
continue;
|
||||
@ -697,7 +728,7 @@ SaveTLSInfo(thread_info_t *tinfo) {
|
||||
pthread_key_t key = it->first;
|
||||
tinfo->tlsInfo.push_back(TLSInfoList::value_type(key, value));
|
||||
}
|
||||
pthread_mutex_unlock(&sTLSKeyLock);
|
||||
MOZ_RELEASE_ASSERT(pthread_mutex_unlock(&sTLSKeyLock) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -726,9 +757,9 @@ __wrap_pthread_key_create(pthread_key_t *key, void (*destructor)(void*)) {
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
REAL(pthread_mutex_lock)(&sTLSKeyLock);
|
||||
sTLSKeys.insert(TLSKeySet::value_type(*key, destructor));
|
||||
pthread_mutex_unlock(&sTLSKeyLock);
|
||||
MOZ_RELEASE_ASSERT(REAL(pthread_mutex_lock)(&sTLSKeyLock) == 0);
|
||||
sTLSKeys.insertBack(new TLSKey(*key, destructor));
|
||||
MOZ_RELEASE_ASSERT(pthread_mutex_unlock(&sTLSKeyLock) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -741,9 +772,14 @@ __wrap_pthread_key_delete(pthread_key_t key) {
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
REAL(pthread_mutex_lock)(&sTLSKeyLock);
|
||||
sTLSKeys.erase(key);
|
||||
pthread_mutex_unlock(&sTLSKeyLock);
|
||||
MOZ_RELEASE_ASSERT(REAL(pthread_mutex_lock)(&sTLSKeyLock) == 0);
|
||||
for (TLSKey *it = sTLSKeys.getFirst(); it != nullptr; it = it->getNext()) {
|
||||
if (key == it->first) {
|
||||
delete it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(pthread_mutex_unlock(&sTLSKeyLock) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user