+ /* The type initialization already failed once, rethrow the same exception */
+ if (raise_exception)
+ mono_raise_exception (get_type_init_exception_for_vtable (vtable));
+ return get_type_init_exception_for_vtable (vtable);
+ }
+ lock = g_hash_table_lookup (type_initialization_hash, vtable);
+ if (lock == NULL) {
+ /* This thread will get to do the initialization */
+ if (mono_domain_get () != domain) {
+ /* Transfer into the target domain */
+ last_domain = mono_domain_get ();
+ if (!mono_domain_set (domain, FALSE)) {
+ vtable->initialized = 1;
+ mono_type_initialization_unlock ();
+ if (raise_exception)
+ mono_raise_exception (mono_get_exception_appdomain_unloaded ());
+ return mono_get_exception_appdomain_unloaded ();
+ }
+ }
+ lock = g_malloc (sizeof(TypeInitializationLock));
+ mono_mutex_init_recursive (&lock->initialization_section);
+ lock->initializing_tid = tid;
+ lock->waiting_count = 1;
+ lock->done = FALSE;
+ /* grab the vtable lock while this thread still owns type_initialization_section */
+ /* This is why type_initialization_lock needs to enter blocking mode */
+ mono_type_init_lock (lock);
+ g_hash_table_insert (type_initialization_hash, vtable, lock);
+ do_initialization = 1;
+ } else {
+ gpointer blocked;
+ TypeInitializationLock *pending_lock;
+
+ if (lock->initializing_tid == tid || lock->done) {