Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Unified Diff: base/tracked_objects.cc

Issue 8587031: Avoid any possibility of an Alloc during TLS thread teardown (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/tracked_objects.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/tracked_objects.cc
===================================================================
--- base/tracked_objects.cc (revision 110643)
+++ base/tracked_objects.cc (working copy)
@@ -11,6 +11,7 @@
#include "base/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
+#include "base/port.h"
using base::TimeDelta;
@@ -147,22 +148,18 @@
ThreadData::ThreadData(const std::string& suggested_name)
: incarnation_count_for_pool_(-1),
next_(NULL),
- is_a_worker_thread_(false) {
+ worker_thread_number_(0) {
DCHECK_GE(suggested_name.size(), 0u);
thread_name_ = suggested_name;
PushToHeadOfList(); // Which sets real incarnation_count_for_pool_.
}
-ThreadData::ThreadData()
+ThreadData::ThreadData(size_t thread_number)
: incarnation_count_for_pool_(-1),
next_(NULL),
- is_a_worker_thread_(true) {
- int thread_number;
- {
- base::AutoLock lock(*list_lock_.Pointer());
- thread_number = ++thread_number_counter_;
- }
- base::StringAppendF(&thread_name_, "WorkerThread-%d", thread_number);
+ worker_thread_number_(thread_number) {
+ CHECK_NE(thread_number, 0u);
+ base::StringAppendF(&thread_name_, "WorkerThread-%"PRIuS, thread_number);
PushToHeadOfList(); // Which sets real incarnation_count_for_pool_.
}
@@ -198,19 +195,25 @@
// We must be a worker thread, since we didn't pre-register.
ThreadData* worker_thread_data = NULL;
+ size_t thread_number = 0;
{
base::AutoLock lock(*list_lock_.Pointer());
- if (unregistered_thread_data_pool_ &&
- !unregistered_thread_data_pool_->empty()) {
+ if (!unregistered_thread_data_pool_)
+ unregistered_thread_data_pool_ = new ThreadDataPool;
+ if (!unregistered_thread_data_pool_->empty()) {
worker_thread_data =
const_cast<ThreadData*>(unregistered_thread_data_pool_->top());
unregistered_thread_data_pool_->pop();
+ } else {
+ thread_number = ++thread_number_counter_;
+ unregistered_thread_data_pool_->reserve(thread_number);
}
}
// If we can't find a previously used instance, then we have to create one.
if (!worker_thread_data)
- worker_thread_data = new ThreadData();
+ worker_thread_data = new ThreadData(thread_number);
+ DCHECK_GT(worker_thread_data->worker_thread_number_, 0u);
tls_index_.Set(worker_thread_data);
return worker_thread_data;
@@ -226,18 +229,12 @@
}
void ThreadData::OnThreadTerminationCleanup() const {
- if (!is_a_worker_thread_)
+ if (!worker_thread_number_)
return;
base::AutoLock lock(*list_lock_.Pointer());
if (incarnation_counter_ != incarnation_count_for_pool_)
return; // ThreadData was constructed in an earlier unit test.
-
- // Handle case where we are in unit tests, and have become UNINITIALIZED.
- // In that case, the pool might be NULL. We really should detect this via the
- // incarnation_counter_, but this call is rarely made, so we can afford to
- // code defensively.
- if (!unregistered_thread_data_pool_)
- unregistered_thread_data_pool_ = new ThreadDataPool;
+ // The following will never have to do an allocation.
unregistered_thread_data_pool_->push(this);
}
@@ -562,6 +559,49 @@
}
//------------------------------------------------------------------------------
+// Small partial implementation of a stack that never has to allocate during a
+// push() operation, because it is always prepared to accept the maximum number
+// of ThreadData instances (all the worker thread related instances).
+
+ThreadData::ThreadDataPool::ThreadDataPool() : empty_slot_(0) {};
+ThreadData::ThreadDataPool::~ThreadDataPool() {};
+
+bool ThreadData::ThreadDataPool::empty() const { return empty_slot_ == 0; }
+
+void ThreadData::ThreadDataPool::reserve(size_t largest_worker_pool_number) {
+ // Worker pool numbers start at 1, and exclude 0, so the number is exactly
+ // the least size needed.
+ // Due to asynchronous construction of worker-pool numbers (and associated
+ // ThreadData), we might not hear about the numbers sequentially.
+ if (largest_worker_pool_number > stack_.size())
+ stack_.resize(largest_worker_pool_number);
+}
+
+const ThreadData* ThreadData::ThreadDataPool::top() const {
+ if (empty_slot_ > 0)
+ return stack_[empty_slot_ - 1];
+ NOTREACHED();
+ return NULL;
+}
+
+void ThreadData::ThreadDataPool::push(const ThreadData* thread_data) {
+ if (empty_slot_ < stack_.size()) {
+ stack_[empty_slot_] = thread_data;
+ ++empty_slot_;
+ return;
+ }
+ NOTREACHED();
+}
+
+void ThreadData::ThreadDataPool::pop() {
+ if (empty_slot_ > 0) {
+ --empty_slot_;
+ return;
+ }
+ NOTREACHED();
+}
+
+//------------------------------------------------------------------------------
// Individual 3-tuple of birth (place and thread) along with death thread, and
// the accumulated stats for instances (DeathData).
« no previous file with comments | « base/tracked_objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698