Skip to content

Instantly share code, notes, and snippets.

@jieyu
Last active December 11, 2015 01:48
Show Gist options
  • Save jieyu/4525848 to your computer and use it in GitHub Desktop.
Save jieyu/4525848 to your computer and use it in GitHub Desktop.
How to track concurrency related events (e.g. thread creation, monitor entering, etc.) in Android.

How to track concurrency related events in Android

This document is based on the code of Android 4.1.1_r6.1 (Jelly Bean).

Thread forking

libcore/luni/src/main/java/java/lang/Thread.java

1043     public synchronized void start() {                                           
1044         if (hasBeenStarted) {                                                    
1045             throw new IllegalThreadStateException("Thread already started."); // TODO Externalize?
1046         } 
1047                                                                                  
1048         hasBeenStarted = true;                                                   
1049 
1050         VMThread.create(this, stackSize);                                        
1051     }

dalvik/vm/native/java_lang_VMThread.cpp

31 static void Dalvik_java_lang_VMThread_create(const u4* args, JValue* pResult)     
32 {    
33     Object* threadObj = (Object*) args[0];                                        
34     s8 stackSize = GET_ARG_LONG(args, 1);                                         
35 
36     /* copying collector will pin threadObj for us since it was an argument */    
37     dvmCreateInterpThread(threadObj, (int) stackSize);                            
38     RETURN_VOID();
39 }

dalvik/vm/Thread.cpp

1232 bool dvmCreateInterpThread(Object* threadObj, int reqStackSize)                  
1233 {                                                                                
1234     assert(threadObj != NULL);
1235                                                                                  
1236     Thread* self = dvmThreadSelf();
...      ...
1303     pthread_t threadHandle;
1304     int cc = pthread_create(&threadHandle, &threadAttr, interpThreadStart,
1305                             newThread);
...      ...
1451 }

Thread joining

libcore/luni/src/main/java/java/lang/Thread.java

753     public final void join() throws InterruptedException {
754         VMThread t = vmThread;
755         if (t == null) {
756             return;
757         }
758 
759         synchronized (t) {
760             while (isAlive()) {
761                 t.wait();
762             }
763         }
764     }

Thread begin/end

dalvik/vm/Thread.cpp

1456 static void* interpThreadStart(void* arg)
1457 {   
1458     Thread* self = (Thread*) arg;
1459 
1460     std::string threadName(dvmGetThreadName(self));
1461     setThreadName(threadName.c_str());
...      ...
1533     Method* run = self->threadObj->clazz->vtable[gDvm.voffJavaLangThread_run];
...      ...
1538     dvmCallMethod(self, run, self->threadObj, &unused);
...      ...
1545     dvmDetachCurrentThread();
1546 
1547     return NULL;
1548 }

Mutex locking

dalvik/vm/Sync.cpp

855 void dvmLockObject(Thread* self, Object *obj)                                    
856 {
...     ...
868     thinp = &obj->lock;
869 retry:
870     thin = *thinp;
871     if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
...         ...
876         if (LW_LOCK_OWNER(thin) == threadId) {
...             ...
890         } else if (LW_LOCK_OWNER(thin) == 0) {
...             ...
898             if (android_atomic_acquire_cas(thin, newThin,
899                     (int32_t*)thinp) != 0) {
...                 ...
903                 goto retry;
904             }
905         } else {
...             ...
986         }
987     } else {
...         ...
992         lockMonitor(self, LW_MONITOR(obj->lock));
993     }
994 }

Mutex unlocking

dalvik/vm/Sync.cpp

1001 bool dvmUnlockObject(Thread* self, Object *obj)
1002 {
...      ...
1012     thin = *(volatile u4 *)&obj->lock;
1013     if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
...          ...
1018         if (LW_LOCK_OWNER(thin) == self->threadId) {
...              ...
1023             if (LW_LOCK_COUNT(thin) == 0) {
...                  ...
1030                 android_atomic_release_store(thin, (int32_t*)&obj->lock);
1031             } else {
...                  ...
1036                 obj->lock -= 1 << LW_LOCK_COUNT_SHIFT;
1037             }
1038         } else {
...              ...
1045         }
1046     } else {
1052         if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
...              ...
1056             return false;
1057         }
1058     }
1059     return true;
1060 }

Conditional variable wait

dalvik/vm/native/java_lang_Object.cpp

87 static void Dalvik_java_lang_Object_wait(const u4* args, JValue* pResult,         
88     const Method* method, Thread* self)                                           
89 {                                                                                 
90     Object* thisPtr = (Object*) args[0];                                          
91                                                                                   
92     dvmObjectWait(self, thisPtr, GET_ARG_LONG(args,1), (s4)args[3], true);        
93     RETURN_VOID();                                                                
94 }

dalvik/vm/Sync.cpp

1065 void dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
1066     bool interruptShouldThrow)
1067 {
1068     Monitor* mon;
1069     u4 thin = *(volatile u4 *)&obj->lock;
...      ...
1090     mon = LW_MONITOR(obj->lock);
1091     waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1092 }

Conditional variable notify

dalvik/vm/native/java_lang_Object.cpp

63 static void Dalvik_java_lang_Object_notify(const u4* args, JValue* pResult,
64     const Method* method, Thread* self)
65 {
66     Object* thisPtr = (Object*) args[0];
67 
68     dvmObjectNotify(self, thisPtr);
69     RETURN_VOID();                                                                
70 }

dalvik/vm/Sync.cpp

1097 void dvmObjectNotify(Thread* self, Object *obj)
1098 {
1099     u4 thin = *(volatile u4 *)&obj->lock;
...      ...
1104     if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
...          ...
1115     } else {
...          ...
1118         notifyMonitor(self, LW_MONITOR(thin));
1119     }
1120 }

Conditional variable notifyAll

dalvik/vm/native/java_lang_Object.cpp

75 static void Dalvik_java_lang_Object_notifyAll(const u4* args, JValue* pResult,    
76     const Method* method, Thread* self)                                           
77 {                                                                                 
78     Object* thisPtr = (Object*) args[0];                                          
79                                                                                   
80     dvmObjectNotifyAll(self, thisPtr);                                            
81     RETURN_VOID();                                                                
82 }

dalvik/vm/Sync.cpp

1125 void dvmObjectNotifyAll(Thread* self, Object *obj)
1126 {
1127     u4 thin = *(volatile u4 *)&obj->lock;
...      ...
1132     if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
...          ...
1143     } else {
...          ...
1146         notifyAllMonitor(self, LW_MONITOR(thin));
1147     }
1148 }

Thread sleep

dalvik/vm/native/java_lang_VMThread.cpp

215 static void Dalvik_java_lang_VMThread_sleep(const u4* args, JValue* pResult)
216 {   
217     dvmThreadSleep(GET_ARG_LONG(args,0), args[2]);
218     RETURN_VOID();
219 }

dalvik/vm/Sync.cpp

1164 void dvmThreadSleep(u8 msec, u4 nsec)                                            
1165 {                                                                                
1166     Thread* self = dvmThreadSelf();                                              
1167     Monitor* mon = gDvm.threadSleepMon;                                          
1168                                                                                  
1169     /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */  
1170     if (msec == 0 && nsec == 0)                                                  
1171         nsec++;                                                                  
1172                                                                                  
1173     lockMonitor(self, mon);                                                      
1174     waitMonitor(self, mon, msec, nsec, true);                                    
1175     unlockMonitor(self, mon);                                                    
1176 }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment