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

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

Issue 12321046: Send SIGPROF signals on the profiler event processor thread (Closed) Base URL: git://github.com/v8/v8.git@master
Patch Set: Fixed typo: Profler->Profiler Created 7 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
« no previous file with comments | « src/platform-freebsd.cc ('k') | src/platform-macos.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 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1120 #elif V8_HOST_ARCH_MIPS 1120 #elif V8_HOST_ARCH_MIPS
1121 sample->pc = reinterpret_cast<Address>(mcontext.pc); 1121 sample->pc = reinterpret_cast<Address>(mcontext.pc);
1122 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]); 1122 sample->sp = reinterpret_cast<Address>(mcontext.gregs[29]);
1123 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]); 1123 sample->fp = reinterpret_cast<Address>(mcontext.gregs[30]);
1124 #endif // V8_HOST_ARCH_* 1124 #endif // V8_HOST_ARCH_*
1125 sampler->SampleStack(sample); 1125 sampler->SampleStack(sample);
1126 sampler->Tick(sample); 1126 sampler->Tick(sample);
1127 } 1127 }
1128 1128
1129 1129
1130 class Sampler::PlatformData : public Malloced { 1130 class CpuProfilerSignalHandler {
1131 public: 1131 public:
1132 PlatformData() : vm_tid_(GetThreadID()) {}
1133
1134 int vm_tid() const { return vm_tid_; }
1135
1136 private:
1137 const int vm_tid_;
1138 };
1139
1140
1141 class SignalSender : public Thread {
1142 public:
1143 static const int kSignalSenderStackSize = 64 * KB;
1144
1145 explicit SignalSender(int interval)
1146 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
1147 vm_tgid_(getpid()),
1148 interval_(interval) {}
1149
1150 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } 1132 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
1151 static void TearDown() { delete mutex_; } 1133 static void TearDown() { delete mutex_; }
1152 1134
1135 static bool RegisterProfilingSampler() {
1136 ScopedLock lock(mutex_);
1137 if (!profiling_samplers_count_) InstallSignalHandler();
1138 ++profiling_samplers_count_;
1139 return signal_handler_installed_;
1140 }
1141
1142 static void UnregisterProfilingSampler() {
1143 ScopedLock lock(mutex_);
1144 ASSERT(profiling_samplers_count_ > 0);
1145 if (!profiling_samplers_count_) return;
1146 if (profiling_samplers_count_ == 1) RestoreSignalHandler();
1147 --profiling_samplers_count_;
1148 }
1149
1150 private:
1153 static void InstallSignalHandler() { 1151 static void InstallSignalHandler() {
1154 struct sigaction sa; 1152 struct sigaction sa;
1155 sa.sa_sigaction = ProfilerSignalHandler; 1153 sa.sa_sigaction = ProfilerSignalHandler;
1156 sigemptyset(&sa.sa_mask); 1154 sigemptyset(&sa.sa_mask);
1157 sa.sa_flags = SA_RESTART | SA_SIGINFO; 1155 sa.sa_flags = SA_RESTART | SA_SIGINFO;
1158 signal_handler_installed_ = 1156 signal_handler_installed_ =
1159 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); 1157 (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
1160 } 1158 }
1161 1159
1162 static void RestoreSignalHandler() { 1160 static void RestoreSignalHandler() {
1163 if (signal_handler_installed_) { 1161 if (signal_handler_installed_) {
1164 sigaction(SIGPROF, &old_signal_handler_, 0); 1162 sigaction(SIGPROF, &old_signal_handler_, 0);
1165 signal_handler_installed_ = false; 1163 signal_handler_installed_ = false;
1166 } 1164 }
1167 } 1165 }
1168 1166
1167 // Protects the process wide state below.
1168 static Mutex* mutex_;
1169 static int profiling_samplers_count_;
1170 static bool signal_handler_installed_;
1171 static struct sigaction old_signal_handler_;
1172 };
1173
1174
1175 Mutex* CpuProfilerSignalHandler::mutex_ = NULL;
1176 int CpuProfilerSignalHandler::profiling_samplers_count_ = 0;
1177 bool CpuProfilerSignalHandler::signal_handler_installed_ = false;
1178 struct sigaction CpuProfilerSignalHandler::old_signal_handler_;
1179
1180
1181 class Sampler::PlatformData : public Malloced {
1182 public:
1183 PlatformData()
1184 : vm_tgid_(getpid()),
1185 vm_tid_(GetThreadID()),
1186 signal_handler_installed_(false) {}
1187
1188 void set_signal_handler_installed(bool value) {
1189 signal_handler_installed_ = value;
1190 }
1191
1192 void SendProfilingSignal() {
1193 if (!signal_handler_installed_) return;
1194 // Glibc doesn't provide a wrapper for tgkill(2).
1195 #if defined(ANDROID)
1196 syscall(__NR_tgkill, vm_tgid_, vm_tid_, SIGPROF);
1197 #else
1198 int result = syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF);
1199 USE(result);
1200 ASSERT(result == 0);
1201 #endif
1202 }
1203
1204 private:
1205 const int vm_tgid_;
1206 const int vm_tid_;
1207 bool signal_handler_installed_;
1208 };
1209
1210
1211 class SignalSender : public Thread {
1212 public:
1213 static const int kSignalSenderStackSize = 64 * KB;
1214
1215 explicit SignalSender(int interval)
1216 : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
1217 interval_(interval) {}
1218
1219 static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
1220 static void TearDown() { delete mutex_; }
1221
1169 static void AddActiveSampler(Sampler* sampler) { 1222 static void AddActiveSampler(Sampler* sampler) {
1170 ScopedLock lock(mutex_); 1223 ScopedLock lock(mutex_);
1171 SamplerRegistry::AddActiveSampler(sampler); 1224 SamplerRegistry::AddActiveSampler(sampler);
1172 if (instance_ == NULL) { 1225 if (instance_ == NULL) {
1173 // Start a thread that will send SIGPROF signal to VM threads, 1226 // Start a thread that will send SIGPROF signal to VM threads,
1174 // when CPU profiling will be enabled. 1227 // when CPU profiling will be enabled.
1175 instance_ = new SignalSender(sampler->interval()); 1228 instance_ = new SignalSender(sampler->interval());
1176 instance_->Start(); 1229 instance_->Start();
1177 } else { 1230 } else {
1178 ASSERT(instance_->interval_ == sampler->interval()); 1231 ASSERT(instance_->interval_ == sampler->interval());
1179 } 1232 }
1180 } 1233 }
1181 1234
1182 static void RemoveActiveSampler(Sampler* sampler) { 1235 static void RemoveActiveSampler(Sampler* sampler) {
1183 ScopedLock lock(mutex_); 1236 ScopedLock lock(mutex_);
1184 SamplerRegistry::RemoveActiveSampler(sampler); 1237 SamplerRegistry::RemoveActiveSampler(sampler);
1185 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 1238 if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
1186 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 1239 RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
1187 delete instance_; 1240 delete instance_;
1188 instance_ = NULL; 1241 instance_ = NULL;
1189 RestoreSignalHandler();
1190 } 1242 }
1191 } 1243 }
1192 1244
1193 // Implement Thread::Run(). 1245 // Implement Thread::Run().
1194 virtual void Run() { 1246 virtual void Run() {
1195 SamplerRegistry::State state; 1247 SamplerRegistry::State state;
1196 while ((state = SamplerRegistry::GetState()) != 1248 while ((state = SamplerRegistry::GetState()) !=
1197 SamplerRegistry::HAS_NO_SAMPLERS) { 1249 SamplerRegistry::HAS_NO_SAMPLERS) {
1198 // When CPU profiling is enabled both JavaScript and C++ code is 1250 // When CPU profiling is enabled both JavaScript and C++ code is
1199 // profiled. We must not suspend. 1251 // profiled. We must not suspend.
1200 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { 1252 if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
1201 if (!signal_handler_installed_) InstallSignalHandler();
1202 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); 1253 SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
1203 } else { 1254 } else {
1204 if (signal_handler_installed_) RestoreSignalHandler();
1205 if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue; 1255 if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
1206 } 1256 }
1207 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough. 1257 Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
1208 } 1258 }
1209 } 1259 }
1210 1260
1211 static void DoCpuProfile(Sampler* sampler, void* raw_sender) { 1261 static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
1212 if (!sampler->IsProfiling()) return; 1262 if (!sampler->IsProfiling()) return;
1213 SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); 1263 sampler->DoSample();
1214 sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
1215 }
1216
1217 void SendProfilingSignal(int tid) {
1218 if (!signal_handler_installed_) return;
1219 // Glibc doesn't provide a wrapper for tgkill(2).
1220 #if defined(ANDROID)
1221 syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF);
1222 #else
1223 int result = syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF);
1224 USE(result);
1225 ASSERT(result == 0);
1226 #endif
1227 } 1264 }
1228 1265
1229 void Sleep() { 1266 void Sleep() {
1230 // Convert ms to us and subtract 100 us to compensate delays 1267 // Convert ms to us and subtract 100 us to compensate delays
1231 // occuring during signal delivery. 1268 // occuring during signal delivery.
1232 useconds_t interval = interval_ * 1000 - 100; 1269 useconds_t interval = interval_ * 1000 - 100;
1233 #if defined(ANDROID) 1270 #if defined(ANDROID)
1234 usleep(interval); 1271 usleep(interval);
1235 #else 1272 #else
1236 int result = usleep(interval); 1273 int result = usleep(interval);
1237 #ifdef DEBUG 1274 #ifdef DEBUG
1238 if (result != 0 && errno != EINTR) { 1275 if (result != 0 && errno != EINTR) {
1239 fprintf(stderr, 1276 fprintf(stderr,
1240 "SignalSender usleep error; interval = %u, errno = %d\n", 1277 "SignalSender usleep error; interval = %u, errno = %d\n",
1241 interval, 1278 interval,
1242 errno); 1279 errno);
1243 ASSERT(result == 0 || errno == EINTR); 1280 ASSERT(result == 0 || errno == EINTR);
1244 } 1281 }
1245 #endif // DEBUG 1282 #endif // DEBUG
1246 USE(result); 1283 USE(result);
1247 #endif // ANDROID 1284 #endif // ANDROID
1248 } 1285 }
1249 1286
1250 const int vm_tgid_;
1251 const int interval_; 1287 const int interval_;
1252 1288
1253 // Protects the process wide state below. 1289 // Protects the process wide state below.
1254 static Mutex* mutex_; 1290 static Mutex* mutex_;
1255 static SignalSender* instance_; 1291 static SignalSender* instance_;
1256 static bool signal_handler_installed_;
1257 static struct sigaction old_signal_handler_; 1292 static struct sigaction old_signal_handler_;
1258 1293
1259 private: 1294 private:
1260 DISALLOW_COPY_AND_ASSIGN(SignalSender); 1295 DISALLOW_COPY_AND_ASSIGN(SignalSender);
1261 }; 1296 };
1262 1297
1263 1298
1264 Mutex* SignalSender::mutex_ = NULL; 1299 Mutex* SignalSender::mutex_ = NULL;
1265 SignalSender* SignalSender::instance_ = NULL; 1300 SignalSender* SignalSender::instance_ = NULL;
1266 struct sigaction SignalSender::old_signal_handler_; 1301 struct sigaction SignalSender::old_signal_handler_;
1267 bool SignalSender::signal_handler_installed_ = false;
1268 1302
1269 1303
1270 void OS::SetUp() { 1304 void OS::SetUp() {
1271 // Seed the random number generator. We preserve microsecond resolution. 1305 // Seed the random number generator. We preserve microsecond resolution.
1272 uint64_t seed = Ticks() ^ (getpid() << 16); 1306 uint64_t seed = Ticks() ^ (getpid() << 16);
1273 srandom(static_cast<unsigned int>(seed)); 1307 srandom(static_cast<unsigned int>(seed));
1274 limit_mutex = CreateMutex(); 1308 limit_mutex = CreateMutex();
1275 1309
1276 #ifdef __arm__ 1310 #ifdef __arm__
1277 // When running on ARM hardware check that the EABI used by V8 and 1311 // When running on ARM hardware check that the EABI used by V8 and
1278 // by the C code is the same. 1312 // by the C code is the same.
1279 bool hard_float = OS::ArmUsingHardFloat(); 1313 bool hard_float = OS::ArmUsingHardFloat();
1280 if (hard_float) { 1314 if (hard_float) {
1281 #if !USE_EABI_HARDFLOAT 1315 #if !USE_EABI_HARDFLOAT
1282 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without " 1316 PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without "
1283 "-DUSE_EABI_HARDFLOAT\n"); 1317 "-DUSE_EABI_HARDFLOAT\n");
1284 exit(1); 1318 exit(1);
1285 #endif 1319 #endif
1286 } else { 1320 } else {
1287 #if USE_EABI_HARDFLOAT 1321 #if USE_EABI_HARDFLOAT
1288 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with " 1322 PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with "
1289 "-DUSE_EABI_HARDFLOAT\n"); 1323 "-DUSE_EABI_HARDFLOAT\n");
1290 exit(1); 1324 exit(1);
1291 #endif 1325 #endif
1292 } 1326 }
1293 #endif 1327 #endif
1294 SignalSender::SetUp(); 1328 SignalSender::SetUp();
1329 CpuProfilerSignalHandler::SetUp();
1295 } 1330 }
1296 1331
1297 1332
1298 void OS::TearDown() { 1333 void OS::TearDown() {
1334 CpuProfilerSignalHandler::TearDown();
1299 SignalSender::TearDown(); 1335 SignalSender::TearDown();
1300 delete limit_mutex; 1336 delete limit_mutex;
1301 } 1337 }
1302 1338
1303 1339
1304 Sampler::Sampler(Isolate* isolate, int interval) 1340 Sampler::Sampler(Isolate* isolate, int interval)
1305 : isolate_(isolate), 1341 : isolate_(isolate),
1306 interval_(interval), 1342 interval_(interval),
1307 profiling_(false), 1343 profiling_(false),
1344 has_processing_thread_(false),
1308 active_(false), 1345 active_(false),
1309 samples_taken_(0) { 1346 samples_taken_(0) {
1310 data_ = new PlatformData; 1347 data_ = new PlatformData;
1311 } 1348 }
1312 1349
1313 1350
1314 Sampler::~Sampler() { 1351 Sampler::~Sampler() {
1315 ASSERT(!IsActive()); 1352 ASSERT(!IsActive());
1316 delete data_; 1353 delete data_;
1317 } 1354 }
1318 1355
1319 1356
1320 void Sampler::Start() { 1357 void Sampler::Start() {
1321 ASSERT(!IsActive()); 1358 ASSERT(!IsActive());
1322 SetActive(true); 1359 SetActive(true);
1323 SignalSender::AddActiveSampler(this); 1360 SignalSender::AddActiveSampler(this);
1324 } 1361 }
1325 1362
1326 1363
1327 void Sampler::Stop() { 1364 void Sampler::Stop() {
1328 ASSERT(IsActive()); 1365 ASSERT(IsActive());
1329 SignalSender::RemoveActiveSampler(this); 1366 SignalSender::RemoveActiveSampler(this);
1330 SetActive(false); 1367 SetActive(false);
1331 } 1368 }
1332 1369
1333 1370
1371 bool Sampler::CanSampleOnProfilerEventsProcessorThread() {
1372 return true;
1373 }
1374
1375
1376 void Sampler::DoSample() {
1377 platform_data()->SendProfilingSignal();
1378 }
1379
1380
1381 void Sampler::StartProfiling() {
1382 platform_data()->set_signal_handler_installed(
1383 CpuProfilerSignalHandler::RegisterProfilingSampler());
1384 }
1385
1386
1387 void Sampler::StopProfiling() {
1388 CpuProfilerSignalHandler::UnregisterProfilingSampler();
1389 platform_data()->set_signal_handler_installed(false);
1390 }
1391
1392
1334 } } // namespace v8::internal 1393 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-freebsd.cc ('k') | src/platform-macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698