From d18051870e8e2a5f55237a2c11fde75f46082639 Mon Sep 17 00:00:00 2001 From: Jeff Brown Date: Tue, 21 Sep 2010 15:11:18 -0700 Subject: [PATCH] Looper: use pthread_once for TLS key initialization. Also fix a Valgrind complaint by zeroing out the entire epoll event struct since otherwise the data field union would be partly uninitialized (but not in a harmful way). Change-Id: I2091ce517e87fcad7c9caf90e2c5e4854a7ca465 --- include/utils/Looper.h | 1 + libs/utils/Looper.cpp | 29 ++++++++++++++--------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/utils/Looper.h b/include/utils/Looper.h index 7d908669e..3f00b788c 100644 --- a/include/utils/Looper.h +++ b/include/utils/Looper.h @@ -205,6 +205,7 @@ private: int pollInner(int timeoutMillis); + static void initTLSKey(); static void threadDestructor(void *st); }; diff --git a/libs/utils/Looper.cpp b/libs/utils/Looper.cpp index b46279efc..d2dd6eb48 100644 --- a/libs/utils/Looper.cpp +++ b/libs/utils/Looper.cpp @@ -24,16 +24,15 @@ namespace android { -static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; -static bool gHaveTLS = false; -static pthread_key_t gTLS = 0; - // Hint for number of file descriptors to be associated with the epoll instance. static const int EPOLL_SIZE_HINT = 8; // Maximum number of file descriptors for which to retrieve poll events each iteration. static const int EPOLL_MAX_EVENTS = 16; +static pthread_once_t gTLSOnce = PTHREAD_ONCE_INIT; +static pthread_key_t gTLSKey = 0; + Looper::Looper(bool allowNonCallbacks) : mAllowNonCallbacks(allowNonCallbacks), mResponseIndex(0) { @@ -56,6 +55,7 @@ Looper::Looper(bool allowNonCallbacks) : errno); struct epoll_event eventItem; + memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union eventItem.events = EPOLLIN; eventItem.data.fd = mWakeReadPipeFd; result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, & eventItem); @@ -69,6 +69,11 @@ Looper::~Looper() { close(mEpollFd); } +void Looper::initTLSKey() { + int result = pthread_key_create(& gTLSKey, threadDestructor); + LOG_ALWAYS_FATAL_IF(result != 0, "Could not allocate TLS key."); +} + void Looper::threadDestructor(void *st) { Looper* const self = static_cast(st); if (self != NULL) { @@ -83,7 +88,7 @@ void Looper::setForThread(const sp& looper) { looper->incStrong((void*)threadDestructor); } - pthread_setspecific(gTLS, looper.get()); + pthread_setspecific(gTLSKey, looper.get()); if (old != NULL) { old->decStrong((void*)threadDestructor); @@ -91,17 +96,10 @@ void Looper::setForThread(const sp& looper) { } sp Looper::getForThread() { - if (!gHaveTLS) { - pthread_mutex_lock(&gTLSMutex); - if (pthread_key_create(&gTLS, threadDestructor) != 0) { - pthread_mutex_unlock(&gTLSMutex); - return NULL; - } - gHaveTLS = true; - pthread_mutex_unlock(&gTLSMutex); - } + int result = pthread_once(& gTLSOnce, initTLSKey); + LOG_ALWAYS_FATAL_IF(result != 0, "pthread_once failed"); - return (Looper*)pthread_getspecific(gTLS); + return (Looper*)pthread_getspecific(gTLSKey); } sp Looper::prepare(int opts) { @@ -331,6 +329,7 @@ int Looper::addFd(int fd, int ident, int events, ALooper_callbackFunc callback, request.data = data; struct epoll_event eventItem; + memset(& eventItem, 0, sizeof(epoll_event)); // zero out unused members of data field union eventItem.events = epollEvents; eventItem.data.fd = fd;