0

Prevent unsafe narrowing: base/task

Bug: 1292951
Change-Id: I0996dc0eff7aaf23753acf7f895c7294bc964189
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3688583
Commit-Queue: danakj <danakj@chromium.org>
Commit-Queue: Peter Kasting <pkasting@chromium.org>
Owners-Override: danakj <danakj@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Auto-Submit: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1011619}
This commit is contained in:
Peter Kasting
2022-06-07 19:52:07 +00:00
committed by Chromium LUCI CQ
parent 77f6f8e62b
commit 12bf330e29
40 changed files with 122 additions and 210 deletions

@ -196,8 +196,8 @@ void TaskAnnotator::MaybeEmitIPCHashAndDelay(perfetto::EventContext& ctx,
auto* annotator = event->set_chrome_task_annotator();
annotator->set_ipc_hash(task.ipc_hash);
if (!task.delayed_run_time.is_null()) {
annotator->set_task_delay_us(
(task.delayed_run_time - task.queue_time).InMicroseconds());
annotator->set_task_delay_us(static_cast<uint64_t>(
(task.delayed_run_time - task.queue_time).InMicroseconds()));
}
}
#endif // BUILDFLAG(ENABLE_BASE_TRACING)

@ -91,14 +91,6 @@ SequenceManager::Settings::Builder::SetPerPrioritySameThreadTaskDelay(
per_priority_same_thread_task_delay_val;
return *this;
}
SequenceManager::Settings::Builder&
SequenceManager::Settings::Builder::SetRandomTaskSelectionSeed(
int random_task_selection_seed_val) {
settings_.random_task_selection_seed = random_task_selection_seed_val;
return *this;
}
#endif // DCHECK_IS_ON()
SequenceManager::Settings SequenceManager::Settings::Builder::Build() {

@ -129,12 +129,6 @@ class BASE_EXPORT SequenceManager {
// Like the above but for same thread posting.
std::array<TimeDelta, TaskQueue::kQueuePriorityCount>
per_priority_same_thread_task_delay;
// If not zero this seeds a PRNG used by the task selection logic to choose
// a random TaskQueue for a given priority rather than the TaskQueue with
// the oldest EnqueueOrder.
int random_task_selection_seed = 0;
#endif // DCHECK_IS_ON()
};
@ -312,12 +306,6 @@ class BASE_EXPORT SequenceManager::Settings::Builder {
Builder& SetPerPrioritySameThreadTaskDelay(
std::array<TimeDelta, TaskQueue::kQueuePriorityCount>
per_priority_same_thread_task_delay);
// If not zero this seeds a PRNG used by the task selection logic to choose a
// random TaskQueue for a given priority rather than the TaskQueue with the
// oldest EnqueueOrder.
Builder& SetRandomTaskSelectionSeed(int random_task_selection_seed);
#endif // DCHECK_IS_ON()
Settings Build();

@ -105,10 +105,6 @@ const double kTaskSamplingRateForRecordingCPUTime = 0.01;
// enabling advanced metrics.
const double kThreadSamplingRateForRecordingCPUTime = 0.0001;
// Magic value to protect against memory corruption and bail out
// early when detected.
constexpr int kMemoryCorruptionSentinelValue = 0xdeadbeef;
void ReclaimMemoryFromQueue(internal::TaskQueueImpl* queue, LazyNow* lazy_now) {
queue->ReclaimMemory(lazy_now->Now());
// If the queue was shut down as a side-effect of reclaiming memory, |queue|
@ -213,7 +209,6 @@ SequenceManagerImpl::SequenceManagerImpl(
add_queue_time_to_tasks_(settings_.add_queue_time_to_tasks),
empty_queues_to_reload_(associated_thread_),
memory_corruption_sentinel_(kMemoryCorruptionSentinelValue),
main_thread_only_(this, associated_thread_, settings_, settings_.clock),
clock_(settings_.clock) {
TRACE_EVENT_OBJECT_CREATED_WITH_ID(
@ -647,8 +642,6 @@ void SequenceManagerImpl::LogTaskDebugInfo(
absl::optional<SequenceManagerImpl::SelectedTask>
SequenceManagerImpl::SelectNextTaskImpl(LazyNow& lazy_now,
SelectTaskOption option) {
CHECK(Validate());
DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("sequence_manager"),
"SequenceManagerImpl::SelectNextTask");
@ -1251,10 +1244,6 @@ bool SequenceManagerImpl::IsType(MessagePumpType type) const {
return settings_.message_loop_type == type;
}
NOINLINE bool SequenceManagerImpl::Validate() {
return memory_corruption_sentinel_ == kMemoryCorruptionSentinelValue;
}
void SequenceManagerImpl::EnableCrashKeys(const char* async_stack_crash_key) {
DCHECK(!main_thread_only().async_stack_crash_key);
#if !BUILDFLAG(IS_NACL)
@ -1295,8 +1284,9 @@ void SequenceManagerImpl::RecordCrashKeys(const PendingTask& pending_task) {
*(--pos) = ' ';
pos = PrependHexAddress(pos - 1, pending_task.posted_from.program_counter());
DCHECK_GE(pos, buffer);
debug::SetCrashKeyString(main_thread_only().async_stack_crash_key,
StringPiece(pos, buffer_end - pos));
debug::SetCrashKeyString(
main_thread_only().async_stack_crash_key,
StringPiece(pos, static_cast<size_t>(buffer_end - pos)));
#endif // BUILDFLAG(IS_NACL)
}

@ -460,12 +460,6 @@ class BASE_EXPORT SequenceManagerImpl
AtomicFlagSet empty_queues_to_reload_;
// A check to bail out early during memory corruption.
// https://crbug.com/757940
bool Validate();
volatile int32_t memory_corruption_sentinel_;
MainThreadOnly main_thread_only_;
MainThreadOnly& main_thread_only() {
DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);

@ -835,21 +835,28 @@ Value TaskQueueImpl::AsValue(TimeTicks now, bool force_verbose) const {
StringPrintf("0x%" PRIx64,
static_cast<uint64_t>(reinterpret_cast<uintptr_t>(this))));
state.SetBoolKey("enabled", IsQueueEnabled());
state.SetIntKey("any_thread_.immediate_incoming_queuesize",
any_thread_.immediate_incoming_queue.size());
state.SetIntKey("delayed_incoming_queue_size",
main_thread_only().delayed_incoming_queue.size());
state.SetIntKey("immediate_work_queue_size",
main_thread_only().immediate_work_queue->Size());
state.SetIntKey("delayed_work_queue_size",
main_thread_only().delayed_work_queue->Size());
// TODO(crbug.com/1334256): Make base::Value able to store an int64_t and
// remove the various static_casts below.
state.SetIntKey(
"any_thread_.immediate_incoming_queuesize",
static_cast<int>(any_thread_.immediate_incoming_queue.size()));
state.SetIntKey(
"delayed_incoming_queue_size",
static_cast<int>(main_thread_only().delayed_incoming_queue.size()));
state.SetIntKey(
"immediate_work_queue_size",
static_cast<int>(main_thread_only().immediate_work_queue->Size()));
state.SetIntKey(
"delayed_work_queue_size",
static_cast<int>(main_thread_only().delayed_work_queue->Size()));
state.SetIntKey("any_thread_.immediate_incoming_queuecapacity",
any_thread_.immediate_incoming_queue.capacity());
state.SetIntKey(
"any_thread_.immediate_incoming_queuecapacity",
static_cast<int>(any_thread_.immediate_incoming_queue.capacity()));
state.SetIntKey("immediate_work_queue_capacity",
immediate_work_queue()->Capacity());
static_cast<int>(immediate_work_queue()->Capacity()));
state.SetIntKey("delayed_work_queue_capacity",
delayed_work_queue()->Capacity());
static_cast<int>(delayed_work_queue()->Capacity()));
if (!main_thread_only().delayed_incoming_queue.empty()) {
TimeDelta delay_to_next_task =
@ -862,7 +869,8 @@ Value TaskQueueImpl::AsValue(TimeTicks now, bool force_verbose) const {
Value fence_state(Value::Type::DICTIONARY);
fence_state.SetIntKey(
"enqueue_order",
main_thread_only().current_fence->task_order().enqueue_order());
static_cast<int>(
main_thread_only().current_fence->task_order().enqueue_order()));
fence_state.SetBoolKey("activated_in_wake_up",
!main_thread_only()
.current_fence->task_order()
@ -1069,7 +1077,7 @@ Value TaskQueueImpl::TaskAsValue(const Task& task, TimeTicks now) {
Value state(Value::Type::DICTIONARY);
state.SetStringKey("posted_from", task.posted_from.ToString());
if (task.enqueue_order_set())
state.SetIntKey("enqueue_order", task.enqueue_order());
state.SetIntKey("enqueue_order", static_cast<int>(task.enqueue_order()));
state.SetIntKey("sequence_num", task.sequence_num);
state.SetBoolKey("nestable", task.nestable == Nestable::kNestable);
state.SetBoolKey("is_high_res", task.is_high_res);
@ -1516,7 +1524,8 @@ void TaskQueueImpl::ReportIpcTaskQueued(
auto* proto = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>()
->set_chrome_task_posted_to_disabled_queue();
proto->set_task_queue_name(task_queue_name);
proto->set_time_since_disabled_ms(time_since_disabled.InMilliseconds());
proto->set_time_since_disabled_ms(
checked_cast<uint64_t>(time_since_disabled.InMilliseconds()));
proto->set_ipc_hash(pending_task.ipc_hash);
proto->set_source_location_iid(
base::trace_event::InternedSourceLocation::Get(

@ -594,7 +594,7 @@ class BASE_EXPORT TaskQueueImpl {
// to index into
// SequenceManager::Settings::per_priority_cross_thread_task_delay to apply
// a priority specific delay for debugging purposes.
int queue_set_index = 0;
size_t queue_set_index = 0;
#endif
TracingOnly tracing_only;

@ -23,12 +23,8 @@ TaskQueueSelector::TaskQueueSelector(
scoped_refptr<AssociatedThreadId> associated_thread,
const SequenceManager::Settings& settings)
: associated_thread_(std::move(associated_thread)),
#if DCHECK_IS_ON()
random_task_selection_(settings.random_task_selection_seed != 0),
#endif
delayed_work_queue_sets_("delayed", this, settings),
immediate_work_queue_sets_("immediate", this, settings) {
}
immediate_work_queue_sets_("immediate", this, settings) {}
TaskQueueSelector::~TaskQueueSelector() = default;
@ -188,21 +184,11 @@ WorkQueue* TaskQueueSelector::SelectWorkQueueToService(
// but the resulting queue must be the lower one.
if (option == SelectTaskOption::kSkipDelayedTask) {
WorkQueue* queue =
#if DCHECK_IS_ON()
random_task_selection_
? ChooseImmediateOnlyWithPriority<SetOperationRandom>(priority)
:
#endif
ChooseImmediateOnlyWithPriority<SetOperationOldest>(priority);
ChooseImmediateOnlyWithPriority<SetOperationOldest>(priority);
return queue;
}
WorkQueue* queue =
#if DCHECK_IS_ON()
random_task_selection_ ? ChooseWithPriority<SetOperationRandom>(priority)
:
#endif
ChooseWithPriority<SetOperationOldest>(priority);
WorkQueue* queue = ChooseWithPriority<SetOperationOldest>(priority);
// If we have selected a delayed task while having an immediate task of the
// same priority, increase the starvation count.
@ -249,7 +235,7 @@ TaskQueueSelector::GetHighestPendingPriority(SelectTaskOption option) const {
}
void TaskQueueSelector::SetImmediateStarvationCountForTest(
size_t immediate_starvation_count) {
int immediate_starvation_count) {
immediate_starvation_count_ = immediate_starvation_count;
}

@ -104,11 +104,11 @@ class BASE_EXPORT TaskQueueSelector : public WorkQueueSets::Observer {
// This method will force select an immediate task if those are being
// starved by delayed tasks.
void SetImmediateStarvationCountForTest(size_t immediate_starvation_count);
void SetImmediateStarvationCountForTest(int immediate_starvation_count);
// Maximum number of delayed tasks tasks which can be run while there's a
// waiting non-delayed task.
static const size_t kMaxDelayedStarvationTasks = 3;
static const int kMaxDelayedStarvationTasks = 3;
// Tracks which priorities are currently active, meaning there are pending
// runnable tasks with that priority. Because there are only a handful of
@ -154,16 +154,6 @@ class BASE_EXPORT TaskQueueSelector : public WorkQueueSets::Observer {
}
};
#if DCHECK_IS_ON()
struct SetOperationRandom {
static absl::optional<WorkQueueAndTaskOrder> GetWithPriority(
const WorkQueueSets& sets,
TaskQueue::QueuePriority priority) {
return sets.GetRandomQueueAndTaskOrderInSet(priority);
}
};
#endif // DCHECK_IS_ON()
template <typename SetOperation>
WorkQueue* ChooseWithPriority(TaskQueue::QueuePriority priority) const {
// Select an immediate work queue if we are starving immediate tasks.
@ -233,10 +223,6 @@ class BASE_EXPORT TaskQueueSelector : public WorkQueueSets::Observer {
scoped_refptr<AssociatedThreadId> associated_thread_;
#if DCHECK_IS_ON()
const bool random_task_selection_ = false;
#endif
// Count of the number of sets (delayed or immediate) for each priority.
// Should only contain 0, 1 or 2.
std::array<int, TaskQueue::kQueuePriorityCount> non_empty_set_counts_ = {{0}};
@ -249,7 +235,7 @@ class BASE_EXPORT TaskQueueSelector : public WorkQueueSets::Observer {
WorkQueueSets delayed_work_queue_sets_;
WorkQueueSets immediate_work_queue_sets_;
size_t immediate_starvation_count_ = 0;
int immediate_starvation_count_ = 0;
raw_ptr<Observer> task_queue_selector_observer_ = nullptr; // Not owned.
};

@ -110,7 +110,8 @@ ThreadController::RunLevelTracker::RunLevel::~RunLevel() {
// thread_controller_sample_metadata_ when yielding back to a parent RunLevel
// (which is active by definition as it is currently running this one).
if (is_nested_) {
thread_controller_sample_metadata_.Set(++thread_controller_active_id_);
thread_controller_sample_metadata_.Set(
static_cast<int64_t>(++thread_controller_active_id_));
}
}
@ -144,7 +145,8 @@ void ThreadController::RunLevelTracker::RunLevel::UpdateState(State new_state) {
TRACE_EVENT_BEGIN0("base", "ThreadController active");
// Overriding the annotation from the previous RunLevel is intentional. Only
// the top RunLevel is ever updated, which holds the relevant state.
thread_controller_sample_metadata_.Set(++thread_controller_active_id_);
thread_controller_sample_metadata_.Set(
static_cast<int64_t>(++thread_controller_active_id_));
} else {
thread_controller_sample_metadata_.Remove();
TRACE_EVENT_END0("base", "ThreadController active");

@ -134,7 +134,10 @@ absl::optional<WakeUp> WakeUpQueue::GetNextDelayedWakeUp() const {
Value WakeUpQueue::AsValue(TimeTicks now) const {
Value state(Value::Type::DICTIONARY);
state.SetStringKey("name", GetName());
state.SetIntKey("registered_delay_count", wake_up_queue_.size());
// TODO(crbug.com/1334256): Make base::Value able to store an int64_t and
// remove this cast.
state.SetIntKey("registered_delay_count",
checked_cast<int>(wake_up_queue_.size()));
if (!wake_up_queue_.empty()) {
TimeDelta delay = wake_up_queue_.top().wake_up.time - now;
state.SetDoubleKey("next_delay_ms", delay.InMillisecondsF());

@ -16,12 +16,7 @@ namespace internal {
WorkQueueSets::WorkQueueSets(const char* name,
Observer* observer,
const SequenceManager::Settings& settings)
: name_(name),
#if DCHECK_IS_ON()
last_rand_(settings.random_task_selection_seed),
#endif
observer_(observer) {
}
: name_(name), observer_(observer) {}
WorkQueueSets::~WorkQueueSets() = default;
@ -159,23 +154,6 @@ WorkQueueSets::GetOldestQueueAndTaskOrderInSet(size_t set_index) const {
return WorkQueueAndTaskOrder(*oldest.value, oldest.key);
}
#if DCHECK_IS_ON()
absl::optional<WorkQueueAndTaskOrder>
WorkQueueSets::GetRandomQueueAndTaskOrderInSet(size_t set_index) const {
DCHECK_LT(set_index, work_queue_heaps_.size());
if (work_queue_heaps_[set_index].empty())
return absl::nullopt;
const OldestTaskOrder& chosen =
work_queue_heaps_[set_index]
.begin()[Random() % work_queue_heaps_[set_index].size()];
#if DCHECK_IS_ON()
absl::optional<TaskOrder> key = chosen.value->GetFrontTaskOrder();
DCHECK(key && chosen.key == *key);
#endif
return WorkQueueAndTaskOrder(*chosen.value, chosen.key);
}
#endif
bool WorkQueueSets::IsSetEmpty(size_t set_index) const {
DCHECK_LT(set_index, work_queue_heaps_.size())
<< " set_index = " << set_index;

@ -79,12 +79,6 @@ class BASE_EXPORT WorkQueueSets {
absl::optional<WorkQueueAndTaskOrder> GetOldestQueueAndTaskOrderInSet(
size_t set_index) const;
#if DCHECK_IS_ON()
// O(1)
absl::optional<WorkQueueAndTaskOrder> GetRandomQueueAndTaskOrderInSet(
size_t set_index) const;
#endif
// O(1)
bool IsSetEmpty(size_t set_index) const;
@ -127,27 +121,6 @@ class BASE_EXPORT WorkQueueSets {
TaskQueue::kQueuePriorityCount>
work_queue_heaps_;
#if DCHECK_IS_ON()
static inline uint64_t MurmurHash3(uint64_t value) {
value ^= value >> 33;
value *= uint64_t{0xFF51AFD7ED558CCD};
value ^= value >> 33;
value *= uint64_t{0xC4CEB9FE1A85EC53};
value ^= value >> 33;
return value;
}
// This is for a debugging feature which lets us randomize task selection. Its
// not for production use.
// TODO(alexclarke): Use a seedable PRNG from ::base if one is added.
uint64_t Random() const {
last_rand_ = MurmurHash3(last_rand_);
return last_rand_;
}
mutable uint64_t last_rand_;
#endif
const raw_ptr<Observer> observer_;
};

@ -43,7 +43,7 @@ SingleThreadTaskExecutor::task_runner() const {
return default_task_queue_->task_runner();
}
void SingleThreadTaskExecutor::SetWorkBatchSize(size_t work_batch_size) {
void SingleThreadTaskExecutor::SetWorkBatchSize(int work_batch_size) {
sequence_manager_->SetWorkBatchSize(work_batch_size);
}

@ -51,7 +51,7 @@ class BASE_EXPORT SingleThreadTaskExecutor {
// asks its delegate to DoWork(). Defaults to 1. Can be increased in some
// scenarios where the native pump (i.e. not MessagePumpType::DEFAULT) has
// high overhead and yielding to native isn't critical.
void SetWorkBatchSize(size_t work_batch_size);
void SetWorkBatchSize(int work_batch_size);
private:
explicit SingleThreadTaskExecutor(MessagePumpType type,

@ -12,12 +12,13 @@
namespace base {
int RecommendedMaxNumberOfThreadsInThreadGroup(int min,
int max,
double cores_multiplier,
int offset) {
const int num_of_cores = SysInfo::NumberOfProcessors();
const int threads = std::ceil<int>(num_of_cores * cores_multiplier) + offset;
size_t RecommendedMaxNumberOfThreadsInThreadGroup(size_t min,
size_t max,
double cores_multiplier,
size_t offset) {
const auto num_of_cores = static_cast<size_t>(SysInfo::NumberOfProcessors());
const size_t threads =
std::ceil<size_t>(num_of_cores * cores_multiplier) + offset;
return clamp(threads, min, max);
}

@ -5,17 +5,19 @@
#ifndef BASE_TASK_THREAD_POOL_INITIALIZATION_UTIL_H_
#define BASE_TASK_THREAD_POOL_INITIALIZATION_UTIL_H_
#include <stddef.h>
#include "base/base_export.h"
namespace base {
// Computes a value that may be used as the maximum number of threads in a
// ThreadGroup. Developers may use other methods to choose this maximum.
BASE_EXPORT int RecommendedMaxNumberOfThreadsInThreadGroup(
int min,
int max,
double cores_multiplier,
int offset);
BASE_EXPORT size_t
RecommendedMaxNumberOfThreadsInThreadGroup(size_t min,
size_t max,
double cores_multiplier,
size_t offset);
} // namespace base

@ -54,6 +54,8 @@ JobTaskSource::State::Value JobTaskSource::State::DecrementWorkerCount() {
JobTaskSource::State::Value JobTaskSource::State::IncrementWorkerCount() {
uint32_t value_before_add =
value_.fetch_add(kWorkerCountIncrement, std::memory_order_relaxed);
// The worker count must not overflow a uint8_t.
DCHECK((value_before_add >> kWorkerCountBitOffset) < ((1 << 8) - 1));
return {value_before_add};
}
@ -296,7 +298,7 @@ uint8_t JobTaskSource::AcquireTaskId() {
uint32_t assigned_task_ids =
assigned_task_ids_.load(std::memory_order_relaxed);
uint32_t new_assigned_task_ids = 0;
uint8_t task_id = 0;
int task_id = 0;
// memory_order_acquire on success, matched with memory_order_release in
// ReleaseTaskId() so that operations done by previous threads that had
// the same task_id become visible to the current thread.
@ -308,7 +310,7 @@ uint8_t JobTaskSource::AcquireTaskId() {
} while (!assigned_task_ids_.compare_exchange_weak(
assigned_task_ids, new_assigned_task_ids, std::memory_order_acquire,
std::memory_order_relaxed));
return task_id;
return static_cast<uint8_t>(task_id);
}
void JobTaskSource::ReleaseTaskId(uint8_t task_id) {

@ -103,7 +103,9 @@ class BASE_EXPORT JobTaskSource : public TaskSource {
<< kWorkerCountBitOffset;
struct Value {
size_t worker_count() const { return value >> kWorkerCountBitOffset; }
uint8_t worker_count() const {
return static_cast<uint8_t>(value >> kWorkerCountBitOffset);
}
// Returns true if canceled.
bool is_canceled() const { return value & kCanceledMask; }

@ -8,6 +8,7 @@
#include "base/check_op.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
namespace base {
namespace internal {
@ -193,12 +194,12 @@ void PriorityQueue::EnableFlushTaskSourcesOnDestroyForTesting() {
}
void PriorityQueue::DecrementNumTaskSourcesForPriority(TaskPriority priority) {
DCHECK_GT(num_task_sources_per_priority_[static_cast<int>(priority)], 0U);
--num_task_sources_per_priority_[static_cast<int>(priority)];
DCHECK_GT(num_task_sources_per_priority_[base::to_underlying(priority)], 0U);
--num_task_sources_per_priority_[base::to_underlying(priority)];
}
void PriorityQueue::IncrementNumTaskSourcesForPriority(TaskPriority priority) {
++num_task_sources_per_priority_[static_cast<int>(priority)];
++num_task_sources_per_priority_[base::to_underlying(priority)];
}
} // namespace internal

@ -387,8 +387,8 @@ ThreadGroupImpl::ThreadGroupImpl(StringPiece histogram_label,
}
void ThreadGroupImpl::Start(
int max_tasks,
int max_best_effort_tasks,
size_t max_tasks,
size_t max_best_effort_tasks,
TimeDelta suggested_reclaim_time,
scoped_refptr<SingleThreadTaskRunner> service_thread_task_runner,
WorkerThreadObserver* worker_thread_observer,
@ -763,7 +763,8 @@ void ThreadGroupImpl::WorkerThreadDelegateImpl::CleanupLockRequired(
if (outer_->num_tasks_before_detach_histogram_) {
executor->ScheduleAddHistogramSample(
outer_->num_tasks_before_detach_histogram_,
worker_only().num_tasks_since_last_detach);
saturated_cast<HistogramBase::Sample>(
worker_only().num_tasks_since_last_detach));
}
worker->Cleanup();
outer_->idle_workers_stack_.Remove(worker);

@ -78,8 +78,8 @@ class BASE_EXPORT ThreadGroupImpl : public ThreadGroup {
// `synchronous_thread_start_for_testing` is true if this ThreadGroupImpl
// should synchronously wait for OnMainEntry() after starting each worker. Can
// only be called once. CHECKs on failure.
void Start(int max_tasks,
int max_best_effort_tasks,
void Start(size_t max_tasks,
size_t max_best_effort_tasks,
TimeDelta suggested_reclaim_time,
scoped_refptr<SingleThreadTaskRunner> service_thread_task_runner,
WorkerThreadObserver* worker_thread_observer,

@ -172,8 +172,7 @@ size_t ThreadGroupNative::GetMaxConcurrentNonBlockedTasksDeprecated() const {
// active at one time. Consequently, we cannot report a true value here.
// Instead, the values were chosen to match
// ThreadPoolInstance::StartWithDefaultParams.
const int num_cores = SysInfo::NumberOfProcessors();
return std::max(3, num_cores - 1);
return static_cast<size_t>(std::max(3, SysInfo::NumberOfProcessors() - 1));
}
void ThreadGroupNative::DidUpdateCanRunPolicy() {

@ -52,7 +52,7 @@ constexpr EnvironmentParams kForegroundPoolEnvironmentParams{
constexpr EnvironmentParams kBackgroundPoolEnvironmentParams{
"Background", base::ThreadPriority::BACKGROUND};
constexpr int kMaxBestEffortTasks = 2;
constexpr size_t kMaxBestEffortTasks = 2;
// Indicates whether BEST_EFFORT tasks are disabled by a command line switch.
bool HasDisableBestEffortTasksSwitch() {
@ -135,7 +135,7 @@ void ThreadPoolImpl::Start(const ThreadPoolInstance::InitParams& init_params,
// The max number of concurrent BEST_EFFORT tasks is |kMaxBestEffortTasks|,
// unless the max number of foreground threads is lower.
const int max_best_effort_tasks =
const size_t max_best_effort_tasks =
std::min(kMaxBestEffortTasks, init_params.max_num_foreground_threads);
// Start the service thread. On platforms that support it (POSIX except NaCL
@ -322,7 +322,7 @@ void ThreadPoolImpl::SetSynchronousThreadStartForTesting(bool enabled) {
g_synchronous_thread_start_for_testing = enabled;
}
int ThreadPoolImpl::GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
size_t ThreadPoolImpl::GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
const TaskTraits& traits) const {
// This method does not support getting the maximum number of BEST_EFFORT
// tasks that can run concurrently in a pool.

@ -66,7 +66,7 @@ class BASE_EXPORT ThreadPoolImpl : public ThreadPoolInstance,
WorkerThreadObserver* worker_thread_observer) override;
bool WasStarted() const final;
bool WasStartedUnsafe() const final;
int GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
size_t GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
const TaskTraits& traits) const override;
void Shutdown() override;
void FlushForTesting() override;

@ -63,7 +63,7 @@ namespace internal {
namespace {
constexpr int kMaxNumForegroundThreads = 4;
constexpr size_t kMaxNumForegroundThreads = 4;
struct TraitsExecutionModePair {
TraitsExecutionModePair(const TaskTraits& traits,
@ -304,7 +304,7 @@ class ThreadPoolImplTestBase : public testing::Test {
}
void StartThreadPool(
int max_num_foreground_threads = kMaxNumForegroundThreads,
size_t max_num_foreground_threads = kMaxNumForegroundThreads,
TimeDelta reclaim_time = Seconds(30)) {
SetupFeatures();
@ -817,10 +817,10 @@ TEST_P(ThreadPoolImplTest,
{MayBlock(), TaskPriority::BEST_EFFORT});
});
const int expected_max =
const size_t expected_max =
GetGroupTypes().foreground_type == test::GroupType::GENERIC
? kMaxNumForegroundThreads
: std::max(3, SysInfo::NumberOfProcessors() - 1);
: static_cast<size_t>(std::max(3, SysInfo::NumberOfProcessors() - 1));
EXPECT_EQ(expected_max,
thread_pool_->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
@ -1437,7 +1437,7 @@ void TestUpdatePrioritySequenceNotScheduled(ThreadPoolImplTest* test,
// thread per pool, it is possible that tasks don't run in order even if
// threads got tasks from the PriorityQueue in order. Therefore, enforce a
// maximum of 1 thread per pool.
constexpr int kLocalMaxNumForegroundThreads = 1;
constexpr size_t kLocalMaxNumForegroundThreads = 1;
test->StartThreadPool(kLocalMaxNumForegroundThreads);
auto task_runners_and_events =

@ -23,7 +23,7 @@ ThreadPoolInstance* g_thread_pool = nullptr;
} // namespace
ThreadPoolInstance::InitParams::InitParams(int max_num_foreground_threads_in)
ThreadPoolInstance::InitParams::InitParams(size_t max_num_foreground_threads_in)
: max_num_foreground_threads(max_num_foreground_threads_in) {}
ThreadPoolInstance::InitParams::~InitParams() = default;
@ -64,8 +64,8 @@ void ThreadPoolInstance::StartWithDefaultParams() {
// * The system is utilized maximally by foreground threads.
// * The main thread is assumed to be busy, cap foreground workers at
// |num_cores - 1|.
const int num_cores = SysInfo::NumberOfProcessors();
const int max_num_foreground_threads = std::max(3, num_cores - 1);
const size_t max_num_foreground_threads =
static_cast<size_t>(std::max(3, SysInfo::NumberOfProcessors() - 1));
Start({max_num_foreground_threads});
}
#endif // !BUILDFLAG(IS_NACL)

@ -57,12 +57,12 @@ class BASE_EXPORT ThreadPoolInstance {
#endif // BUILDFLAG(IS_WIN)
};
InitParams(int max_num_foreground_threads_in);
InitParams(size_t max_num_foreground_threads_in);
~InitParams();
// Maximum number of unblocked tasks that can run concurrently in the
// foreground thread group.
int max_num_foreground_threads;
size_t max_num_foreground_threads;
// Whether COM is initialized when running sequenced and parallel tasks.
CommonThreadPoolEnvironment common_thread_pool_environment =
@ -244,7 +244,7 @@ class BASE_EXPORT ThreadPoolInstance {
// n/GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated() items.
//
// TODO(fdoray): Remove this method. https://crbug.com/687264
virtual int GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
virtual size_t GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
const TaskTraits& traits) const = 0;
// Starts/stops a fence that prevents scheduling of tasks of any / BEST_EFFORT

@ -148,7 +148,7 @@ class ThreadPoolPerfTest : public testing::Test {
void StartThreadPool(size_t num_running_threads,
size_t num_posting_threads,
base::RepeatingClosure post_action) {
ThreadPoolInstance::Get()->Start({static_cast<int>(num_running_threads)});
ThreadPoolInstance::Get()->Start({num_running_threads});
base::RepeatingClosure done = BarrierClosure(
num_posting_threads,

@ -1453,7 +1453,7 @@ bool TestLauncher::Init(CommandLine* command_line) {
fprintf(stdout, "Using %zu parallel jobs.\n", parallel_jobs_);
fflush(stdout);
CreateAndStartThreadPool(static_cast<int>(parallel_jobs_));
CreateAndStartThreadPool(parallel_jobs_);
std::vector<std::string> positive_file_filter;
std::vector<std::string> positive_gtest_filter;
@ -1747,7 +1747,7 @@ bool TestLauncher::ProcessAndValidateTests() {
return result;
}
void TestLauncher::CreateAndStartThreadPool(int num_parallel_jobs) {
void TestLauncher::CreateAndStartThreadPool(size_t num_parallel_jobs) {
base::ThreadPoolInstance::Create("TestLauncher");
base::ThreadPoolInstance::Get()->Start({num_parallel_jobs});
}

@ -221,7 +221,7 @@ class TestLauncher {
// Creates and starts a ThreadPoolInstance with |num_parallel_jobs| dedicated
// to foreground blocking tasks (corresponds to the traits used to launch and
// wait for child processes). virtual to mock in testing.
virtual void CreateAndStartThreadPool(int num_parallel_jobs);
virtual void CreateAndStartThreadPool(size_t num_parallel_jobs);
// Callback to receive result of a test.
// |result_file| is a path to xml file written by child process.

@ -73,7 +73,7 @@ class MockTestLauncher : public TestLauncher {
size_t parallel_jobs)
: TestLauncher(launcher_delegate, parallel_jobs) {}
void CreateAndStartThreadPool(int parallel_jobs) override {}
void CreateAndStartThreadPool(size_t parallel_jobs) override {}
MOCK_METHOD4(LaunchChildGTestProcess,
void(scoped_refptr<TaskRunner> task_runner,

@ -228,8 +228,8 @@ void ComServerApp::InitializeThreadPool() {
base::ThreadPoolInstance::Create(kThreadPoolName);
// Reuses the logic in base::ThreadPoolInstance::StartWithDefaultParams.
const int num_cores = base::SysInfo::NumberOfProcessors();
const int max_num_foreground_threads = std::max(3, num_cores - 1);
const size_t max_num_foreground_threads =
static_cast<size_t>(std::max(3, base::SysInfo::NumberOfProcessors() - 1));
base::ThreadPoolInstance::InitParams init_params(max_num_foreground_threads);
init_params.common_thread_pool_environment = base::ThreadPoolInstance::
InitParams::CommonThreadPoolEnvironment::COM_MTA;

@ -71,7 +71,7 @@ TEST_F(BrowserMainLoopTest, CreateThreadsInSingleProcess) {
EXPECT_GE(base::ThreadPoolInstance::Get()
->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
{base::TaskPriority::USER_VISIBLE}),
base::SysInfo::NumberOfProcessors() - 1);
static_cast<size_t>(base::SysInfo::NumberOfProcessors() - 1));
browser_main_loop.ShutdownThreadsAndCleanUp();
BrowserTaskExecutor::ResetForTesting();
}

@ -49,16 +49,16 @@ std::unique_ptr<base::FieldTrialList> SetUpFieldTrialsAndFeatureList() {
namespace {
#if BUILDFLAG(IS_ANDROID)
// Mobile config, for iOS see ios/web/app/web_main_loop.cc.
constexpr int kThreadPoolDefaultMin = 6;
constexpr int kThreadPoolMax = 8;
constexpr size_t kThreadPoolDefaultMin = 6;
constexpr size_t kThreadPoolMax = 8;
constexpr double kThreadPoolCoresMultiplier = 0.6;
constexpr int kThreadPoolOffset = 0;
constexpr size_t kThreadPoolOffset = 0;
#else
// Desktop config.
constexpr int kThreadPoolDefaultMin = 16;
constexpr int kThreadPoolMax = 32;
constexpr size_t kThreadPoolDefaultMin = 16;
constexpr size_t kThreadPoolMax = 32;
constexpr double kThreadPoolCoresMultiplier = 0.6;
constexpr int kThreadPoolOffset = 0;
constexpr size_t kThreadPoolOffset = 0;
#endif
const base::Feature kBrowserThreadPoolAdjustment{
@ -73,7 +73,7 @@ const base::FeatureParam<int> kBrowserThreadPoolMin{
void StartBrowserThreadPool() {
// Ensure we always support at least one thread regardless of the field trial
// param setting.
int min = std::max(kBrowserThreadPoolMin.Get(), 1);
auto min = static_cast<size_t>(std::max(kBrowserThreadPoolMin.Get(), 1));
base::ThreadPoolInstance::InitParams thread_pool_init_params = {
base::RecommendedMaxNumberOfThreadsInThreadGroup(
min, kThreadPoolMax, kThreadPoolCoresMultiplier, kThreadPoolOffset)};

@ -10,9 +10,10 @@
namespace content {
int GetMinForegroundThreadsInRendererThreadPool() {
size_t GetMinForegroundThreadsInRendererThreadPool() {
// Assume a busy main thread.
return std::max(1, base::SysInfo::NumberOfProcessors() - 1);
return static_cast<size_t>(
std::max(1, base::SysInfo::NumberOfProcessors() - 1));
}
} // namespace content

@ -5,11 +5,13 @@
#ifndef CONTENT_COMMON_THREAD_POOL_UTIL_H_
#define CONTENT_COMMON_THREAD_POOL_UTIL_H_
#include <stddef.h>
namespace content {
// Returns the minimum number of foreground threads that the ThreadPool
// must have in a process that runs a renderer.
int GetMinForegroundThreadsInRendererThreadPool();
size_t GetMinForegroundThreadsInRendererThreadPool();
} // namespace content

@ -72,7 +72,7 @@ void SetV8FlagIfHasSwitch(const char* switch_name, const char* v8_flag) {
std::unique_ptr<base::ThreadPoolInstance::InitParams>
GetThreadPoolInitParams() {
constexpr int kMaxNumThreadsInForegroundPoolLowerBound = 3;
constexpr size_t kMaxNumThreadsInForegroundPoolLowerBound = 3;
return std::make_unique<base::ThreadPoolInstance::InitParams>(
std::max(kMaxNumThreadsInForegroundPoolLowerBound,
content::GetMinForegroundThreadsInRendererThreadPool()));

@ -395,7 +395,7 @@ std::shared_ptr<v8::TaskRunner> V8Platform::GetForegroundTaskRunner(
int V8Platform::NumberOfWorkerThreads() {
// V8Platform assumes the scheduler uses the same set of workers for default
// and user blocking tasks.
const int num_foreground_workers =
const size_t num_foreground_workers =
base::ThreadPoolInstance::Get()
->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
kDefaultTaskTraits);
@ -403,7 +403,7 @@ int V8Platform::NumberOfWorkerThreads() {
base::ThreadPoolInstance::Get()
->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
kBlockingTaskTraits));
return std::max(1, num_foreground_workers);
return std::max(1, static_cast<int>(num_foreground_workers));
}
void V8Platform::CallOnWorkerThread(std::unique_ptr<v8::Task> task) {

@ -72,10 +72,10 @@ void DestroyNetworkChangeNotifier() {
void StartThreadPool() {
static dispatch_once_t once_token;
dispatch_once(&once_token, ^{
constexpr int kMinForegroundThreads = 6;
constexpr int kMaxForegroundThreads = 16;
constexpr size_t kMinForegroundThreads = 6;
constexpr size_t kMaxForegroundThreads = 16;
constexpr double kCoreMultiplierForegroundThreads = 0.6;
constexpr int kOffsetForegroundThreads = 0;
constexpr size_t kOffsetForegroundThreads = 0;
base::ThreadPoolInstance::Get()->Start(
{base::RecommendedMaxNumberOfThreadsInThreadGroup(
kMinForegroundThreads, kMaxForegroundThreads,