Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / data / lock-decoder / LockTracerDecoder.cs
index b5a3f755ea569ee32b7b4c830573dbbd97ba89b4..1471ea511817cbed7af16759188a359021cf0ca8 100644 (file)
@@ -86,7 +86,7 @@ LOCK RULES
 Simple locks:
        Can be acquired at any point regardless of which locks are taken or not.
        No other locks can be acquired or released while holding a simple lock.
-       Reentrancy is not recomended. (warning)
+       Reentrancy is not recommended. (warning)
        Simple locks are leaf locks on the lock lattice.
 
 Complex locks:
@@ -102,15 +102,35 @@ Global locks:
        Adding global locks is not to be taken lightly.
 
 The current lock hierarchy:
-loader lock
-       domain lock
-               domain jit lock
+loader lock (global)
+       domain lock (complex)
+               domain jit lock (complex)
+               marshal lock
                        simple locks
 
 Examples:
        You can take the loader lock without holding a domain lock.
-       You cannot take a domain lock if the loader lock is held.
+       You can take the domain load while holding the loader lock
+       You cannot take the loader lock if only the domain lock is held.
        You cannot take a domain lock while holding the lock to another domain.
+
+
+TODO:
+
+We have a few known ok violation. We need a way to whitelist them.
+
+Known ok issues:
+
+ERROR: tried to acquire lock DomainLock at mono_domain_code_reserve_align while holding DomainLock at mono_class_create_runtime_vtable: Hierarchy violation.
+       This is triggered when building the vtable of a non-root domain and fetching a vtable trampoline for an offset that has not been built. We'll take the root
+       domain lock while holding the other one.
+       This is ok since we never allow locking to have in the other direction, IOW, the root-domain lock is one level down from the other domain-locks.
+
+WARNING: tried to acquire lock ImageDataLock at mono_image_init_name_cache while holding ImageDataLock at mono_class_from_name
+WARNING: tried to acquire lock ImageDataLock at mono_image_init_name_cache while holding ImageDataLock at mono_image_add_to_name_cache
+       Both of those happen when filling up the name_cache, as it needs to alloc image memory.
+       This one is fixable by splitting mono_image_init_name_cache into a locked and an unlocked variants and calling them appropriately.
+
 */
 
 public enum Lock {
@@ -120,6 +140,12 @@ public enum Lock {
        DomainLock,
        DomainAssembliesLock,
        DomainJitCodeHashLock,
+       IcallLock,
+       AssemblyBindingLock,
+       MarshalLock,
+       ClassesLock,
+       LoaderGlobalDataLock,
+       ThreadsLock,
 }
 
 public class SimLock
@@ -139,6 +165,7 @@ public class SimLock
                        case Lock.DomainLock:
                                return 1;
                        case Lock.DomainJitCodeHashLock:
+                       case Lock.MarshalLock:
                                return 2;
                        default:
                                return 3;
@@ -157,6 +184,10 @@ public class SimLock
                get { return kind == Lock.LoaderLock; }
        }
 
+       public bool IsResursiveLock {
+               get { return kind == Lock.LoaderLock || kind == Lock.DomainLock; }
+       }
+
        /*locked is already owned by the thread, 'this' is the new one*/
        bool Compare (SimThread thread, SimLock locked, out bool isWarning, out string msg)
        {
@@ -212,7 +243,24 @@ public class SimLock
        }
 
        public override string ToString () {
-               return String.Format ("{0}", kind);
+               switch (kind) {
+               case Lock.LoaderLock:
+               case Lock.IcallLock:
+               case Lock.AssemblyBindingLock:
+               case Lock.MarshalLock:
+               case Lock.ClassesLock:
+               case Lock.LoaderGlobalDataLock:
+               case Lock.ThreadsLock:
+                       return String.Format ("{0}", kind);
+
+               case Lock.ImageDataLock:
+               case Lock.DomainLock:
+               case Lock.DomainAssembliesLock:
+               case Lock.DomainJitCodeHashLock:
+                       return String.Format ("{0}[{1}]", kind, id);
+               default:
+                       return String.Format ("Unknown({0})[{1}]", kind, id);
+               }
        }
 }
 
@@ -276,6 +324,15 @@ public class Trace {
                "mono_loader_unlock",
                "mono_image_lock",
                "mono_image_unlock",
+               "mono_icall_lock",
+               "mono_icall_unlock",
+               "add_record",
+               "mono_locks_lock_acquired",
+               "mono_locks_lock_released",
+               "mono_threads_lock",
+               "mono_threads_unlock",
+               "mono_domain_lock",
+               "mono_domain_unlock",
        };
 
        public Trace (string[] fields) {
@@ -326,6 +383,10 @@ public class Symbol : IComparable<Symbol>
        public int CompareTo(Symbol other) {
                return offset - other.offset;
        }
+
+       public void AdjustSize (Symbol next) {
+               size = next.offset - this.offset;
+       }
 }
 
 public interface SymbolTable {
@@ -352,21 +413,26 @@ public class OsxSymbolTable : SymbolTable
                string line;
                while ((line = proc.StandardOutput.ReadLine ()) != null) {
                        string[] fields = line.Split(new char[] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries);
-                       if (fields.Length < 4)
+                       if (fields.Length < 7)
                                continue;
-                       if (!(fields [1].Equals ("g") || fields [1].Equals ("d")))
-                               continue;
-                       if (!fields [2].Equals ("*UND*"))
+
+                       if (!fields [3].Equals ("FUN"))
                                continue;
 
                        int offset = fields [0].ParseHex ();
-                       string name = fields [3];
+                       string name = fields [6];
+                       if (name.StartsWith ("_"))
+                               name = name.Substring (1);
+
                        if (offset != 0)
                                list.Add (new Symbol (offset, 0, name));
                }
                table = new Symbol [list.Count];
                list.CopyTo (table, 0);
                Array.Sort (table);
+               for (int i = 1; i < table.Length; ++i) {
+                       table [i - 1].AdjustSize (table [i]);
+               }
        }
 
        public string Translate (int offset) {