Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2010 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 47 #include "serialize.h" | 47 #include "serialize.h" |
| 48 #include "simulator.h" | 48 #include "simulator.h" |
| 49 #include "spaces.h" | 49 #include "spaces.h" |
| 50 #include "stub-cache.h" | 50 #include "stub-cache.h" |
| 51 #include "version.h" | 51 #include "version.h" |
| 52 | 52 |
| 53 | 53 |
| 54 namespace v8 { | 54 namespace v8 { |
| 55 namespace internal { | 55 namespace internal { |
| 56 | 56 |
| 57 Mutex* ThreadId::thread_id_process_wide_mutex_ = OS::CreateMutex(); | |
|
Vitaly Repeshko
2011/04/11 19:28:52
I'm worried that this could be accessed before the
Dmitry Lomov
2011/04/11 20:08:35
I think we have the same issue with process_wide_m
Dmitry Lomov
2011/04/11 21:41:14
Done.
| |
| 58 int ThreadId::highest_thread_id_ = 0; | |
| 59 | |
| 60 int ThreadId::AllocateThreadId() { | |
| 61 int new_id; | |
| 62 { | |
| 63 ScopedLock lock(thread_id_process_wide_mutex_); | |
| 64 new_id = ++highest_thread_id_; | |
| 65 } | |
| 66 return new_id; | |
| 67 } | |
| 68 | |
| 69 int ThreadId::GetCurrentThreadId() { | |
| 70 int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_); | |
| 71 if (thread_id == 0) { | |
| 72 thread_id = AllocateThreadId(); | |
| 73 Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id); | |
| 74 } | |
| 75 return thread_id; | |
| 76 } | |
| 57 | 77 |
| 58 // Create a dummy thread that will wait forever on a semaphore. The only | 78 // Create a dummy thread that will wait forever on a semaphore. The only |
| 59 // purpose for this thread is to have some stack area to save essential data | 79 // purpose for this thread is to have some stack area to save essential data |
| 60 // into for use by a stacks only core dump (aka minidump). | 80 // into for use by a stacks only core dump (aka minidump). |
| 61 class PreallocatedMemoryThread: public Thread { | 81 class PreallocatedMemoryThread: public Thread { |
| 62 public: | 82 public: |
| 63 char* data() { | 83 char* data() { |
| 64 if (data_ready_semaphore_ != NULL) { | 84 if (data_ready_semaphore_ != NULL) { |
| 65 // Initial access is guarded until the data has been published. | 85 // Initial access is guarded until the data has been published. |
| 66 data_ready_semaphore_->Wait(); | 86 data_ready_semaphore_->Wait(); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 storage->LinkTo(&free_list_); | 258 storage->LinkTo(&free_list_); |
| 239 } | 259 } |
| 240 | 260 |
| 241 | 261 |
| 242 Isolate* Isolate::default_isolate_ = NULL; | 262 Isolate* Isolate::default_isolate_ = NULL; |
| 243 Thread::LocalStorageKey Isolate::isolate_key_; | 263 Thread::LocalStorageKey Isolate::isolate_key_; |
| 244 Thread::LocalStorageKey Isolate::thread_id_key_; | 264 Thread::LocalStorageKey Isolate::thread_id_key_; |
| 245 Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_; | 265 Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_; |
| 246 Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex(); | 266 Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex(); |
| 247 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL; | 267 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL; |
| 248 Isolate::ThreadId Isolate::highest_thread_id_ = 0; | |
| 249 | 268 |
| 250 | 269 |
| 251 class IsolateInitializer { | 270 class IsolateInitializer { |
| 252 public: | 271 public: |
| 253 IsolateInitializer() { | 272 IsolateInitializer() { |
| 254 Isolate::EnsureDefaultIsolate(); | 273 Isolate::EnsureDefaultIsolate(); |
| 255 } | 274 } |
| 256 }; | 275 }; |
| 257 | 276 |
| 258 static IsolateInitializer* EnsureDefaultIsolateAllocated() { | 277 static IsolateInitializer* EnsureDefaultIsolateAllocated() { |
| 259 // TODO(isolates): Use the system threading API to do this once? | 278 // TODO(isolates): Use the system threading API to do this once? |
| 260 static IsolateInitializer static_initializer; | 279 static IsolateInitializer static_initializer; |
| 261 return &static_initializer; | 280 return &static_initializer; |
| 262 } | 281 } |
| 263 | 282 |
| 264 // This variable only needed to trigger static intialization. | 283 // This variable only needed to trigger static intialization. |
| 265 static IsolateInitializer* static_initializer = EnsureDefaultIsolateAllocated(); | 284 static IsolateInitializer* static_initializer = EnsureDefaultIsolateAllocated(); |
| 266 | 285 |
| 267 | 286 |
| 268 Isolate::ThreadId Isolate::AllocateThreadId() { | 287 |
| 269 ThreadId new_id; | |
| 270 { | |
| 271 ScopedLock lock(process_wide_mutex_); | |
| 272 new_id = ++highest_thread_id_; | |
| 273 } | |
| 274 return new_id; | |
| 275 } | |
| 276 | 288 |
| 277 | 289 |
| 278 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData( | 290 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData( |
| 279 ThreadId thread_id) { | 291 ThreadId thread_id) { |
| 280 ASSERT(thread_id != 0); | 292 ASSERT(!thread_id.Equals(ThreadId::Invalid())); |
| 281 ASSERT(Thread::GetThreadLocalInt(thread_id_key_) == thread_id); | |
| 282 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id); | 293 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id); |
| 283 { | 294 { |
| 284 ScopedLock lock(process_wide_mutex_); | 295 ScopedLock lock(process_wide_mutex_); |
| 285 ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL); | 296 ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL); |
| 286 thread_data_table_->Insert(per_thread); | 297 thread_data_table_->Insert(per_thread); |
| 287 ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread); | 298 ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread); |
| 288 } | 299 } |
| 289 return per_thread; | 300 return per_thread; |
| 290 } | 301 } |
| 291 | 302 |
| 292 | 303 |
| 293 Isolate::PerIsolateThreadData* | 304 Isolate::PerIsolateThreadData* |
| 294 Isolate::FindOrAllocatePerThreadDataForThisThread() { | 305 Isolate::FindOrAllocatePerThreadDataForThisThread() { |
| 295 ThreadId thread_id = Thread::GetThreadLocalInt(thread_id_key_); | 306 ThreadId thread_id = ThreadId::Current(); |
| 296 if (thread_id == 0) { | |
| 297 thread_id = AllocateThreadId(); | |
| 298 Thread::SetThreadLocalInt(thread_id_key_, thread_id); | |
| 299 } | |
| 300 PerIsolateThreadData* per_thread = NULL; | 307 PerIsolateThreadData* per_thread = NULL; |
| 301 { | 308 { |
| 302 ScopedLock lock(process_wide_mutex_); | 309 ScopedLock lock(process_wide_mutex_); |
| 303 per_thread = thread_data_table_->Lookup(this, thread_id); | 310 per_thread = thread_data_table_->Lookup(this, thread_id); |
| 304 if (per_thread == NULL) { | 311 if (per_thread == NULL) { |
| 305 per_thread = AllocatePerIsolateThreadData(thread_id); | 312 per_thread = AllocatePerIsolateThreadData(thread_id); |
| 306 } | 313 } |
| 307 } | 314 } |
| 308 return per_thread; | 315 return per_thread; |
| 309 } | 316 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 return default_isolate_; | 361 return default_isolate_; |
| 355 } | 362 } |
| 356 | 363 |
| 357 | 364 |
| 358 Isolate::ThreadDataTable::ThreadDataTable() | 365 Isolate::ThreadDataTable::ThreadDataTable() |
| 359 : list_(NULL) { | 366 : list_(NULL) { |
| 360 } | 367 } |
| 361 | 368 |
| 362 | 369 |
| 363 Isolate::PerIsolateThreadData* | 370 Isolate::PerIsolateThreadData* |
| 364 Isolate::ThreadDataTable::Lookup(Isolate* isolate, ThreadId thread_id) { | 371 Isolate::ThreadDataTable::Lookup(Isolate* isolate, |
| 372 ThreadId thread_id) { | |
| 365 for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) { | 373 for (PerIsolateThreadData* data = list_; data != NULL; data = data->next_) { |
| 366 if (data->Matches(isolate, thread_id)) return data; | 374 if (data->Matches(isolate, thread_id)) return data; |
| 367 } | 375 } |
| 368 return NULL; | 376 return NULL; |
| 369 } | 377 } |
| 370 | 378 |
| 371 | 379 |
| 372 void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) { | 380 void Isolate::ThreadDataTable::Insert(Isolate::PerIsolateThreadData* data) { |
| 373 if (list_ != NULL) list_->prev_ = data; | 381 if (list_ != NULL) list_->prev_ = data; |
| 374 data->next_ = list_; | 382 data->next_ = list_; |
| 375 list_ = data; | 383 list_ = data; |
| 376 } | 384 } |
| 377 | 385 |
| 378 | 386 |
| 379 void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) { | 387 void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) { |
| 380 if (list_ == data) list_ = data->next_; | 388 if (list_ == data) list_ = data->next_; |
| 381 if (data->next_ != NULL) data->next_->prev_ = data->prev_; | 389 if (data->next_ != NULL) data->next_->prev_ = data->prev_; |
| 382 if (data->prev_ != NULL) data->prev_->next_ = data->next_; | 390 if (data->prev_ != NULL) data->prev_->next_ = data->next_; |
| 383 } | 391 } |
| 384 | 392 |
| 385 | 393 |
| 386 void Isolate::ThreadDataTable::Remove(Isolate* isolate, ThreadId thread_id) { | 394 void Isolate::ThreadDataTable::Remove(Isolate* isolate, |
| 395 ThreadId thread_id) { | |
| 387 PerIsolateThreadData* data = Lookup(isolate, thread_id); | 396 PerIsolateThreadData* data = Lookup(isolate, thread_id); |
| 388 if (data != NULL) { | 397 if (data != NULL) { |
| 389 Remove(data); | 398 Remove(data); |
| 390 } | 399 } |
| 391 } | 400 } |
| 392 | 401 |
| 393 | 402 |
| 394 #ifdef DEBUG | 403 #ifdef DEBUG |
| 395 #define TRACE_ISOLATE(tag) \ | 404 #define TRACE_ISOLATE(tag) \ |
| 396 do { \ | 405 do { \ |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 826 void Isolate::Enter() { | 835 void Isolate::Enter() { |
| 827 Isolate* current_isolate = NULL; | 836 Isolate* current_isolate = NULL; |
| 828 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData(); | 837 PerIsolateThreadData* current_data = CurrentPerIsolateThreadData(); |
| 829 if (current_data != NULL) { | 838 if (current_data != NULL) { |
| 830 current_isolate = current_data->isolate_; | 839 current_isolate = current_data->isolate_; |
| 831 ASSERT(current_isolate != NULL); | 840 ASSERT(current_isolate != NULL); |
| 832 if (current_isolate == this) { | 841 if (current_isolate == this) { |
| 833 ASSERT(Current() == this); | 842 ASSERT(Current() == this); |
| 834 ASSERT(entry_stack_ != NULL); | 843 ASSERT(entry_stack_ != NULL); |
| 835 ASSERT(entry_stack_->previous_thread_data == NULL || | 844 ASSERT(entry_stack_->previous_thread_data == NULL || |
| 836 entry_stack_->previous_thread_data->thread_id() == | 845 entry_stack_->previous_thread_data->thread_id().Equals( |
| 837 Thread::GetThreadLocalInt(thread_id_key_)); | 846 ThreadId::Current())); |
| 838 // Same thread re-enters the isolate, no need to re-init anything. | 847 // Same thread re-enters the isolate, no need to re-init anything. |
| 839 entry_stack_->entry_count++; | 848 entry_stack_->entry_count++; |
| 840 return; | 849 return; |
| 841 } | 850 } |
| 842 } | 851 } |
| 843 | 852 |
| 844 // Threads can have default isolate set into TLS as Current but not yet have | 853 // Threads can have default isolate set into TLS as Current but not yet have |
| 845 // PerIsolateThreadData for it, as it requires more advanced phase of the | 854 // PerIsolateThreadData for it, as it requires more advanced phase of the |
| 846 // initialization. For example, a thread might be the one that system used for | 855 // initialization. For example, a thread might be the one that system used for |
| 847 // static initializers - in this case the default isolate is set in TLS but | 856 // static initializers - in this case the default isolate is set in TLS but |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 865 CHECK(PreInit()); | 874 CHECK(PreInit()); |
| 866 | 875 |
| 867 // In case it's the first time some thread enters the isolate. | 876 // In case it's the first time some thread enters the isolate. |
| 868 set_thread_id(data->thread_id()); | 877 set_thread_id(data->thread_id()); |
| 869 } | 878 } |
| 870 | 879 |
| 871 | 880 |
| 872 void Isolate::Exit() { | 881 void Isolate::Exit() { |
| 873 ASSERT(entry_stack_ != NULL); | 882 ASSERT(entry_stack_ != NULL); |
| 874 ASSERT(entry_stack_->previous_thread_data == NULL || | 883 ASSERT(entry_stack_->previous_thread_data == NULL || |
| 875 entry_stack_->previous_thread_data->thread_id() == | 884 entry_stack_->previous_thread_data->thread_id().Equals( |
| 876 Thread::GetThreadLocalInt(thread_id_key_)); | 885 ThreadId::Current())); |
| 877 | 886 |
| 878 if (--entry_stack_->entry_count > 0) return; | 887 if (--entry_stack_->entry_count > 0) return; |
| 879 | 888 |
| 880 ASSERT(CurrentPerIsolateThreadData() != NULL); | 889 ASSERT(CurrentPerIsolateThreadData() != NULL); |
| 881 ASSERT(CurrentPerIsolateThreadData()->isolate_ == this); | 890 ASSERT(CurrentPerIsolateThreadData()->isolate_ == this); |
| 882 | 891 |
| 883 // Pop the stack. | 892 // Pop the stack. |
| 884 EntryStackItem* item = entry_stack_; | 893 EntryStackItem* item = entry_stack_; |
| 885 entry_stack_ = item->previous_item; | 894 entry_stack_ = item->previous_item; |
| 886 | 895 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 901 | 910 |
| 902 #ifdef DEBUG | 911 #ifdef DEBUG |
| 903 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ | 912 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ |
| 904 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); | 913 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); |
| 905 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) | 914 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) |
| 906 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) | 915 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) |
| 907 #undef ISOLATE_FIELD_OFFSET | 916 #undef ISOLATE_FIELD_OFFSET |
| 908 #endif | 917 #endif |
| 909 | 918 |
| 910 } } // namespace v8::internal | 919 } } // namespace v8::internal |
| OLD | NEW |