diff options
| -rw-r--r-- | runtime/trace.cc | 36 | ||||
| -rw-r--r-- | runtime/trace.h | 5 | ||||
| -rw-r--r-- | test/2246-trace-stream/expected-stdout.txt | 82 | ||||
| -rw-r--r-- | test/2246-trace-stream/src/Main.java | 7 | ||||
| -rw-r--r-- | test/2246-trace-stream/src/NonStreamTraceParser.java | 2 |
5 files changed, 103 insertions, 29 deletions
diff --git a/runtime/trace.cc b/runtime/trace.cc index 051a600650..bad4992b46 100644 --- a/runtime/trace.cc +++ b/runtime/trace.cc @@ -621,6 +621,11 @@ void Trace::StopTracing(bool finish_tracing, bool flush_file) { the_trace_->FlushStreamingBuffer(thread); thread->ResetMethodTraceBuffer(); } + // Record threads here before resetting the_trace_ to prevent any races between + // unregistering the thread and resetting the_trace_. + std::string name; + thread->GetThreadName(name); + the_trace->threads_list_.Put(thread->GetTid(), name); } } @@ -1242,28 +1247,17 @@ void Trace::DumpMethodList(std::ostream& os) { } } -static void DumpThread(Thread* t, void* arg) { - std::ostream& os = *reinterpret_cast<std::ostream*>(arg); - std::string name; - t->GetThreadName(name); - // We use only 16 bits to encode thread id. On Android, we don't expect to use more than - // 16-bits for a Tid. For 32-bit platforms it is always ensured we use less than 16 bits. - // See __check_max_thread_id in bionic for more details. Even on 64-bit the max threads - // is currently less than 65536. - // TODO(mythria): On host, we know thread ids can be greater than 16 bits. Consider adding - // a map similar to method ids. - DCHECK(!kIsTargetBuild || t->GetTid() < (1 << 16)); - os << static_cast<uint16_t>(t->GetTid()) << "\t" << name << "\n"; -} - void Trace::DumpThreadList(std::ostream& os) { - Thread* self = Thread::Current(); - for (const auto& it : exited_threads_) { + for (const auto& it : threads_list_) { + // We use only 16 bits to encode thread id. On Android, we don't expect to use more than + // 16-bits for a Tid. For 32-bit platforms it is always ensured we use less than 16 bits. + // See __check_max_thread_id in bionic for more details. Even on 64-bit the max threads + // is currently less than 65536. + // TODO(mythria): On host, we know thread ids can be greater than 16 bits. Consider adding + // a map similar to method ids. + DCHECK(!kIsTargetBuild || it.first < (1 << 16)); os << static_cast<uint16_t>(it.first) << "\t" << it.second << "\n"; } - Locks::thread_list_lock_->AssertNotHeld(self); - MutexLock mu(self, *Locks::thread_list_lock_); - Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os); } void Trace::StoreExitingThreadInfo(Thread* thread) { @@ -1271,9 +1265,7 @@ void Trace::StoreExitingThreadInfo(Thread* thread) { if (the_trace_ != nullptr) { std::string name; thread->GetThreadName(name); - // The same thread/tid may be used multiple times. As SafeMap::Put does not allow to override - // a previous mapping, use SafeMap::Overwrite. - the_trace_->exited_threads_.Overwrite(thread->GetTid(), name); + the_trace_->threads_list_.Put(thread->GetTid(), name); } } diff --git a/runtime/trace.h b/runtime/trace.h index c3f903c58a..5f6f3c2cd8 100644 --- a/runtime/trace.h +++ b/runtime/trace.h @@ -395,8 +395,9 @@ class Trace final : public instrumentation::InstrumentationListener { // Did we overflow the buffer recording traces? bool overflow_; - // Map of thread ids and names that have already exited. - SafeMap<pid_t, std::string> exited_threads_; + // Map of thread ids and names. We record the information when the threads are + // exiting and when the tracing has finished. + SafeMap<pid_t, std::string> threads_list_; // Sampling profiler sampling interval. int interval_us_; diff --git a/test/2246-trace-stream/expected-stdout.txt b/test/2246-trace-stream/expected-stdout.txt index cb4c0cacf7..90706b50fc 100644 --- a/test/2246-trace-stream/expected-stdout.txt +++ b/test/2246-trace-stream/expected-stdout.txt @@ -72,3 +72,85 @@ ....<<E main Main callThrowFunction ()V Main.java ...<< main Main doSomeWorkThrow ()V Main.java ...>> main Main$VMDebug $noinline$stopMethodTracing ()V Main.java +***** non streaming test ******* +.>> main Main main ([Ljava/lang/String;)V Main.java +..>> main Main testTracing (ZLBaseTraceParser;I)V Main.java +...>> main Main$VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V Main.java +....>> main java.lang.reflect.Method invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; Method.java +.....>> main dalvik.system.VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V VMDebug.java +......>> main dalvik.system.VMDebug startMethodTracingFd (Ljava/lang/String;IIIZIZ)V VMDebug.java +......<< main dalvik.system.VMDebug startMethodTracingFd (Ljava/lang/String;IIIZIZ)V VMDebug.java +.....<< main dalvik.system.VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V VMDebug.java +....<< main java.lang.reflect.Method invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; Method.java +...<< main Main$VMDebug startMethodTracing (Ljava/lang/String;Ljava/io/FileDescriptor;IIZIZ)V Main.java +...>> main java.lang.Thread start ()V Thread.java +....>> main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java +....<< main java.lang.ThreadGroup add (Ljava/lang/Thread;)V ThreadGroup.java +....>> main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java +....<< main java.lang.Thread nativeCreate (Ljava/lang/Thread;JZ)V Thread.java +...<< main java.lang.Thread start ()V Thread.java +...>> main java.lang.Thread join ()V Thread.java +....>> main java.lang.Thread join (J)V Thread.java +.....>> main java.lang.System currentTimeMillis ()J System.java +.....<< main java.lang.System currentTimeMillis ()J System.java +.....>> main java.lang.Thread isAlive ()Z Thread.java +.....<< main java.lang.Thread isAlive ()Z Thread.java +.....>> main java.lang.Object wait (J)V Object.java +......>> main java.lang.Object wait (JI)V Object.java +.>> TestThread2246 java.lang.Thread run ()V Thread.java +..>> TestThread2246 Main$$ExternalSyntheticLambda0 run ()V D8$$SyntheticClass +...>> TestThread2246 Main lambda$testTracing$0 ()V Main.java +....>> TestThread2246 Main <init> ()V Main.java +.....>> TestThread2246 java.lang.Object <init> ()V Object.java +.....<< TestThread2246 java.lang.Object <init> ()V Object.java +....<< TestThread2246 Main <init> ()V Main.java +....>> TestThread2246 Main $noinline$doSomeWork ()V Main.java +.....>> TestThread2246 Main callOuterFunction ()V Main.java +......>> TestThread2246 Main callLeafFunction ()V Main.java +......<< TestThread2246 Main callLeafFunction ()V Main.java +.....<< TestThread2246 Main callOuterFunction ()V Main.java +.....>> TestThread2246 Main callLeafFunction ()V Main.java +.....<< TestThread2246 Main callLeafFunction ()V Main.java +....<< TestThread2246 Main $noinline$doSomeWork ()V Main.java +...<< TestThread2246 Main lambda$testTracing$0 ()V Main.java +..<< TestThread2246 Main$$ExternalSyntheticLambda0 run ()V D8$$SyntheticClass +.<< TestThread2246 java.lang.Thread run ()V Thread.java +.>> TestThread2246 java.lang.ThreadGroup threadTerminated (Ljava/lang/Thread;)V ThreadGroup.java +..>> TestThread2246 java.lang.ThreadGroup remove (Ljava/lang/Thread;)V ThreadGroup.java +...>> TestThread2246 java.lang.System arraycopy (Ljava/lang/Object;ILjava/lang/Object;II)V System.java +...<< TestThread2246 java.lang.System arraycopy (Ljava/lang/Object;ILjava/lang/Object;II)V System.java +..<< TestThread2246 java.lang.ThreadGroup remove (Ljava/lang/Thread;)V ThreadGroup.java +.<< TestThread2246 java.lang.ThreadGroup threadTerminated (Ljava/lang/Thread;)V ThreadGroup.java +......<< main java.lang.Object wait (JI)V Object.java +.....<< main java.lang.Object wait (J)V Object.java +.....>> main java.lang.Thread isAlive ()Z Thread.java +.....<< main java.lang.Thread isAlive ()Z Thread.java +....<< main java.lang.Thread join (J)V Thread.java +...<< main java.lang.Thread join ()V Thread.java +...>> main Main $noinline$doSomeWork ()V Main.java +....>> main Main callOuterFunction ()V Main.java +.....>> main Main callLeafFunction ()V Main.java +.....<< main Main callLeafFunction ()V Main.java +....<< main Main callOuterFunction ()V Main.java +....>> main Main callLeafFunction ()V Main.java +....<< main Main callLeafFunction ()V Main.java +...<< main Main $noinline$doSomeWork ()V Main.java +...>> main Main doSomeWorkThrow ()V Main.java +....>> main Main callThrowFunction ()V Main.java +.....>> main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java +......>> main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java +.......>> main java.lang.Object <init> ()V Object.java +.......<< main java.lang.Object <init> ()V Object.java +.......>> main java.util.Collections emptyList ()Ljava/util/List; Collections.java +.......<< main java.util.Collections emptyList ()Ljava/util/List; Collections.java +.......>> main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java +........>> main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java +........<< main java.lang.Throwable nativeFillInStackTrace ()Ljava/lang/Object; Throwable.java +.......<< main java.lang.Throwable fillInStackTrace ()Ljava/lang/Throwable; Throwable.java +......<< main java.lang.Throwable <init> (Ljava/lang/String;)V Throwable.java +.....<< main java.lang.Exception <init> (Ljava/lang/String;)V Exception.java +....<<E main Main callThrowFunction ()V Main.java +...<< main Main doSomeWorkThrow ()V Main.java +...>> main Main$VMDebug $noinline$stopMethodTracing ()V Main.java +....>> main java.lang.reflect.Method invoke (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; Method.java +.....>> main dalvik.system.VMDebug stopMethodTracing ()V VMDebug.java diff --git a/test/2246-trace-stream/src/Main.java b/test/2246-trace-stream/src/Main.java index 942061f738..daada7d1b1 100644 --- a/test/2246-trace-stream/src/Main.java +++ b/test/2246-trace-stream/src/Main.java @@ -36,10 +36,9 @@ public class Main { testTracing( /* streaming=*/true, stream_parser, BaseTraceParser.STREAMING_DUAL_CLOCK_VERSION); - // TODO(mythria): Enable after fixing failures on the bots. - // System.out.println("***** non streaming test *******"); - // NonStreamTraceParser non_stream_parser = new NonStreamTraceParser(); - // testTracing(/* streaming=*/false, non_stream_parser, BaseTraceParser.DUAL_CLOCK_VERSION); + System.out.println("***** non streaming test *******"); + NonStreamTraceParser non_stream_parser = new NonStreamTraceParser(); + testTracing(/* streaming=*/false, non_stream_parser, BaseTraceParser.DUAL_CLOCK_VERSION); } public static void testTracing(boolean streaming, BaseTraceParser parser, int expected_version) diff --git a/test/2246-trace-stream/src/NonStreamTraceParser.java b/test/2246-trace-stream/src/NonStreamTraceParser.java index 3219591d3f..db0450f4f4 100644 --- a/test/2246-trace-stream/src/NonStreamTraceParser.java +++ b/test/2246-trace-stream/src/NonStreamTraceParser.java @@ -52,7 +52,7 @@ public class NonStreamTraceParser extends BaseTraceParser { line = readLine(); while (!line.startsWith(START_SECTION_ID)) { - String[] threadInfo = line.split("\t"); + String[] threadInfo = line.split("\t", 2); threadIdMap.put(Integer.decode(threadInfo[0]), threadInfo[1]); line = readLine(); } |