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

Side by Side Diff: src/platform-cygwin.cc

Issue 6525028: Cygwin support (Closed)
Patch Set: Use sampler from platform-win32.cc Created 9 years, 10 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
(Empty)
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
Vyacheslav Egorov (Chromium) 2011/02/17 14:00:48 2011
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 // Platform specific code for Cygwin goes here. For the POSIX comaptible parts
29 // the implementation is in platform-posix.cc.
30
31 #include <errno.h>
32 #include <pthread.h>
33 #include <semaphore.h>
34 #include <stdarg.h>
35 #include <strings.h> // index
36 #include <sys/time.h>
37 #include <sys/mman.h> // mmap & munmap
38 #include <unistd.h> // sysconf
39
40 #undef MAP_TYPE
41
42 #include "v8.h"
43
44 #include "platform.h"
45 #include "top.h"
46 #include "v8threads.h"
47 #include "vm-state-inl.h"
48 #include "win32-headers.h"
49
50 namespace v8 {
51 namespace internal {
52
53 // 0 is never a valid thread id
54 static const pthread_t kNoThread = (pthread_t) 0;
55
56
57 double ceiling(double x) {
58 return ceil(x);
59 }
60
61
62 void OS::Setup() {
63 // Seed the random number generator.
64 // Convert the current time to a 64-bit integer first, before converting it
65 // to an unsigned. Going directly can cause an overflow and the seed to be
66 // set to all ones. The seed will be identical for different instances that
67 // call this setup code within the same millisecond.
68 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
69 srandom(static_cast<unsigned int>(seed));
70 }
71
72
73 uint64_t OS::CpuFeaturesImpliedByPlatform() {
74 return 0; // Nothing special about cygwin
Vyacheslav Egorov (Chromium) 2011/02/17 14:00:48 dot at the end of the comment. cygwin -> Cygwin
75 }
76
77
78 int OS::ActivationFrameAlignment() {
79 // With gcc 4.4 the tree vectorization optimizer can generate code
80 // that requires 16 byte alignment such as movdqa on x86.
81 return 16;
82 }
83
84
85 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
86 __asm__ __volatile__("" : : : "memory");
87 // An x86 store acts as a release barrier.
88 *ptr = value;
89 }
90
91 const char* OS::LocalTimezone(double time) {
92 if (isnan(time)) return "";
93 time_t tv = static_cast<time_t>(floor(time/msPerSecond));
94 struct tm* t = localtime(&tv);
95 if (NULL == t) return "";
96 return tzname[0]; // The location of the timezone string on Cygwin.
97 }
98
99
100 double OS::LocalTimeOffset() {
101 // On Cygwin, struct tm does not contain a tm_gmtoff field.
102 time_t utc = time(NULL);
103 ASSERT(utc != -1);
104 struct tm* loc = localtime(&utc);
105 ASSERT(loc != NULL);
106 // time - localtime includes any daylight savings offset, so subtract it.
107 return static_cast<double>((mktime(loc) - utc) * msPerSecond -
108 (loc->tm_isdst > 0 ? 3600 * msPerSecond : 0));
109 }
110
111
112 // We keep the lowest and highest addresses mapped as a quick way of
113 // determining that pointers are outside the heap (used mostly in assertions
114 // and verification). The estimate is conservative, ie, not all addresses in
115 // 'allocated' space are actually allocated to our heap. The range is
116 // [lowest, highest), inclusive on the low and and exclusive on the high end.
117 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
118 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
119
120
121 static void UpdateAllocatedSpaceLimits(void* address, int size) {
122 lowest_ever_allocated = Min(lowest_ever_allocated, address);
123 highest_ever_allocated =
124 Max(highest_ever_allocated,
125 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
126 }
127
128
129 bool OS::IsOutsideAllocatedSpace(void* address) {
130 return address < lowest_ever_allocated || address >= highest_ever_allocated;
131 }
132
133
134 size_t OS::AllocateAlignment() {
135 return sysconf(_SC_PAGESIZE);
136 }
137
138
139 void* OS::Allocate(const size_t requested,
140 size_t* allocated,
141 bool is_executable) {
142 const size_t msize = RoundUp(requested, sysconf(_SC_PAGESIZE));
143 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
144 void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
145 if (mbase == MAP_FAILED) {
146 LOG(StringEvent("OS::Allocate", "mmap failed"));
147 return NULL;
148 }
149 *allocated = msize;
150 UpdateAllocatedSpaceLimits(mbase, msize);
151 return mbase;
152 }
153
154
155 void OS::Free(void* address, const size_t size) {
156 // TODO(1240712): munmap has a return value which is ignored here.
157 int result = munmap(address, size);
158 USE(result);
159 ASSERT(result == 0);
160 }
161
162
163 #ifdef ENABLE_HEAP_PROTECTION
164
165 void OS::Protect(void* address, size_t size) {
166 // TODO(1240712): mprotect has a return value which is ignored here.
167 mprotect(address, size, PROT_READ);
168 }
169
170
171 void OS::Unprotect(void* address, size_t size, bool is_executable) {
172 // TODO(1240712): mprotect has a return value which is ignored here.
173 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
174 mprotect(address, size, prot);
175 }
176
177 #endif
178
179
180 void OS::Sleep(int milliseconds) {
181 unsigned int ms = static_cast<unsigned int>(milliseconds);
182 usleep(1000 * ms);
183 }
184
185
186 void OS::Abort() {
187 // Redirect to std abort to signal abnormal program termination.
188 abort();
189 }
190
191
192 void OS::DebugBreak() {
193 asm("int $3");
194 }
195
196
197 class PosixMemoryMappedFile : public OS::MemoryMappedFile {
198 public:
199 PosixMemoryMappedFile(FILE* file, void* memory, int size)
200 : file_(file), memory_(memory), size_(size) { }
201 virtual ~PosixMemoryMappedFile();
202 virtual void* memory() { return memory_; }
203 virtual int size() { return size_; }
204 private:
205 FILE* file_;
206 void* memory_;
207 int size_;
208 };
209
210
211 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
212 FILE* file = fopen(name, "w+");
213 if (file == NULL) return NULL;
214
215 fseek(file, 0, SEEK_END);
216 int size = ftell(file);
217
218 void* memory =
219 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
220 return new PosixMemoryMappedFile(file, memory, size);
221 }
222
223
224 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
225 void* initial) {
226 FILE* file = fopen(name, "w+");
227 if (file == NULL) return NULL;
228 int result = fwrite(initial, size, 1, file);
229 if (result < 1) {
230 fclose(file);
231 return NULL;
232 }
233 void* memory =
234 mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
235 return new PosixMemoryMappedFile(file, memory, size);
236 }
237
238
239 PosixMemoryMappedFile::~PosixMemoryMappedFile() {
240 if (memory_) munmap(memory_, size_);
241 fclose(file_);
242 }
243
244
245 void OS::LogSharedLibraryAddresses() {
246 #ifdef ENABLE_LOGGING_AND_PROFILING
247 // This function assumes that the layout of the file is as follows:
248 // hex_start_addr-hex_end_addr rwxp <unused data> [binary_file_name]
249 // If we encounter an unexpected situation we abort scanning further entries.
250 FILE* fp = fopen("/proc/self/maps", "r");
251 if (fp == NULL) return;
252
253 // Allocate enough room to be able to store a full file name.
254 const int kLibNameLen = FILENAME_MAX + 1;
255 char* lib_name = reinterpret_cast<char*>(malloc(kLibNameLen));
256
257 // This loop will terminate once the scanning hits an EOF.
258 while (true) {
259 uintptr_t start, end;
260 char attr_r, attr_w, attr_x, attr_p;
261 // Parse the addresses and permission bits at the beginning of the line.
262 if (fscanf(fp, "%" V8PRIxPTR "-%" V8PRIxPTR, &start, &end) != 2) break;
263 if (fscanf(fp, " %c%c%c%c", &attr_r, &attr_w, &attr_x, &attr_p) != 4) break;
264
265 int c;
266 if (attr_r == 'r' && attr_w != 'w' && attr_x == 'x') {
267 // Found a read-only executable entry. Skip characters until we reach
268 // the beginning of the filename or the end of the line.
269 do {
270 c = getc(fp);
271 } while ((c != EOF) && (c != '\n') && (c != '/'));
272 if (c == EOF) break; // EOF: Was unexpected, just exit.
273
274 // Process the filename if found.
275 if (c == '/') {
276 ungetc(c, fp); // Push the '/' back into the stream to be read below.
277
278 // Read to the end of the line. Exit if the read fails.
279 if (fgets(lib_name, kLibNameLen, fp) == NULL) break;
280
281 // Drop the newline character read by fgets. We do not need to check
282 // for a zero-length string because we know that we at least read the
283 // '/' character.
284 lib_name[strlen(lib_name) - 1] = '\0';
285 } else {
286 // No library name found, just record the raw address range.
287 snprintf(lib_name, kLibNameLen,
288 "%08" V8PRIxPTR "-%08" V8PRIxPTR, start, end);
289 }
290 LOG(SharedLibraryEvent(lib_name, start, end));
291 } else {
292 // Entry not describing executable data. Skip to end of line to setup
293 // reading the next entry.
294 do {
295 c = getc(fp);
296 } while ((c != EOF) && (c != '\n'));
297 if (c == EOF) break;
298 }
299 }
300 free(lib_name);
301 fclose(fp);
302 #endif
303 }
304
305
306 void OS::SignalCodeMovingGC() {
307 // Nothing to do on Cygwin
Vyacheslav Egorov (Chromium) 2011/02/17 14:00:48 dot at the end of the comment.
308 }
309
310
311 int OS::StackWalk(Vector<OS::StackFrame> frames) {
312 // Not supported on Cygwin
Vyacheslav Egorov (Chromium) 2011/02/17 14:00:48 ditto
313 return 0;
314 }
315
316
317 // Constants used for mmap.
318 static const int kMmapFd = -1;
319 static const int kMmapFdOffset = 0;
320
321
322 VirtualMemory::VirtualMemory(size_t size) {
323 address_ = mmap(NULL, size, PROT_NONE,
324 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
325 kMmapFd, kMmapFdOffset);
326 size_ = size;
327 }
328
329
330 VirtualMemory::~VirtualMemory() {
331 if (IsReserved()) {
332 if (0 == munmap(address(), size())) address_ = MAP_FAILED;
333 }
334 }
335
336
337 bool VirtualMemory::IsReserved() {
338 return address_ != MAP_FAILED;
339 }
340
341
342 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
343 int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
344
345 if (mprotect(address, size, prot) != 0) {
346 return false;
347 }
348
349 UpdateAllocatedSpaceLimits(address, size);
350 return true;
351 }
352
353
354 bool VirtualMemory::Uncommit(void* address, size_t size) {
355 return mmap(address, size, PROT_NONE,
356 MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
357 kMmapFd, kMmapFdOffset) != MAP_FAILED;
358 }
359
360
361 class ThreadHandle::PlatformData : public Malloced {
362 public:
363 explicit PlatformData(ThreadHandle::Kind kind) {
364 Initialize(kind);
365 }
366
367 void Initialize(ThreadHandle::Kind kind) {
368 switch (kind) {
369 case ThreadHandle::SELF: thread_ = pthread_self(); break;
370 case ThreadHandle::INVALID: thread_ = kNoThread; break;
371 }
372 }
373
374 pthread_t thread_; // Thread handle for pthread.
375 };
376
377
378 ThreadHandle::ThreadHandle(Kind kind) {
379 data_ = new PlatformData(kind);
380 }
381
382
383 void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
384 data_->Initialize(kind);
385 }
386
387
388 ThreadHandle::~ThreadHandle() {
389 delete data_;
390 }
391
392
393 bool ThreadHandle::IsSelf() const {
394 return pthread_equal(data_->thread_, pthread_self());
395 }
396
397
398 bool ThreadHandle::IsValid() const {
399 return data_->thread_ != kNoThread;
400 }
401
402
403 Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
404 set_name("v8:<unknown>");
405 }
406
407
408 Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
409 set_name(name);
410 }
411
412
413 Thread::~Thread() {
414 }
415
416
417 static void* ThreadEntry(void* arg) {
418 Thread* thread = reinterpret_cast<Thread*>(arg);
419 // This is also initialized by the first argument to pthread_create() but we
420 // don't know which thread will run first (the original thread or the new
421 // one) so we initialize it here too.
422 thread->thread_handle_data()->thread_ = pthread_self();
423 ASSERT(thread->IsValid());
424 thread->Run();
425 return NULL;
426 }
427
428
429 void Thread::set_name(const char* name) {
430 strncpy(name_, name, sizeof(name_));
431 name_[sizeof(name_) - 1] = '\0';
432 }
433
434
435 void Thread::Start() {
436 pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
437 ASSERT(IsValid());
438 }
439
440
441 void Thread::Join() {
442 pthread_join(thread_handle_data()->thread_, NULL);
443 }
444
445
446 Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
447 pthread_key_t key;
448 int result = pthread_key_create(&key, NULL);
449 USE(result);
450 ASSERT(result == 0);
451 return static_cast<LocalStorageKey>(key);
452 }
453
454
455 void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
456 pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
457 int result = pthread_key_delete(pthread_key);
458 USE(result);
459 ASSERT(result == 0);
460 }
461
462
463 void* Thread::GetThreadLocal(LocalStorageKey key) {
464 pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
465 return pthread_getspecific(pthread_key);
466 }
467
468
469 void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
470 pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
471 pthread_setspecific(pthread_key, value);
472 }
473
474
475 void Thread::YieldCPU() {
476 sched_yield();
477 }
478
479
480 class CygwinMutex : public Mutex {
481 public:
482
483 CygwinMutex() {
484 pthread_mutexattr_t attrs;
485 memset(&attrs, 0, sizeof(attrs));
486
487 int result = pthread_mutexattr_init(&attrs);
488 ASSERT(result == 0);
489 result = pthread_mutexattr_settype(&attrs, PTHREAD_MUTEX_RECURSIVE);
490 ASSERT(result == 0);
491 result = pthread_mutex_init(&mutex_, &attrs);
492 ASSERT(result == 0);
493 }
494
495 virtual ~CygwinMutex() { pthread_mutex_destroy(&mutex_); }
496
497 virtual int Lock() {
498 int result = pthread_mutex_lock(&mutex_);
499 return result;
500 }
501
502 virtual int Unlock() {
503 int result = pthread_mutex_unlock(&mutex_);
504 return result;
505 }
506
507 virtual bool TryLock() {
508 int result = pthread_mutex_trylock(&mutex_);
509 // Return false if the lock is busy and locking failed.
510 if (result == EBUSY) {
511 return false;
512 }
513 ASSERT(result == 0); // Verify no other errors.
514 return true;
515 }
516
517 private:
518 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms.
519 };
520
521
522 Mutex* OS::CreateMutex() {
523 return new CygwinMutex();
524 }
525
526
527 class CygwinSemaphore : public Semaphore {
528 public:
529 explicit CygwinSemaphore(int count) { sem_init(&sem_, 0, count); }
530 virtual ~CygwinSemaphore() { sem_destroy(&sem_); }
531
532 virtual void Wait();
533 virtual bool Wait(int timeout);
534 virtual void Signal() { sem_post(&sem_); }
535 private:
536 sem_t sem_;
537 };
538
539
540 void CygwinSemaphore::Wait() {
541 while (true) {
542 int result = sem_wait(&sem_);
543 if (result == 0) return; // Successfully got semaphore.
544 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
545 }
546 }
547
548
549 #ifndef TIMEVAL_TO_TIMESPEC
550 #define TIMEVAL_TO_TIMESPEC(tv, ts) do { \
551 (ts)->tv_sec = (tv)->tv_sec; \
552 (ts)->tv_nsec = (tv)->tv_usec * 1000; \
553 } while (false)
554 #endif
555
556
557 bool CygwinSemaphore::Wait(int timeout) {
558 const long kOneSecondMicros = 1000000; // NOLINT
559
560 // Split timeout into second and nanosecond parts.
561 struct timeval delta;
562 delta.tv_usec = timeout % kOneSecondMicros;
563 delta.tv_sec = timeout / kOneSecondMicros;
564
565 struct timeval current_time;
566 // Get the current time.
567 if (gettimeofday(&current_time, NULL) == -1) {
568 return false;
569 }
570
571 // Calculate time for end of timeout.
572 struct timeval end_time;
573 timeradd(&current_time, &delta, &end_time);
574
575 struct timespec ts;
576 TIMEVAL_TO_TIMESPEC(&end_time, &ts);
577 // Wait for semaphore signalled or timeout.
578 while (true) {
579 int result = sem_timedwait(&sem_, &ts);
580 if (result == 0) return true; // Successfully got semaphore.
581 if (result == -1 && errno == ETIMEDOUT) return false; // Timeout.
582 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
583 }
584 }
585
586
587 Semaphore* OS::CreateSemaphore(int count) {
588 return new CygwinSemaphore(count);
589 }
590
591
592 #ifdef ENABLE_LOGGING_AND_PROFILING
593
594 // ----------------------------------------------------------------------------
595 // Cygwin profiler support.
596 //
597 // On cygwin we use the same sampler implementation as on win32
Vyacheslav Egorov (Chromium) 2011/02/17 14:00:48 cygwin -> Cygwin dot at the end.
598
599 class Sampler::PlatformData : public Malloced {
600 public:
601 explicit PlatformData(Sampler* sampler) {
602 sampler_ = sampler;
603 sampler_thread_ = INVALID_HANDLE_VALUE;
604 profiled_thread_ = INVALID_HANDLE_VALUE;
605 }
606
607 Sampler* sampler_;
608 HANDLE sampler_thread_;
609 HANDLE profiled_thread_;
610 RuntimeProfilerRateLimiter rate_limiter_;
611
612 // Sampler thread handler.
613 void Runner() {
614 while (sampler_->IsActive()) {
615 if (rate_limiter_.SuspendIfNecessary()) continue;
616 Sample();
617 Sleep(sampler_->interval_);
618 }
619 }
620
621 void Sample() {
622 if (sampler_->IsProfiling()) {
623 // Context used for sampling the register state of the profiled thread.
624 CONTEXT context;
625 memset(&context, 0, sizeof(context));
626
627 TickSample sample_obj;
628 TickSample* sample = CpuProfiler::TickSampleEvent();
629 if (sample == NULL) sample = &sample_obj;
630
631 static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
632 if (SuspendThread(profiled_thread_) == kSuspendFailed) return;
633 sample->state = Top::current_vm_state();
634
635 context.ContextFlags = CONTEXT_FULL;
636 if (GetThreadContext(profiled_thread_, &context) != 0) {
637 #if V8_HOST_ARCH_X64
638 sample->pc = reinterpret_cast<Address>(context.Rip);
639 sample->sp = reinterpret_cast<Address>(context.Rsp);
640 sample->fp = reinterpret_cast<Address>(context.Rbp);
641 #else
642 sample->pc = reinterpret_cast<Address>(context.Eip);
643 sample->sp = reinterpret_cast<Address>(context.Esp);
644 sample->fp = reinterpret_cast<Address>(context.Ebp);
645 #endif
646 sampler_->SampleStack(sample);
647 sampler_->Tick(sample);
648 }
649 ResumeThread(profiled_thread_);
650 }
651 if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
652 }
653 };
654
655
656 // Entry point for sampler thread.
657 static DWORD __stdcall SamplerEntry(void* arg) {
658 Sampler::PlatformData* data =
659 reinterpret_cast<Sampler::PlatformData*>(arg);
660 data->Runner();
661 return 0;
662 }
663
664
665 // Initialize a profile sampler.
666 Sampler::Sampler(int interval)
667 : interval_(interval),
668 profiling_(false),
669 active_(false),
670 samples_taken_(0) {
671 data_ = new PlatformData(this);
672 }
673
674
675 Sampler::~Sampler() {
676 delete data_;
677 }
678
679
680 // Start profiling.
681 void Sampler::Start() {
682 // Do not start multiple threads for the same sampler.
683 ASSERT(!IsActive());
684
685 // Get a handle to the calling thread. This is the thread that we are
686 // going to profile. We need to make a copy of the handle because we are
687 // going to use it in the sampler thread. Using GetThreadHandle() will
688 // not work in this case. We're using OpenThread because DuplicateHandle
689 // for some reason doesn't work in Chrome's sandbox.
690 data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT |
691 THREAD_SUSPEND_RESUME |
692 THREAD_QUERY_INFORMATION,
693 false,
694 GetCurrentThreadId());
695 BOOL ok = data_->profiled_thread_ != NULL;
696 if (!ok) return;
697
698 // Start sampler thread.
699 DWORD tid;
700 SetActive(true);
701 data_->sampler_thread_ = CreateThread(NULL, 0, SamplerEntry, data_, 0,
Vyacheslav Egorov (Chromium) 2011/02/17 14:00:48 one argument per line or the whole call on the nex
702 &tid);
703 // Set thread to high priority to increase sampling accuracy.
704 SetThreadPriority(data_->sampler_thread_, THREAD_PRIORITY_TIME_CRITICAL);
705 }
706
707
708 // Stop profiling.
709 void Sampler::Stop() {
710 // Seting active to false triggers termination of the sampler
711 // thread.
712 SetActive(false);
713
714 // Wait for sampler thread to terminate.
715 Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
716 WaitForSingleObject(data_->sampler_thread_, INFINITE);
717
718 // Release the thread handles
719 CloseHandle(data_->sampler_thread_);
720 CloseHandle(data_->profiled_thread_);
721 }
722
723
724 #endif // ENABLE_LOGGING_AND_PROFILING
725
726 } } // namespace v8::internal
727
OLDNEW
« src/platform.h ('K') | « src/platform.h ('k') | tools/utils.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698