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

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

Issue 13852005: Move *BSD and Solaris Sampler implementations into sampler.cc (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Removed class TickSample forward declaration Created 7 years, 8 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-freebsd.cc ('k') | src/platform-openbsd.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 defined(__arm__) && !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT) 61 defined(__arm__) && !defined(__BIONIC_HAVE_STRUCT_SIGCONTEXT)
62 #include <asm/sigcontext.h> 62 #include <asm/sigcontext.h>
63 #endif 63 #endif
64 64
65 #undef MAP_TYPE 65 #undef MAP_TYPE
66 66
67 #include "v8.h" 67 #include "v8.h"
68 68
69 #include "platform-posix.h" 69 #include "platform-posix.h"
70 #include "platform.h" 70 #include "platform.h"
71 #include "simulator.h"
72 #include "v8threads.h" 71 #include "v8threads.h"
73 #include "vm-state-inl.h" 72 #include "vm-state-inl.h"
74 73
75 74
76 namespace v8 { 75 namespace v8 {
77 namespace internal { 76 namespace internal {
78 77
79 // 0 is never a valid thread id on Linux since tids and pids share a 78 // 0 is never a valid thread id on Linux since tids and pids share a
80 // name space and pid 0 is reserved (see man 2 kill). 79 // name space and pid 0 is reserved (see man 2 kill).
81 static const pthread_t kNoThread = (pthread_t) 0; 80 static const pthread_t kNoThread = (pthread_t) 0;
(...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after
985 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup. 984 CHECK(result == -1 && errno == EINTR); // Signal caused spurious wakeup.
986 } 985 }
987 } 986 }
988 987
989 988
990 Semaphore* OS::CreateSemaphore(int count) { 989 Semaphore* OS::CreateSemaphore(int count) {
991 return new LinuxSemaphore(count); 990 return new LinuxSemaphore(count);
992 } 991 }
993 992
994 993
995 #if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T)
996
997 // Not all versions of Android's C library provide ucontext_t.
998 // Detect this and provide custom but compatible definitions. Note that these
999 // follow the GLibc naming convention to access register values from
1000 // mcontext_t.
1001 //
1002 // See http://code.google.com/p/android/issues/detail?id=34784
1003
1004 #if defined(__arm__)
1005
1006 typedef struct sigcontext mcontext_t;
1007
1008 typedef struct ucontext {
1009 uint32_t uc_flags;
1010 struct ucontext* uc_link;
1011 stack_t uc_stack;
1012 mcontext_t uc_mcontext;
1013 // Other fields are not used by V8, don't define them here.
1014 } ucontext_t;
1015
1016 #elif defined(__mips__)
1017 // MIPS version of sigcontext, for Android bionic.
1018 typedef struct {
1019 uint32_t regmask;
1020 uint32_t status;
1021 uint64_t pc;
1022 uint64_t gregs[32];
1023 uint64_t fpregs[32];
1024 uint32_t acx;
1025 uint32_t fpc_csr;
1026 uint32_t fpc_eir;
1027 uint32_t used_math;
1028 uint32_t dsp;
1029 uint64_t mdhi;
1030 uint64_t mdlo;
1031 uint32_t hi1;
1032 uint32_t lo1;
1033 uint32_t hi2;
1034 uint32_t lo2;
1035 uint32_t hi3;
1036 uint32_t lo3;
1037 } mcontext_t;
1038
1039 typedef struct ucontext {
1040 uint32_t uc_flags;
1041 struct ucontext* uc_link;
1042 stack_t uc_stack;
1043 mcontext_t uc_mcontext;
1044 // Other fields are not used by V8, don't define them here.
1045 } ucontext_t;
1046
1047 #elif defined(__i386__)
1048 // x86 version for Android.
1049 typedef struct {
1050 uint32_t gregs[19];
1051 void* fpregs;
1052 uint32_t oldmask;
1053 uint32_t cr2;
1054 } mcontext_t;
1055
1056 typedef uint32_t kernel_sigset_t[2]; // x86 kernel uses 64-bit signal masks
1057 typedef struct ucontext {
1058 uint32_t uc_flags;
1059 struct ucontext* uc_link;
1060 stack_t uc_stack;
1061 mcontext_t uc_mcontext;
1062 // Other fields are not used by V8, don't define them here.
1063 } ucontext_t;
1064 enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
1065 #endif
1066
1067 #endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T)
1068
1069 static int GetThreadID() {
1070 #if defined(__ANDROID__)
1071 // Android's C library provides gettid(2).
1072 return gettid();
1073 #else
1074 // Glibc doesn't provide a wrapper for gettid(2).
1075 return syscall(SYS_gettid);
1076 #endif
1077 }
1078
1079
1080 class Sampler::PlatformData : public Malloced {
1081 public:
1082 PlatformData()
1083 : vm_tid_(GetThreadID()),
1084 profiled_thread_id_(ThreadId::Current()) {}
1085
1086 pthread_t vm_tid() const { return vm_tid_; }
1087 ThreadId profiled_thread_id() { return profiled_thread_id_; }
1088
1089 private:
1090 pthread_t vm_tid_;
1091 ThreadId profiled_thread_id_;
1092 };
1093
1094
1095 static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
1096 #if defined(__native_client__)
1097 // As Native Client does not support signal handling, profiling
1098 // is disabled.
1099 return;
1100 #else
1101 USE(info);
1102 if (signal != SIGPROF) return;
1103 Isolate* isolate = Isolate::UncheckedCurrent();
1104 if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
1105 // We require a fully initialized and entered isolate.
1106 return;
1107 }
1108 if (v8::Locker::IsActive() &&
1109 !isolate->thread_manager()->IsLockedByCurrentThread()) {
1110 return;
1111 }
1112
1113 Sampler* sampler = isolate->logger()->sampler();
1114 if (sampler == NULL || !sampler->IsActive()) return;
1115
1116 #if defined(USE_SIMULATOR)
1117 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
1118 ThreadId thread_id = sampler->platform_data()->profiled_thread_id();
1119 Isolate::PerIsolateThreadData* per_thread_data = isolate->
1120 FindPerThreadDataForThread(thread_id);
1121 if (!per_thread_data) return;
1122 Simulator* sim = per_thread_data->simulator();
1123 // Check if there is active simulator before allocating TickSample.
1124 if (!sim) return;
1125 #endif
1126 #endif // USE_SIMULATOR
1127
1128 TickSample sample_obj;
1129 TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
1130 if (sample == NULL) sample = &sample_obj;
1131
1132 #if defined(USE_SIMULATOR)
1133 #if V8_TARGET_ARCH_ARM
1134 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
1135 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
1136 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::r11));
1137 #elif V8_TARGET_ARCH_MIPS
1138 sample->pc = reinterpret_cast<Address>(sim->get_register(Simulator::pc));
1139 sample->sp = reinterpret_cast<Address>(sim->get_register(Simulator::sp));
1140 sample->fp = reinterpret_cast<Address>(sim->get_register(Simulator::fp));
1141 #endif
1142 #else
1143 // Extracting the sample from the context is extremely machine dependent.
1144 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
1145 mcontext_t& mcontext = ucontext->uc_mcontext;
1146 sample->state = isolate->current_vm_state();
1147 #if V8_HOST_ARCH_IA32
1148 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_EIP]);
1149 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_ESP]);
1150 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_EBP]);
1151 #elif V8_HOST_ARCH_X64
1152 sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_RIP]);
1153 sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_RSP]);
1154 sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_RBP]);
1155 #elif V8_HOST_ARCH_ARM
1156 #if defined(__GLIBC__) && !defined(__UCLIBC__) && \
1157 (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1158 // Old GLibc ARM versions used a gregs[] array to access the register
1159 // values from mcontext_t.
1160 sample->pc = reinterpret_cast<Address>(mcontext.gregs[R15]);
1161 sample->sp = reinterpret_cast<Address>(mcontext.gregs[R13]);
1162 sample->fp = reinterpret_cast<Address>(mcontext.gregs[R11]);
1163 #else
1164 sample->pc = reinterpret_cast<Address>(mcontext.arm_pc);
1165 sample->sp = reinterpret_cast<Address>(mcontext.arm_sp);
1166 sample->fp = reinterpret_cast<Address>(mcontext.arm_fp);
1167 #endif // defined(__GLIBC__) && !defined(__UCLIBC__) &&
1168 // (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 3))
1169 #elif V8_HOST_ARCH_MIPS
1170 sample->pc = reinterpret_cast<Address>(mcontext.pc);
1171 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);
1172 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]);
1173 #endif // V8_HOST_ARCH_*
1174 #endif // USE_SIMULATOR
1175 sampler->SampleStack(sample);
1176 sampler->Tick(sample);
1177 #endif // __native_client__
1178 }
1179
1180
1181 class SignalSender : public Thread {
1182 public:
1183 static const int kSignalSenderStackSize = 64 * KB;
1184
1185 explicit SignalSender(int interval)
1186 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
1187 vm_tgid_(getpid()),
1188 interval_(interval) {}
1189
1190 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
1191 static void TearDown() { delete mutex_; }
1192
1193 static void InstallSignalHandler() {
1194 struct sigaction sa;
1195 sa.sa_sigaction = ProfilerSignalHandler;
1196 sigemptyset(&sa.sa_mask);
1197 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1198 signal_handler_installed_ =
1199 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
1200 }
1201
1202 static void RestoreSignalHandler() {
1203 if (signal_handler_installed_) {
1204 sigaction(SIGPROF, &old_signal_handler_, 0);
1205 signal_handler_installed_ = false;
1206 }
1207 }
1208
1209 static void AddActiveSampler(Sampler* sampler) {
1210 ScopedLock lock(mutex_);
1211 SamplerRegistry::AddActiveSampler(sampler);
1212 if (instance_ == NULL) {
1213 // Start a thread that will send SIGPROF signal to VM threads,
1214 // when CPU profiling will be enabled.
1215 instance_ = new SignalSender(sampler->interval());
1216 instance_->StartSynchronously();
1217 } else {
1218 ASSERT(instance_->interval_ == sampler->interval());
1219 }
1220 }
1221
1222 static void RemoveActiveSampler(Sampler* sampler) {
1223 ScopedLock lock(mutex_);
1224 SamplerRegistry::RemoveActiveSampler(sampler);
1225 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
1226 instance_->Join();
1227 delete instance_;
1228 instance_ = NULL;
1229 RestoreSignalHandler();
1230 }
1231 }
1232
1233 // Implement Thread::Run().
1234 virtual void Run() {
1235 SamplerRegistry::State state;
1236 while ((state = SamplerRegistry::GetState()) !=
1237 SamplerRegistry::HAS_NO_SAMPLERS) {
1238 // When CPU profiling is enabled both JavaScript and C++ code is
1239 // profiled. We must not suspend.
1240 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
1241 if (!signal_handler_installed_) InstallSignalHandler();
1242 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
1243 } else {
1244 if (signal_handler_installed_) RestoreSignalHandler();
1245 }
1246 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
1247 }
1248 }
1249
1250 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
1251 if (!sampler->IsProfiling()) return;
1252 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
1253 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
1254 }
1255
1256 void SendProfilingSignal(int tid) {
1257 if (!signal_handler_installed_) return;
1258 // Glibc doesn't provide a wrapper for tgkill(2).
1259 #if defined(ANDROID)
1260 syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF);
1261 #else
1262 int result = syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
1263 USE(result);
1264 ASSERT(result == 0);
1265 #endif
1266 }
1267
1268 void Sleep() {
1269 // Convert ms to us and subtract 100 us to compensate delays
1270 // occuring during signal delivery.
1271 useconds_t interval = interval_ * 1000 - 100;
1272 #if defined(ANDROID)
1273 usleep(interval);
1274 #else
1275 int result = usleep(interval);
1276 #ifdef DEBUG
1277 if (result != 0 && errno != EINTR) {
1278 fprintf(stderr,
1279 "SignalSender usleep error; interval = %u, errno = %d\n",
1280 interval,
1281 errno);
1282 ASSERT(result == 0 || errno == EINTR);
1283 }
1284 #endif // DEBUG
1285 USE(result);
1286 #endif // ANDROID
1287 }
1288
1289 const int vm_tgid_;
1290 const int interval_;
1291
1292 // Protects the process wide state below.
1293 static Mutex* mutex_;
1294 static SignalSender* instance_;
1295 static bool signal_handler_installed_;
1296 static struct sigaction old_signal_handler_;
1297
1298 private:
1299 DISALLOW_COPY_AND_ASSIGN(SignalSender);
1300 };
1301
1302
1303 Mutex* SignalSender::mutex_ = NULL;
1304 SignalSender* SignalSender::instance_ = NULL;
1305 struct sigaction SignalSender::old_signal_handler_;
1306 bool SignalSender::signal_handler_installed_ = false;
1307
1308
1309 void OS::SetUp() { 994 void OS::SetUp() {
1310 // Seed the random number generator. We preserve microsecond resolution. 995 // Seed the random number generator. We preserve microsecond resolution.
1311 uint64_t seed = Ticks() ^ (getpid() << 16); 996 uint64_t seed = Ticks() ^ (getpid() << 16);
1312 srandom(static_cast<unsigned int>(seed)); 997 srandom(static_cast<unsigned int>(seed));
1313 limit_mutex = CreateMutex(); 998 limit_mutex = CreateMutex();
1314 999
1315 #ifdef __arm__ 1000 #ifdef __arm__
1316 // When running on ARM hardware check that the EABI used by V8 and 1001 // When running on ARM hardware check that the EABI used by V8 and
1317 // by the C code is the same. 1002 // by the C code is the same.
1318 bool hard_float = OS::ArmUsingHardFloat(); 1003 bool hard_float = OS::ArmUsingHardFloat();
1319 if (hard_float) { 1004 if (hard_float) {
1320 #if !USE_EABI_HARDFLOAT 1005 #if !USE_EABI_HARDFLOAT
1321 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without " 1006 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without "
1322 "-DUSE_EABI_HARDFLOAT\n"); 1007 "-DUSE_EABI_HARDFLOAT\n");
1323 exit(1); 1008 exit(1);
1324 #endif 1009 #endif
1325 } else { 1010 } else {
1326 #if USE_EABI_HARDFLOAT 1011 #if USE_EABI_HARDFLOAT
1327 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with " 1012 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with "
1328 "-DUSE_EABI_HARDFLOAT\n"); 1013 "-DUSE_EABI_HARDFLOAT\n");
1329 exit(1); 1014 exit(1);
1330 #endif 1015 #endif
1331 } 1016 }
1332 #endif 1017 #endif
1333 SignalSender::SetUp();
1334 } 1018 }
1335 1019
1336 1020
1337 void OS::TearDown() { 1021 void OS::TearDown() {
1338 SignalSender::TearDown();
1339 delete limit_mutex; 1022 delete limit_mutex;
1340 } 1023 }
1341 1024
1342 1025
1343 Sampler::Sampler(Isolate* isolate, int interval)
1344 : isolate_(isolate),
1345 interval_(interval),
1346 profiling_(false),
1347 active_(false),
1348 samples_taken_(0) {
1349 data_ = new PlatformData;
1350 }
1351
1352
1353 Sampler::~Sampler() {
1354 ASSERT(!IsActive());
1355 delete data_;
1356 }
1357
1358
1359 void Sampler::Start() {
1360 ASSERT(!IsActive());
1361 SetActive(true);
1362 SignalSender::AddActiveSampler(this);
1363 }
1364
1365
1366 void Sampler::Stop() {
1367 ASSERT(IsActive());
1368 SignalSender::RemoveActiveSampler(this);
1369 SetActive(false);
1370 }
1371
1372
1373 } } // namespace v8::internal 1026 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-freebsd.cc ('k') | src/platform-openbsd.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698