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

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

Issue 6993057: Version 3.4.2 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « src/platform-linux.cc ('k') | src/platform-posix.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2011 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
11 // with the distribution. 11 // with the distribution.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 #include <unistd.h> // getpagesize 43 #include <unistd.h> // getpagesize
44 #include <execinfo.h> // backtrace, backtrace_symbols 44 #include <execinfo.h> // backtrace, backtrace_symbols
45 #include <strings.h> // index 45 #include <strings.h> // index
46 #include <errno.h> 46 #include <errno.h>
47 #include <stdarg.h> 47 #include <stdarg.h>
48 #include <limits.h> 48 #include <limits.h>
49 49
50 #undef MAP_TYPE 50 #undef MAP_TYPE
51 51
52 #include "v8.h" 52 #include "v8.h"
53 #include "v8threads.h"
53 54
54 #include "platform.h" 55 #include "platform.h"
55 #include "vm-state-inl.h" 56 #include "vm-state-inl.h"
56 57
57 58
58 namespace v8 { 59 namespace v8 {
59 namespace internal { 60 namespace internal {
60 61
61 // 0 is never a valid thread id on OpenBSD since tids and pids share a 62 // 0 is never a valid thread id on OpenBSD since tids and pids share a
62 // name space and pid 0 is used to kill the group (see man 2 kill). 63 // name space and pid 0 is used to kill the group (see man 2 kill).
63 static const pthread_t kNoThread = (pthread_t) 0; 64 static const pthread_t kNoThread = (pthread_t) 0;
64 65
65 66
66 double ceiling(double x) { 67 double ceiling(double x) {
67 // Correct as on OS X 68 // Correct as on OS X
68 if (-1.0 < x && x < 0.0) { 69 if (-1.0 < x && x < 0.0) {
69 return -0.0; 70 return -0.0;
70 } else { 71 } else {
71 return ceil(x); 72 return ceil(x);
72 } 73 }
73 } 74 }
74 75
75 76
77 static Mutex* limit_mutex = NULL;
78
79
76 void OS::Setup() { 80 void OS::Setup() {
77 // Seed the random number generator. 81 // Seed the random number generator.
78 // Convert the current time to a 64-bit integer first, before converting it 82 // Convert the current time to a 64-bit integer first, before converting it
79 // to an unsigned. Going directly can cause an overflow and the seed to be 83 // to an unsigned. Going directly can cause an overflow and the seed to be
80 // set to all ones. The seed will be identical for different instances that 84 // set to all ones. The seed will be identical for different instances that
81 // call this setup code within the same millisecond. 85 // call this setup code within the same millisecond.
82 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 86 uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
83 srandom(static_cast<unsigned int>(seed)); 87 srandom(static_cast<unsigned int>(seed));
88 limit_mutex = CreateMutex();
84 } 89 }
85 90
86 91
87 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 92 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
88 __asm__ __volatile__("" : : : "memory"); 93 __asm__ __volatile__("" : : : "memory");
89 *ptr = value; 94 *ptr = value;
90 } 95 }
91 96
92 97
93 uint64_t OS::CpuFeaturesImpliedByPlatform() { 98 uint64_t OS::CpuFeaturesImpliedByPlatform() {
(...skipping 28 matching lines...) Expand all
122 // We keep the lowest and highest addresses mapped as a quick way of 127 // We keep the lowest and highest addresses mapped as a quick way of
123 // determining that pointers are outside the heap (used mostly in assertions 128 // determining that pointers are outside the heap (used mostly in assertions
124 // and verification). The estimate is conservative, ie, not all addresses in 129 // and verification). The estimate is conservative, ie, not all addresses in
125 // 'allocated' space are actually allocated to our heap. The range is 130 // 'allocated' space are actually allocated to our heap. The range is
126 // [lowest, highest), inclusive on the low and and exclusive on the high end. 131 // [lowest, highest), inclusive on the low and and exclusive on the high end.
127 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 132 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
128 static void* highest_ever_allocated = reinterpret_cast<void*>(0); 133 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
129 134
130 135
131 static void UpdateAllocatedSpaceLimits(void* address, int size) { 136 static void UpdateAllocatedSpaceLimits(void* address, int size) {
137 ASSERT(limit_mutex != NULL);
138 ScopedLock lock(limit_mutex);
139
132 lowest_ever_allocated = Min(lowest_ever_allocated, address); 140 lowest_ever_allocated = Min(lowest_ever_allocated, address);
133 highest_ever_allocated = 141 highest_ever_allocated =
134 Max(highest_ever_allocated, 142 Max(highest_ever_allocated,
135 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 143 reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
136 } 144 }
137 145
138 146
139 bool OS::IsOutsideAllocatedSpace(void* address) { 147 bool OS::IsOutsideAllocatedSpace(void* address) {
140 return address < lowest_ever_allocated || address >= highest_ever_allocated; 148 return address < lowest_ever_allocated || address >= highest_ever_allocated;
141 } 149 }
(...skipping 15 matching lines...) Expand all
157 LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed")); 165 LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed"));
158 return NULL; 166 return NULL;
159 } 167 }
160 *allocated = msize; 168 *allocated = msize;
161 UpdateAllocatedSpaceLimits(mbase, msize); 169 UpdateAllocatedSpaceLimits(mbase, msize);
162 return mbase; 170 return mbase;
163 } 171 }
164 172
165 173
166 void OS::Free(void* buf, const size_t length) { 174 void OS::Free(void* buf, const size_t length) {
175 // TODO(1240712): munmap has a return value which is ignored here.
167 int result = munmap(buf, length); 176 int result = munmap(buf, length);
168 USE(result); 177 USE(result);
169 ASSERT(result == 0); 178 ASSERT(result == 0);
170 } 179 }
171 180
172 181
173 #ifdef ENABLE_HEAP_PROTECTION 182 #ifdef ENABLE_HEAP_PROTECTION
174 183
175 void OS::Protect(void* address, size_t size) { 184 void OS::Protect(void* address, size_t size) {
176 UNIMPLEMENTED(); 185 UNIMPLEMENTED();
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 result = read(fd, buffer + bytes_read, 1); 299 result = read(fd, buffer + bytes_read, 1);
291 if (result < 1) break; 300 if (result < 1) break;
292 } while (buffer[bytes_read] != '\n'); 301 } while (buffer[bytes_read] != '\n');
293 buffer[bytes_read] = 0; 302 buffer[bytes_read] = 0;
294 // Ignore mappings that are not executable. 303 // Ignore mappings that are not executable.
295 if (buffer[3] != 'x') continue; 304 if (buffer[3] != 'x') continue;
296 char* start_of_path = index(buffer, '/'); 305 char* start_of_path = index(buffer, '/');
297 // There may be no filename in this line. Skip to next. 306 // There may be no filename in this line. Skip to next.
298 if (start_of_path == NULL) continue; 307 if (start_of_path == NULL) continue;
299 buffer[bytes_read] = 0; 308 buffer[bytes_read] = 0;
300 LOG(SharedLibraryEvent(start_of_path, start, end)); 309 LOG(i::Isolate::Current(), SharedLibraryEvent(start_of_path, start, end));
301 } 310 }
302 close(fd); 311 close(fd);
303 #endif 312 #endif
304 } 313 }
305 314
306 315
307 void OS::SignalCodeMovingGC() { 316 void OS::SignalCodeMovingGC() {
308 } 317 }
309 318
310 319
311 int OS::StackWalk(Vector<OS::StackFrame> frames) { 320 int OS::StackWalk(Vector<OS::StackFrame> frames) {
312 UNIMPLEMENTED(); 321 int frames_size = frames.length();
313 return 1; 322 ScopedVector<void*> addresses(frames_size);
323
324 int frames_count = backtrace(addresses.start(), frames_size);
325
326 char** symbols = backtrace_symbols(addresses.start(), frames_count);
327 if (symbols == NULL) {
328 return kStackWalkError;
329 }
330
331 for (int i = 0; i < frames_count; i++) {
332 frames[i].address = addresses[i];
333 // Format a text representation of the frame based on the information
334 // available.
335 SNPrintF(MutableCStrVector(frames[i].text, kStackWalkMaxTextLen),
336 "%s",
337 symbols[i]);
338 // Make sure line termination is in place.
339 frames[i].text[kStackWalkMaxTextLen - 1] = '\0';
340 }
341
342 free(symbols);
343
344 return frames_count;
314 } 345 }
315 346
316 347
317 // Constants used for mmap. 348 // Constants used for mmap.
318 static const int kMmapFd = -1; 349 static const int kMmapFd = -1;
319 static const int kMmapFdOffset = 0; 350 static const int kMmapFdOffset = 0;
320 351
321 352
322 VirtualMemory::VirtualMemory(size_t size) { 353 VirtualMemory::VirtualMemory(size_t size) {
323 address_ = mmap(NULL, size, PROT_NONE, 354 address_ = mmap(NULL, size, PROT_NONE,
(...skipping 23 matching lines...) Expand all
347 return false; 378 return false;
348 } 379 }
349 380
350 UpdateAllocatedSpaceLimits(address, size); 381 UpdateAllocatedSpaceLimits(address, size);
351 return true; 382 return true;
352 } 383 }
353 384
354 385
355 bool VirtualMemory::Uncommit(void* address, size_t size) { 386 bool VirtualMemory::Uncommit(void* address, size_t size) {
356 return mmap(address, size, PROT_NONE, 387 return mmap(address, size, PROT_NONE,
357 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, 388 MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED,
358 kMmapFd, kMmapFdOffset) != MAP_FAILED; 389 kMmapFd, kMmapFdOffset) != MAP_FAILED;
359 } 390 }
360 391
361 392
362 class Thread::PlatformData : public Malloced { 393 class Thread::PlatformData : public Malloced {
363 public: 394 public:
364 PlatformData() : thread_(kNoThread) {}
365
366 pthread_t thread_; // Thread handle for pthread. 395 pthread_t thread_; // Thread handle for pthread.
367 }; 396 };
368 397
369 398
370 Thread::Thread(Isolate* isolate, const Options& options) 399 Thread::Thread(Isolate* isolate, const Options& options)
371 : data_(new PlatformData()), 400 : data_(new PlatformData),
372 isolate_(isolate), 401 isolate_(isolate),
373 stack_size_(options.stack_size) { 402 stack_size_(options.stack_size) {
374 set_name(options.name); 403 set_name(options.name);
375 } 404 }
376 405
377 406
378 Thread::Thread(Isolate* isolate, const char* name) 407 Thread::Thread(Isolate* isolate, const char* name)
379 : data_(new PlatfromData()), 408 : data_(new PlatformData),
380 isolate_(isolate), 409 isolate_(isolate),
381 stack_size_(0) { 410 stack_size_(0) {
382 set_name(name); 411 set_name(name);
383 } 412 }
384 413
385 414
386 Thread::~Thread() { 415 Thread::~Thread() {
387 delete data_; 416 delete data_;
388 } 417 }
389 418
(...skipping 19 matching lines...) Expand all
409 438
410 void Thread::Start() { 439 void Thread::Start() {
411 pthread_attr_t* attr_ptr = NULL; 440 pthread_attr_t* attr_ptr = NULL;
412 pthread_attr_t attr; 441 pthread_attr_t attr;
413 if (stack_size_ > 0) { 442 if (stack_size_ > 0) {
414 pthread_attr_init(&attr); 443 pthread_attr_init(&attr);
415 pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_)); 444 pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
416 attr_ptr = &attr; 445 attr_ptr = &attr;
417 } 446 }
418 pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this); 447 pthread_create(&data_->thread_, attr_ptr, ThreadEntry, this);
419 ASSERT(IsValid()); 448 ASSERT(data_->thread_ != kNoThread);
420 } 449 }
421 450
422 451
423 void Thread::Join() { 452 void Thread::Join() {
424 pthread_join(data_->thread_, NULL); 453 pthread_join(data_->thread_, NULL);
425 } 454 }
426 455
427 456
428 Thread::LocalStorageKey Thread::CreateThreadLocalKey() { 457 Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
429 pthread_key_t key; 458 pthread_key_t key;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 virtual int Lock() { 506 virtual int Lock() {
478 int result = pthread_mutex_lock(&mutex_); 507 int result = pthread_mutex_lock(&mutex_);
479 return result; 508 return result;
480 } 509 }
481 510
482 virtual int Unlock() { 511 virtual int Unlock() {
483 int result = pthread_mutex_unlock(&mutex_); 512 int result = pthread_mutex_unlock(&mutex_);
484 return result; 513 return result;
485 } 514 }
486 515
516 virtual bool TryLock() {
517 int result = pthread_mutex_trylock(&mutex_);
518 // Return false if the lock is busy and locking failed.
519 if (result == EBUSY) {
520 return false;
521 }
522 ASSERT(result == 0); // Verify no other errors.
523 return true;
524 }
525
487 private: 526 private:
488 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms. 527 pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms.
489 }; 528 };
490 529
491 530
492 Mutex* OS::CreateMutex() { 531 Mutex* OS::CreateMutex() {
493 return new OpenBSDMutex(); 532 return new OpenBSDMutex();
494 } 533 }
495 534
496 535
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 if (gettimeofday(&current_time, NULL) == -1) { 568 if (gettimeofday(&current_time, NULL) == -1) {
530 return false; 569 return false;
531 } 570 }
532 571
533 // Calculate time for end of timeout. 572 // Calculate time for end of timeout.
534 struct timeval end_time; 573 struct timeval end_time;
535 timeradd(&current_time, &delta, &end_time); 574 timeradd(&current_time, &delta, &end_time);
536 575
537 struct timespec ts; 576 struct timespec ts;
538 TIMEVAL_TO_TIMESPEC(&end_time, &ts); 577 TIMEVAL_TO_TIMESPEC(&end_time, &ts);
578
579 int to = ts.tv_sec;
580
539 while (true) { 581 while (true) {
540 int result = sem_trywait(&sem_); 582 int result = sem_trywait(&sem_);
541 if (result == 0) return true; // Successfully got semaphore. 583 if (result == 0) return true; // Successfully got semaphore.
542 if (result == -1 && errno == ETIMEDOUT) return false; // Timeout. 584 if (!to) return false; // Timeout.
543 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 585 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
586 usleep(ts.tv_nsec / 1000);
587 to--;
544 } 588 }
545 } 589 }
546 590
547 591
548 Semaphore* OS::CreateSemaphore(int count) { 592 Semaphore* OS::CreateSemaphore(int count) {
549 return new OpenBSDSemaphore(count); 593 return new OpenBSDSemaphore(count);
550 } 594 }
551 595
552 596
553 #ifdef ENABLE_LOGGING_AND_PROFILING 597 #ifdef ENABLE_LOGGING_AND_PROFILING
554 598
555 static Sampler* active_sampler_ = NULL; 599 static pthread_t GetThreadID() {
600 pthread_t thread_id = pthread_self();
601 return thread_id;
602 }
603
604
605 class Sampler::PlatformData : public Malloced {
606 public:
607 PlatformData() : vm_tid_(GetThreadID()) {}
608
609 pthread_t vm_tid() const { return vm_tid_; }
610
611 private:
612 pthread_t vm_tid_;
613 };
614
556 615
557 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { 616 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
558 USE(info); 617 USE(info);
559 if (signal != SIGPROF) return; 618 if (signal != SIGPROF) return;
560 if (active_sampler_ == NULL) return; 619 Isolate* isolate = Isolate::UncheckedCurrent();
561 620 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
562 TickSample sample; 621 // We require a fully initialized and entered isolate.
563 622 return;
564 // We always sample the VM state. 623 }
565 sample.state = VMState::current_state(); 624 if (v8::Locker::IsActive() &&
566 625 !isolate->thread_manager()->IsLockedByCurrentThread()) {
567 active_sampler_->Tick(&sample); 626 return;
568 } 627 }
569 628
570 629 Sampler* sampler = isolate->logger()->sampler();
571 class Sampler::PlatformData : public Malloced { 630 if (sampler == NULL || !sampler->IsActive()) return;
631
632 TickSample sample_obj;
633 TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
634 if (sample == NULL) sample = &sample_obj;
635
636 // Extracting the sample from the context is extremely machine dependent.
637 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
638 sample->state = isolate->current_vm_state();
639 #if V8_HOST_ARCH_IA32
640 sample->pc = reinterpret_cast<Address>(ucontext->sc_eip);
641 sample->sp = reinterpret_cast<Address>(ucontext->sc_esp);
642 sample->fp = reinterpret_cast<Address>(ucontext->sc_ebp);
643 #elif V8_HOST_ARCH_X64
644 sample->pc = reinterpret_cast<Address>(ucontext->sc_rip);
645 sample->sp = reinterpret_cast<Address>(ucontext->sc_rsp);
646 sample->fp = reinterpret_cast<Address>(ucontext->sc_rbp);
647 #elif V8_HOST_ARCH_ARM
648 sample->pc = reinterpret_cast<Address>(ucontext->sc_r15);
649 sample->sp = reinterpret_cast<Address>(ucontext->sc_r13);
650 sample->fp = reinterpret_cast<Address>(ucontext->sc_r11);
651 #endif
652 sampler->SampleStack(sample);
653 sampler->Tick(sample);
654 }
655
656
657 class SignalSender : public Thread {
572 public: 658 public:
573 PlatformData() { 659 enum SleepInterval {
574 signal_handler_installed_ = false; 660 HALF_INTERVAL,
575 } 661 FULL_INTERVAL
576 662 };
577 bool signal_handler_installed_; 663
578 struct sigaction old_signal_handler_; 664 explicit SignalSender(int interval)
579 struct itimerval old_timer_value_; 665 : Thread(NULL, "SignalSender"),
666 interval_(interval) {}
667
668 static void AddActiveSampler(Sampler* sampler) {
669 ScopedLock lock(mutex_);
670 SamplerRegistry::AddActiveSampler(sampler);
671 if (instance_ == NULL) {
672 // Install a signal handler.
673 struct sigaction sa;
674 sa.sa_sigaction = ProfilerSignalHandler;
675 sigemptyset(&sa.sa_mask);
676 sa.sa_flags = SA_RESTART | SA_SIGINFO;
677 signal_handler_installed_ =
678 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
679
680 // Start a thread that sends SIGPROF signal to VM threads.
681 instance_ = new SignalSender(sampler->interval());
682 instance_->Start();
683 } else {
684 ASSERT(instance_->interval_ == sampler->interval());
685 }
686 }
687
688 static void RemoveActiveSampler(Sampler* sampler) {
689 ScopedLock lock(mutex_);
690 SamplerRegistry::RemoveActiveSampler(sampler);
691 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
692 RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
693 instance_->Join();
694 delete instance_;
695 instance_ = NULL;
696
697 // Restore the old signal handler.
698 if (signal_handler_installed_) {
699 sigaction(SIGPROF, &old_signal_handler_, 0);
700 signal_handler_installed_ = false;
701 }
702 }
703 }
704
705 // Implement Thread::Run().
706 virtual void Run() {
707 SamplerRegistry::State state;
708 while ((state = SamplerRegistry::GetState()) !=
709 SamplerRegistry::HAS_NO_SAMPLERS) {
710 bool cpu_profiling_enabled =
711 (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
712 bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
713 // When CPU profiling is enabled both JavaScript and C++ code is
714 // profiled. We must not suspend.
715 if (!cpu_profiling_enabled) {
716 if (rate_limiter_.SuspendIfNecessary()) continue;
717 }
718 if (cpu_profiling_enabled && runtime_profiler_enabled) {
719 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
720 return;
721 }
722 Sleep(HALF_INTERVAL);
723 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
724 return;
725 }
726 Sleep(HALF_INTERVAL);
727 } else {
728 if (cpu_profiling_enabled) {
729 if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
730 this)) {
731 return;
732 }
733 }
734 if (runtime_profiler_enabled) {
735 if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
736 NULL)) {
737 return;
738 }
739 }
740 Sleep(FULL_INTERVAL);
741 }
742 }
743 }
744
745 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
746 if (!sampler->IsProfiling()) return;
747 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
748 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
749 }
750
751 static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
752 if (!sampler->isolate()->IsInitialized()) return;
753 sampler->isolate()->runtime_profiler()->NotifyTick();
754 }
755
756 void SendProfilingSignal(pthread_t tid) {
757 if (!signal_handler_installed_) return;
758 pthread_kill(tid, SIGPROF);
759 }
760
761 void Sleep(SleepInterval full_or_half) {
762 // Convert ms to us and subtract 100 us to compensate delays
763 // occuring during signal delivery.
764 useconds_t interval = interval_ * 1000 - 100;
765 if (full_or_half == HALF_INTERVAL) interval /= 2;
766 int result = usleep(interval);
767 #ifdef DEBUG
768 if (result != 0 && errno != EINTR) {
769 fprintf(stderr,
770 "SignalSender usleep error; interval = %u, errno = %d\n",
771 interval,
772 errno);
773 ASSERT(result == 0 || errno == EINTR);
774 }
775 #endif
776 USE(result);
777 }
778
779 const int interval_;
780 RuntimeProfilerRateLimiter rate_limiter_;
781
782 // Protects the process wide state below.
783 static Mutex* mutex_;
784 static SignalSender* instance_;
785 static bool signal_handler_installed_;
786 static struct sigaction old_signal_handler_;
787
788 DISALLOW_COPY_AND_ASSIGN(SignalSender);
580 }; 789 };
581 790
791 Mutex* SignalSender::mutex_ = OS::CreateMutex();
792 SignalSender* SignalSender::instance_ = NULL;
793 struct sigaction SignalSender::old_signal_handler_;
794 bool SignalSender::signal_handler_installed_ = false;
795
582 796
583 Sampler::Sampler(Isolate* isolate, int interval) 797 Sampler::Sampler(Isolate* isolate, int interval)
584 : isolate_(isolate), 798 : isolate_(isolate),
585 interval_(interval), 799 interval_(interval),
586 profiling_(false), 800 profiling_(false),
587 active_(false), 801 active_(false),
588 samples_taken_(0) { 802 samples_taken_(0) {
589 data_ = new PlatformData(); 803 data_ = new PlatformData;
590 } 804 }
591 805
592 806
593 Sampler::~Sampler() { 807 Sampler::~Sampler() {
808 ASSERT(!IsActive());
594 delete data_; 809 delete data_;
595 } 810 }
596 811
597 812
598 void Sampler::Start() { 813 void Sampler::Start() {
599 // There can only be one active sampler at the time on POSIX 814 ASSERT(!IsActive());
600 // platforms. 815 SetActive(true);
601 if (active_sampler_ != NULL) return; 816 SignalSender::AddActiveSampler(this);
602
603 // Request profiling signals.
604 struct sigaction sa;
605 sa.sa_sigaction = ProfilerSignalHandler;
606 sigemptyset(&sa.sa_mask);
607 sa.sa_flags = SA_SIGINFO;
608 if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
609 data_->signal_handler_installed_ = true;
610
611 // Set the itimer to generate a tick for each interval.
612 itimerval itimer;
613 itimer.it_interval.tv_sec = interval_ / 1000;
614 itimer.it_interval.tv_usec = (interval_ % 1000) * 1000;
615 itimer.it_value.tv_sec = itimer.it_interval.tv_sec;
616 itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
617 setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_);
618
619 // Set this sampler as the active sampler.
620 active_sampler_ = this;
621 active_ = true;
622 } 817 }
623 818
624 819
625 void Sampler::Stop() { 820 void Sampler::Stop() {
626 // Restore old signal handler 821 ASSERT(IsActive());
627 if (data_->signal_handler_installed_) { 822 SignalSender::RemoveActiveSampler(this);
628 setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL); 823 SetActive(false);
629 sigaction(SIGPROF, &data_->old_signal_handler_, 0);
630 data_->signal_handler_installed_ = false;
631 }
632
633 // This sampler is no longer the active sampler.
634 active_sampler_ = NULL;
635 active_ = false;
636 } 824 }
637 825
638 #endif // ENABLE_LOGGING_AND_PROFILING 826 #endif // ENABLE_LOGGING_AND_PROFILING
639 827
640 } } // namespace v8::internal 828 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-linux.cc ('k') | src/platform-posix.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698