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

Side by Side Diff: src/heap/page-parallel-job.h

Issue 1998213002: Workaround for glibc semaphore bug. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 7 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef V8_HEAP_PAGE_PARALLEL_JOB_ 5 #ifndef V8_HEAP_PAGE_PARALLEL_JOB_
6 #define V8_HEAP_PAGE_PARALLEL_JOB_ 6 #define V8_HEAP_PAGE_PARALLEL_JOB_
7 7
8 #include "src/allocation.h" 8 #include "src/allocation.h"
9 #include "src/cancelable-task.h" 9 #include "src/cancelable-task.h"
10 #include "src/utils.h" 10 #include "src/utils.h"
(...skipping 15 matching lines...) Expand all
26 // PerPageData page_data) 26 // PerPageData page_data)
27 // The function should return true iff processing succeeded. 27 // The function should return true iff processing succeeded.
28 // - static const bool NeedSequentialFinalization 28 // - static const bool NeedSequentialFinalization
29 // - static void FinalizePageSequentially(Heap* heap, 29 // - static void FinalizePageSequentially(Heap* heap,
30 // bool processing_succeeded, 30 // bool processing_succeeded,
31 // MemoryChunk* page, 31 // MemoryChunk* page,
32 // PerPageData page_data) 32 // PerPageData page_data)
33 template <typename JobTraits> 33 template <typename JobTraits>
34 class PageParallelJob { 34 class PageParallelJob {
35 public: 35 public:
36 PageParallelJob(Heap* heap, CancelableTaskManager* cancelable_task_manager) 36 // PageParallelJob cannot dynamically create a semaphore because of a bug in
37 // glibc. See http://crbug.com/609249 and
38 // https://sourceware.org/bugzilla/show_bug.cgi?id=12674.
39 // The caller must provide a semaphore with value 0 and ensure that
40 // the lifetime of the semaphore is the same as the lifetime of the Isolate.
41 // It is guaranteed that the semaphore value will be 0 after Run() call.
42 PageParallelJob(Heap* heap, CancelableTaskManager* cancelable_task_manager,
43 base::Semaphore* semaphore)
37 : heap_(heap), 44 : heap_(heap),
38 cancelable_task_manager_(cancelable_task_manager), 45 cancelable_task_manager_(cancelable_task_manager),
39 items_(nullptr), 46 items_(nullptr),
40 num_items_(0), 47 num_items_(0),
41 num_tasks_(0), 48 num_tasks_(0),
42 pending_tasks_(new base::Semaphore(0)), 49 pending_tasks_(semaphore) {}
43 finished_tasks_(new base::AtomicNumber<int>(0)) {}
44 50
45 ~PageParallelJob() { 51 ~PageParallelJob() {
46 Item* item = items_; 52 Item* item = items_;
47 while (item != nullptr) { 53 while (item != nullptr) {
48 Item* next = item->next; 54 Item* next = item->next;
49 delete item; 55 delete item;
50 item = next; 56 item = next;
51 } 57 }
52 delete pending_tasks_;
53 delete finished_tasks_;
54 } 58 }
55 59
56 void AddPage(MemoryChunk* chunk, typename JobTraits::PerPageData data) { 60 void AddPage(MemoryChunk* chunk, typename JobTraits::PerPageData data) {
57 Item* item = new Item(chunk, data, items_); 61 Item* item = new Item(chunk, data, items_);
58 items_ = item; 62 items_ = item;
59 ++num_items_; 63 ++num_items_;
60 } 64 }
61 65
62 int NumberOfPages() { return num_items_; } 66 int NumberOfPages() { return num_items_; }
63 67
(...skipping 14 matching lines...) Expand all
78 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())); 82 V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads()));
79 num_tasks_ = Max(1, Min(num_tasks, max_num_tasks)); 83 num_tasks_ = Max(1, Min(num_tasks, max_num_tasks));
80 int items_per_task = (num_items_ + num_tasks_ - 1) / num_tasks_; 84 int items_per_task = (num_items_ + num_tasks_ - 1) / num_tasks_;
81 int start_index = 0; 85 int start_index = 0;
82 Task* main_task = nullptr; 86 Task* main_task = nullptr;
83 for (int i = 0; i < num_tasks_; i++, start_index += items_per_task) { 87 for (int i = 0; i < num_tasks_; i++, start_index += items_per_task) {
84 if (start_index >= num_items_) { 88 if (start_index >= num_items_) {
85 start_index -= num_items_; 89 start_index -= num_items_;
86 } 90 }
87 Task* task = new Task(heap_, items_, num_items_, start_index, 91 Task* task = new Task(heap_, items_, num_items_, start_index,
88 pending_tasks_, per_task_data_callback(i), this); 92 pending_tasks_, per_task_data_callback(i));
89 task_ids[i] = task->id(); 93 task_ids[i] = task->id();
90 if (i > 0) { 94 if (i > 0) {
91 V8::GetCurrentPlatform()->CallOnBackgroundThread( 95 V8::GetCurrentPlatform()->CallOnBackgroundThread(
92 task, v8::Platform::kShortRunningTask); 96 task, v8::Platform::kShortRunningTask);
93 } else { 97 } else {
94 main_task = task; 98 main_task = task;
95 } 99 }
96 } 100 }
97 // Contribute on main thread. 101 // Contribute on main thread.
98 main_task->Run(); 102 main_task->Run();
99 delete main_task; 103 delete main_task;
100 int aborted_tasks = 0;
ulan 2016/05/20 11:28:24 All removed lines below are instrumentation code.
101 // Wait for background tasks. 104 // Wait for background tasks.
102 for (int i = 0; i < num_tasks_; i++) { 105 for (int i = 0; i < num_tasks_; i++) {
103 if (!cancelable_task_manager_->TryAbort(task_ids[i])) { 106 if (!cancelable_task_manager_->TryAbort(task_ids[i])) {
104 pending_tasks_->Wait(); 107 pending_tasks_->Wait();
105 } else {
106 ++aborted_tasks;
107 } 108 }
108 } 109 }
109 int finished_tasks = finished_tasks_->Value();
110 // TODO(ulan): Remove this check after investigation of crbug.com/609249.
111 CHECK_EQ(aborted_tasks + finished_tasks, num_tasks_);
112 if (JobTraits::NeedSequentialFinalization) { 110 if (JobTraits::NeedSequentialFinalization) {
113 Item* item = items_; 111 Item* item = items_;
114 while (item != nullptr) { 112 while (item != nullptr) {
115 bool success = (item->state.Value() == kFinished); 113 bool success = (item->state.Value() == kFinished);
116 JobTraits::FinalizePageSequentially(heap_, item->chunk, success, 114 JobTraits::FinalizePageSequentially(heap_, item->chunk, success,
117 item->data); 115 item->data);
118 item = item->next; 116 item = item->next;
119 } 117 }
120 } 118 }
121 } 119 }
122 120
123 void NotifyFinishedTask() { finished_tasks_->Increment(1); }
124
125 private: 121 private:
126 static const int kMaxNumberOfTasks = 10; 122 static const int kMaxNumberOfTasks = 10;
127 123
128 enum ProcessingState { kAvailable, kProcessing, kFinished, kFailed }; 124 enum ProcessingState { kAvailable, kProcessing, kFinished, kFailed };
129 125
130 struct Item : public Malloced { 126 struct Item : public Malloced {
131 Item(MemoryChunk* chunk, typename JobTraits::PerPageData data, Item* next) 127 Item(MemoryChunk* chunk, typename JobTraits::PerPageData data, Item* next)
132 : chunk(chunk), state(kAvailable), data(data), next(next) {} 128 : chunk(chunk), state(kAvailable), data(data), next(next) {}
133 MemoryChunk* chunk; 129 MemoryChunk* chunk;
134 base::AtomicValue<ProcessingState> state; 130 base::AtomicValue<ProcessingState> state;
135 typename JobTraits::PerPageData data; 131 typename JobTraits::PerPageData data;
136 Item* next; 132 Item* next;
137 }; 133 };
138 134
139 class Task : public CancelableTask { 135 class Task : public CancelableTask {
140 public: 136 public:
141 Task(Heap* heap, Item* items, int num_items, int start_index, 137 Task(Heap* heap, Item* items, int num_items, int start_index,
142 base::Semaphore* on_finish, typename JobTraits::PerTaskData data, 138 base::Semaphore* on_finish, typename JobTraits::PerTaskData data)
143 PageParallelJob<JobTraits>* job)
144 : CancelableTask(heap->isolate()), 139 : CancelableTask(heap->isolate()),
145 heap_(heap), 140 heap_(heap),
146 items_(items), 141 items_(items),
147 num_items_(num_items), 142 num_items_(num_items),
148 start_index_(start_index), 143 start_index_(start_index),
149 on_finish_(on_finish), 144 on_finish_(on_finish),
150 data_(data), 145 data_(data) {}
151 job_(job) {}
152 146
153 virtual ~Task() {} 147 virtual ~Task() {}
154 148
155 private: 149 private:
156 // v8::internal::CancelableTask overrides. 150 // v8::internal::CancelableTask overrides.
157 void RunInternal() override { 151 void RunInternal() override {
158 // Each task starts at a different index to improve parallelization. 152 // Each task starts at a different index to improve parallelization.
159 Item* current = items_; 153 Item* current = items_;
160 int skip = start_index_; 154 int skip = start_index_;
161 while (skip-- > 0) { 155 while (skip-- > 0) {
162 current = current->next; 156 current = current->next;
163 } 157 }
164 for (int i = 0; i < num_items_; i++) { 158 for (int i = 0; i < num_items_; i++) {
165 if (current->state.TrySetValue(kAvailable, kProcessing)) { 159 if (current->state.TrySetValue(kAvailable, kProcessing)) {
166 bool success = JobTraits::ProcessPageInParallel( 160 bool success = JobTraits::ProcessPageInParallel(
167 heap_, data_, current->chunk, current->data); 161 heap_, data_, current->chunk, current->data);
168 current->state.SetValue(success ? kFinished : kFailed); 162 current->state.SetValue(success ? kFinished : kFailed);
169 } 163 }
170 current = current->next; 164 current = current->next;
171 // Wrap around if needed. 165 // Wrap around if needed.
172 if (current == nullptr) { 166 if (current == nullptr) {
173 current = items_; 167 current = items_;
174 } 168 }
175 } 169 }
176 job_->NotifyFinishedTask(); 170 on_finish_->Signal();
177 on_finish_->Signal("PageParallelJob::Task::RunInternal");
178 } 171 }
179 172
180 Heap* heap_; 173 Heap* heap_;
181 Item* items_; 174 Item* items_;
182 int num_items_; 175 int num_items_;
183 int start_index_; 176 int start_index_;
184 base::Semaphore* on_finish_; 177 base::Semaphore* on_finish_;
185 typename JobTraits::PerTaskData data_; 178 typename JobTraits::PerTaskData data_;
186 PageParallelJob<JobTraits>* job_;
187 DISALLOW_COPY_AND_ASSIGN(Task); 179 DISALLOW_COPY_AND_ASSIGN(Task);
188 }; 180 };
189 181
190 Heap* heap_; 182 Heap* heap_;
191 CancelableTaskManager* cancelable_task_manager_; 183 CancelableTaskManager* cancelable_task_manager_;
192 Item* items_; 184 Item* items_;
193 int num_items_; 185 int num_items_;
194 int num_tasks_; 186 int num_tasks_;
195 base::Semaphore* pending_tasks_; 187 base::Semaphore* pending_tasks_;
196 base::AtomicNumber<int>* finished_tasks_;
197 DISALLOW_COPY_AND_ASSIGN(PageParallelJob); 188 DISALLOW_COPY_AND_ASSIGN(PageParallelJob);
198 }; 189 };
199 190
200 } // namespace internal 191 } // namespace internal
201 } // namespace v8 192 } // namespace v8
202 193
203 #endif // V8_HEAP_PAGE_PARALLEL_JOB_ 194 #endif // V8_HEAP_PAGE_PARALLEL_JOB_
OLDNEW
« src/heap/mark-compact.h ('K') | « src/heap/mark-compact.cc ('k') | src/heap/spaces.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698