28b4747b27ee08f368cd2348b0eae02f0a4676eb
[mono.git] / mono / metadata / gc.c
1 /**
2  * \file
3  * GC icalls.
4  *
5  * Author: Paolo Molaro <lupus@ximian.com>
6  *
7  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11  */
12
13 #include <config.h>
14 #include <glib.h>
15 #include <string.h>
16
17 #include <mono/metadata/gc-internals.h>
18 #include <mono/metadata/mono-gc.h>
19 #include <mono/metadata/threads.h>
20 #include <mono/metadata/tabledefs.h>
21 #include <mono/metadata/exception.h>
22 #include <mono/metadata/profiler-private.h>
23 #include <mono/metadata/domain-internals.h>
24 #include <mono/metadata/class-internals.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/mono-mlist.h>
27 #include <mono/metadata/threads-types.h>
28 #include <mono/metadata/threadpool.h>
29 #include <mono/sgen/sgen-conf.h>
30 #include <mono/sgen/sgen-gc.h>
31 #include <mono/utils/mono-logger-internals.h>
32 #include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
33 #include <mono/metadata/attach.h>
34 #include <mono/metadata/console-io.h>
35 #include <mono/metadata/w32process.h>
36 #include <mono/utils/mono-os-semaphore.h>
37 #include <mono/utils/mono-memory-model.h>
38 #include <mono/utils/mono-counters.h>
39 #include <mono/utils/mono-time.h>
40 #include <mono/utils/dtrace.h>
41 #include <mono/utils/mono-threads.h>
42 #include <mono/utils/mono-threads-coop.h>
43 #include <mono/utils/atomic.h>
44 #include <mono/utils/mono-coop-semaphore.h>
45 #include <mono/utils/hazard-pointer.h>
46 #include <mono/utils/w32api.h>
47
48 #ifndef HOST_WIN32
49 #include <pthread.h>
50 #endif
51
52 typedef struct DomainFinalizationReq {
53         gint32 ref;
54         MonoDomain *domain;
55         MonoCoopSem done;
56 } DomainFinalizationReq;
57
58 static gboolean gc_disabled;
59
60 static gboolean finalizing_root_domain;
61
62 gboolean log_finalizers;
63 gboolean mono_do_not_finalize;
64 volatile gboolean suspend_finalizers;
65 gchar **mono_do_not_finalize_class_names ;
66
67 #define mono_finalizer_lock() mono_coop_mutex_lock (&finalizer_mutex)
68 #define mono_finalizer_unlock() mono_coop_mutex_unlock (&finalizer_mutex)
69 static MonoCoopMutex finalizer_mutex;
70 static MonoCoopMutex reference_queue_mutex;
71
72 static GSList *domains_to_finalize;
73
74 static gboolean finalizer_thread_exited;
75 /* Uses finalizer_mutex */
76 static MonoCoopCond exited_cond;
77
78 static MonoInternalThread *gc_thread;
79
80 #ifdef TARGET_WIN32
81 static HANDLE pending_done_event;
82 #else
83 static gboolean pending_done;
84 static MonoCoopCond pending_done_cond;
85 static MonoCoopMutex pending_done_mutex;
86 #endif
87
88 static void object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*));
89
90 static void reference_queue_proccess_all (void);
91 static void mono_reference_queue_cleanup (void);
92 static void reference_queue_clear_for_domain (MonoDomain *domain);
93
94
95 static MonoThreadInfoWaitRet
96 guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertable)
97 {
98         MonoThreadInfoWaitRet result;
99
100         MONO_ENTER_GC_SAFE;
101         result = mono_thread_info_wait_one_handle (thread_handle, timeout, alertable);
102         MONO_EXIT_GC_SAFE;
103
104         return result;
105 }
106
107 typedef struct {
108         MonoCoopCond *cond;
109         MonoCoopMutex *mutex;
110 } BreakCoopAlertableWaitUD;
111
112 static inline void
113 break_coop_alertable_wait (gpointer user_data)
114 {
115         BreakCoopAlertableWaitUD *ud = (BreakCoopAlertableWaitUD*)user_data;
116
117         mono_coop_mutex_lock (ud->mutex);
118         mono_coop_cond_signal (ud->cond);
119         mono_coop_mutex_unlock (ud->mutex);
120
121         g_free (ud);
122 }
123
124 /*
125  * coop_cond_timedwait_alertable:
126  *
127  *   Wait on COND/MUTEX. If ALERTABLE is non-null, the wait can be interrupted.
128  * In that case, *ALERTABLE will be set to TRUE, and 0 is returned.
129  */
130 static inline gint
131 coop_cond_timedwait_alertable (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32 timeout_ms, gboolean *alertable)
132 {
133         BreakCoopAlertableWaitUD *ud;
134         int res;
135
136         if (alertable) {
137                 ud = g_new0 (BreakCoopAlertableWaitUD, 1);
138                 ud->cond = cond;
139                 ud->mutex = mutex;
140
141                 mono_thread_info_install_interrupt (break_coop_alertable_wait, ud, alertable);
142                 if (*alertable) {
143                         g_free (ud);
144                         return 0;
145                 }
146         }
147         res = mono_coop_cond_timedwait (cond, mutex, timeout_ms);
148         if (alertable) {
149                 mono_thread_info_uninstall_interrupt (alertable);
150                 if (*alertable)
151                         return 0;
152                 else {
153                         /* the interrupt token has not been taken by another
154                          * thread, so it's our responsability to free it up. */
155                         g_free (ud);
156                 }
157         }
158         return res;
159 }
160
161 /* 
162  * actually, we might want to queue the finalize requests in a separate thread,
163  * but we need to be careful about the execution domain of the thread...
164  */
165 void
166 mono_gc_run_finalize (void *obj, void *data)
167 {
168         MonoError error;
169         MonoObject *exc = NULL;
170         MonoObject *o;
171 #ifndef HAVE_SGEN_GC
172         MonoObject *o2;
173 #endif
174         MonoMethod* finalizer = NULL;
175         MonoDomain *caller_domain = mono_domain_get ();
176         MonoDomain *domain;
177         RuntimeInvokeFunction runtime_invoke;
178
179         // This function is called from the innards of the GC, so our best alternative for now is to do polling here
180         mono_threads_safepoint ();
181
182         o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data));
183
184         if (mono_do_not_finalize) {
185                 if (!mono_do_not_finalize_class_names)
186                         return;
187
188                 size_t namespace_len = strlen (o->vtable->klass->name_space);
189                 for (int i = 0; mono_do_not_finalize_class_names [i]; ++i) {
190                         const char *name = mono_do_not_finalize_class_names [i];
191                         if (strncmp (name, o->vtable->klass->name_space, namespace_len))
192                                 break;
193                         if (name [namespace_len] != '.')
194                                 break;
195                         if (strcmp (name + namespace_len + 1, o->vtable->klass->name))
196                                 break;
197                         return;
198                 }
199         }
200
201         if (log_finalizers)
202                 g_log ("mono-gc-finalizers", G_LOG_LEVEL_DEBUG, "<%s at %p> Starting finalizer checks.", o->vtable->klass->name, o);
203
204         if (suspend_finalizers)
205                 return;
206
207         domain = o->vtable->domain;
208
209 #ifndef HAVE_SGEN_GC
210         mono_domain_finalizers_lock (domain);
211
212         o2 = (MonoObject *)g_hash_table_lookup (domain->finalizable_objects_hash, o);
213
214         mono_domain_finalizers_unlock (domain);
215
216         if (!o2)
217                 /* Already finalized somehow */
218                 return;
219 #endif
220
221         /* make sure the finalizer is not called again if the object is resurrected */
222         object_register_finalizer ((MonoObject *)obj, NULL);
223
224         if (log_finalizers)
225                 g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Registered finalizer as processed.", o->vtable->klass->name, o);
226
227         if (o->vtable->klass == mono_defaults.internal_thread_class) {
228                 MonoInternalThread *t = (MonoInternalThread*)o;
229
230                 if (mono_gc_is_finalizer_internal_thread (t))
231                         /* Avoid finalizing ourselves */
232                         return;
233         }
234
235         if (o->vtable->klass->image == mono_defaults.corlib && !strcmp (o->vtable->klass->name, "DynamicMethod") && finalizing_root_domain) {
236                 /*
237                  * These can't be finalized during unloading/shutdown, since that would
238                  * free the native code which can still be referenced by other
239                  * finalizers.
240                  * FIXME: This is not perfect, objects dying at the same time as 
241                  * dynamic methods can still reference them even when !shutdown.
242                  */
243                 return;
244         }
245
246         if (mono_runtime_get_no_exec ())
247                 return;
248
249         /* speedup later... and use a timeout */
250         /* g_print ("Finalize run on %p %s.%s\n", o, mono_object_class (o)->name_space, mono_object_class (o)->name); */
251
252         /* Use _internal here, since this thread can enter a doomed appdomain */
253         mono_domain_set_internal (mono_object_domain (o));
254
255         /* delegates that have a native function pointer allocated are
256          * registered for finalization, but they don't have a Finalize
257          * method, because in most cases it's not needed and it's just a waste.
258          */
259         if (o->vtable->klass->delegate) {
260                 MonoDelegate* del = (MonoDelegate*)o;
261                 if (del->delegate_trampoline)
262                         mono_delegate_free_ftnptr ((MonoDelegate*)o);
263                 mono_domain_set_internal (caller_domain);
264                 return;
265         }
266
267         finalizer = mono_class_get_finalizer (o->vtable->klass);
268
269         /* If object has a CCW but has no finalizer, it was only
270          * registered for finalization in order to free the CCW.
271          * Else it needs the regular finalizer run.
272          * FIXME: what to do about ressurection and suppression
273          * of finalizer on object with CCW.
274          */
275         if (mono_marshal_free_ccw (o) && !finalizer) {
276                 mono_domain_set_internal (caller_domain);
277                 return;
278         }
279
280         /* 
281          * To avoid the locking plus the other overhead of mono_runtime_invoke_checked (),
282          * create and precompile a wrapper which calls the finalize method using
283          * a CALLVIRT.
284          */
285         if (log_finalizers)
286                 g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Compiling finalizer.", o->vtable->klass->name, o);
287
288         if (!domain->finalize_runtime_invoke) {
289                 MonoMethod *invoke = mono_marshal_get_runtime_invoke (mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE);
290
291                 domain->finalize_runtime_invoke = mono_compile_method_checked (invoke, &error);
292                 mono_error_assert_ok (&error); /* expect this not to fail */
293         }
294
295         runtime_invoke = (RuntimeInvokeFunction)domain->finalize_runtime_invoke;
296
297         mono_runtime_class_init_full (o->vtable, &error);
298         if (!is_ok (&error))
299                 goto unhandled_error;
300
301         if (G_UNLIKELY (MONO_GC_FINALIZE_INVOKE_ENABLED ())) {
302                 MONO_GC_FINALIZE_INVOKE ((unsigned long)o, mono_object_get_size (o),
303                                 o->vtable->klass->name_space, o->vtable->klass->name);
304         }
305
306         if (log_finalizers)
307                 g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o->vtable->klass->name, o);
308
309         MONO_PROFILER_RAISE (gc_finalizing_object, (o));
310
311         runtime_invoke (o, NULL, &exc, NULL);
312
313         MONO_PROFILER_RAISE (gc_finalized_object, (o));
314
315         if (log_finalizers)
316                 g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o->vtable->klass->name, o);
317
318 unhandled_error:
319         if (!is_ok (&error))
320                 exc = (MonoObject*)mono_error_convert_to_exception (&error);
321         if (exc)
322                 mono_thread_internal_unhandled_exception (exc);
323
324         mono_domain_set_internal (caller_domain);
325 }
326
327 gpointer
328 mono_gc_out_of_memory (size_t size)
329 {
330         /* 
331          * we could allocate at program startup some memory that we could release 
332          * back to the system at this point if we're really low on memory (ie, size is
333          * lower than the memory we set apart)
334          */
335         mono_raise_exception (mono_domain_get ()->out_of_memory_ex);
336
337         return NULL;
338 }
339
340 /*
341  * Some of our objects may point to a different address than the address returned by GC_malloc()
342  * (because of the GetHashCode hack), but we need to pass the real address to register_finalizer.
343  * This also means that in the callback we need to adjust the pointer to get back the real
344  * MonoObject*.
345  * We also need to be consistent in the use of the GC_debug* variants of malloc and register_finalizer, 
346  * since that, too, can cause the underlying pointer to be offset.
347  */
348 static void
349 object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*))
350 {
351         MonoDomain *domain;
352
353         g_assert (obj != NULL);
354
355         domain = obj->vtable->domain;
356
357 #if HAVE_BOEHM_GC
358         if (mono_domain_is_unloading (domain) && (callback != NULL))
359                 /*
360                  * Can't register finalizers in a dying appdomain, since they
361                  * could be invoked after the appdomain has been unloaded.
362                  */
363                 return;
364
365         mono_domain_finalizers_lock (domain);
366
367         if (callback)
368                 g_hash_table_insert (domain->finalizable_objects_hash, obj, obj);
369         else
370                 g_hash_table_remove (domain->finalizable_objects_hash, obj);
371
372         mono_domain_finalizers_unlock (domain);
373
374         mono_gc_register_for_finalization (obj, callback);
375 #elif defined(HAVE_SGEN_GC)
376         /*
377          * If we register finalizers for domains that are unloading we might
378          * end up running them while or after the domain is being cleared, so
379          * the objects will not be valid anymore.
380          */
381         if (!mono_domain_is_unloading (domain))
382                 mono_gc_register_for_finalization (obj, callback);
383 #endif
384 }
385
386 /**
387  * mono_object_register_finalizer:
388  * \param obj object to register
389  *
390  * Records that object \p obj has a finalizer, this will call the
391  * Finalize method when the garbage collector disposes the object.
392  * 
393  */
394 void
395 mono_object_register_finalizer (MonoObject *obj)
396 {
397         /* g_print ("Registered finalizer on %p %s.%s\n", obj, mono_object_class (obj)->name_space, mono_object_class (obj)->name); */
398         object_register_finalizer (obj, mono_gc_run_finalize);
399 }
400
401 /**
402  * mono_domain_finalize:
403  * \param domain the domain to finalize
404  * \param timeout msecs to wait for the finalization to complete, \c -1 to wait indefinitely
405  *
406  * Request finalization of all finalizable objects inside \p domain. Wait
407  * \p timeout msecs for the finalization to complete.
408  *
409  * \returns TRUE if succeeded, FALSE if there was a timeout
410  */
411 gboolean
412 mono_domain_finalize (MonoDomain *domain, guint32 timeout) 
413 {
414         DomainFinalizationReq *req;
415         MonoInternalThread *thread = mono_thread_internal_current ();
416         gint res;
417         gboolean ret;
418         gint64 start;
419
420         if (mono_thread_internal_current () == gc_thread)
421                 /* We are called from inside a finalizer, not much we can do here */
422                 return FALSE;
423
424         /* 
425          * No need to create another thread 'cause the finalizer thread
426          * is still working and will take care of running the finalizers
427          */ 
428         
429         if (gc_disabled)
430                 return TRUE;
431
432         /* We don't support domain finalization without a GC */
433         if (mono_gc_is_null ())
434                 return FALSE;
435
436         mono_gc_collect (mono_gc_max_generation ());
437
438         req = g_new0 (DomainFinalizationReq, 1);
439         req->ref = 2;
440         req->domain = domain;
441         mono_coop_sem_init (&req->done, 0);
442
443         if (domain == mono_get_root_domain ())
444                 finalizing_root_domain = TRUE;
445         
446         mono_finalizer_lock ();
447
448         domains_to_finalize = g_slist_append (domains_to_finalize, req);
449
450         mono_finalizer_unlock ();
451
452         /* Tell the finalizer thread to finalize this appdomain */
453         mono_gc_finalize_notify ();
454
455         if (timeout == -1)
456                 timeout = MONO_INFINITE_WAIT;
457         if (timeout != MONO_INFINITE_WAIT)
458                 start = mono_msec_ticks ();
459
460         ret = TRUE;
461
462         for (;;) {
463                 if (timeout == MONO_INFINITE_WAIT) {
464                         res = mono_coop_sem_wait (&req->done, MONO_SEM_FLAGS_ALERTABLE);
465                 } else {
466                         gint64 elapsed = mono_msec_ticks () - start;
467                         if (elapsed >= timeout) {
468                                 ret = FALSE;
469                                 break;
470                         }
471
472                         res = mono_coop_sem_timedwait (&req->done, timeout - elapsed, MONO_SEM_FLAGS_ALERTABLE);
473                 }
474
475                 if (res == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
476                         break;
477                 } else if (res == MONO_SEM_TIMEDWAIT_RET_ALERTED) {
478                         if ((thread->state & (ThreadState_AbortRequested | ThreadState_SuspendRequested)) != 0) {
479                                 ret = FALSE;
480                                 break;
481                         }
482                 } else if (res == MONO_SEM_TIMEDWAIT_RET_TIMEDOUT) {
483                         ret = FALSE;
484                         break;
485                 } else {
486                         g_error ("%s: unknown result %d", __func__, res);
487                 }
488         }
489
490         if (!ret) {
491                 /* Try removing the req from domains_to_finalize:
492                  *  - if it's not found: the domain is being finalized,
493                  *     so we the ref count is already decremented
494                  *  - if it's found: the domain is not yet being finalized,
495                  *     so we can safely decrement the ref */
496
497                 gboolean found;
498
499                 mono_finalizer_lock ();
500
501                 found = g_slist_index (domains_to_finalize, req) != -1;
502                 if (found)
503                         domains_to_finalize = g_slist_remove (domains_to_finalize, req);
504
505                 mono_finalizer_unlock ();
506
507                 if (found) {
508                         /* We have to decrement it wherever we
509                          * remove it from domains_to_finalize */
510                         if (InterlockedDecrement (&req->ref) != 1)
511                                 g_error ("%s: req->ref should be 1, as we are the first one to decrement it", __func__);
512                 }
513
514                 goto done;
515         }
516
517 done:
518         if (InterlockedDecrement (&req->ref) == 0) {
519                 mono_coop_sem_destroy (&req->done);
520                 g_free (req);
521         }
522
523         return ret;
524 }
525
526 void
527 ves_icall_System_GC_InternalCollect (int generation)
528 {
529         mono_gc_collect (generation);
530 }
531
532 gint64
533 ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollection)
534 {
535         if (forceCollection)
536                 mono_gc_collect (mono_gc_max_generation ());
537         return mono_gc_get_used_size ();
538 }
539
540 void
541 ves_icall_System_GC_KeepAlive (MonoObject *obj)
542 {
543         /*
544          * Does nothing.
545          */
546 }
547
548 void
549 ves_icall_System_GC_ReRegisterForFinalize (MonoObject *obj)
550 {
551         MONO_CHECK_ARG_NULL (obj,);
552
553         object_register_finalizer (obj, mono_gc_run_finalize);
554 }
555
556 void
557 ves_icall_System_GC_SuppressFinalize (MonoObject *obj)
558 {
559         MONO_CHECK_ARG_NULL (obj,);
560
561         /* delegates have no finalizers, but we register them to deal with the
562          * unmanaged->managed trampoline. We don't let the user suppress it
563          * otherwise we'd leak it.
564          */
565         if (obj->vtable->klass->delegate)
566                 return;
567
568         /* FIXME: Need to handle case where obj has COM Callable Wrapper
569          * generated for it that needs cleaned up, but user wants to suppress
570          * their derived object finalizer. */
571
572         object_register_finalizer (obj, NULL);
573 }
574
575 void
576 ves_icall_System_GC_WaitForPendingFinalizers (void)
577 {
578         if (mono_gc_is_null ())
579                 return;
580
581         if (!mono_gc_pending_finalizers ())
582                 return;
583
584         if (mono_thread_internal_current () == gc_thread)
585                 /* Avoid deadlocks */
586                 return;
587
588         /*
589         If the finalizer thread is not live, lets pretend no finalizers are pending since the current thread might
590         be the one responsible for starting it up.
591         */
592         if (gc_thread == NULL)
593                 return;
594
595 #ifdef TARGET_WIN32
596         ResetEvent (pending_done_event);
597         mono_gc_finalize_notify ();
598         /* g_print ("Waiting for pending finalizers....\n"); */
599         MONO_ENTER_GC_SAFE;
600         WaitForSingleObjectEx (pending_done_event, INFINITE, TRUE);
601         MONO_EXIT_GC_SAFE;
602         /* g_print ("Done pending....\n"); */
603 #else
604         gboolean alerted = FALSE;
605         mono_coop_mutex_lock (&pending_done_mutex);
606         pending_done = FALSE;
607         mono_gc_finalize_notify ();
608         while (!pending_done) {
609                 coop_cond_timedwait_alertable (&pending_done_cond, &pending_done_mutex, MONO_INFINITE_WAIT, &alerted);
610                 if (alerted)
611                         break;
612         }
613         mono_coop_mutex_unlock (&pending_done_mutex);
614 #endif
615 }
616
617 void
618 ves_icall_System_GC_register_ephemeron_array (MonoObject *array)
619 {
620 #ifdef HAVE_SGEN_GC
621         if (!mono_gc_ephemeron_array_add (array)) {
622                 mono_set_pending_exception (mono_object_domain (array)->out_of_memory_ex);
623                 return;
624         }
625 #endif
626 }
627
628 MonoObject*
629 ves_icall_System_GC_get_ephemeron_tombstone (void)
630 {
631         return mono_domain_get ()->ephemeron_tombstone;
632 }
633
634 MonoObject *
635 ves_icall_System_GCHandle_GetTarget (guint32 handle)
636 {
637         return mono_gchandle_get_target (handle);
638 }
639
640 /*
641  * if type == -1, change the target of the handle, otherwise allocate a new handle.
642  */
643 guint32
644 ves_icall_System_GCHandle_GetTargetHandle (MonoObject *obj, guint32 handle, gint32 type)
645 {
646         if (type == -1) {
647                 mono_gchandle_set_target (handle, obj);
648                 /* the handle doesn't change */
649                 return handle;
650         }
651         switch (type) {
652         case HANDLE_WEAK:
653                 return mono_gchandle_new_weakref (obj, FALSE);
654         case HANDLE_WEAK_TRACK:
655                 return mono_gchandle_new_weakref (obj, TRUE);
656         case HANDLE_NORMAL:
657                 return mono_gchandle_new (obj, FALSE);
658         case HANDLE_PINNED:
659                 return mono_gchandle_new (obj, TRUE);
660         default:
661                 g_assert_not_reached ();
662         }
663         return 0;
664 }
665
666 void
667 ves_icall_System_GCHandle_FreeHandle (guint32 handle)
668 {
669         mono_gchandle_free (handle);
670 }
671
672 gpointer
673 ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle)
674 {
675         MonoObject *obj;
676
677         if (MONO_GC_HANDLE_TYPE (handle) != HANDLE_PINNED)
678                 return (gpointer)-2;
679         obj = mono_gchandle_get_target (handle);
680         if (obj) {
681                 MonoClass *klass = mono_object_class (obj);
682                 if (klass == mono_defaults.string_class) {
683                         return mono_string_chars ((MonoString*)obj);
684                 } else if (klass->rank) {
685                         return mono_array_addr ((MonoArray*)obj, char, 0);
686                 } else {
687                         /* the C# code will check and throw the exception */
688                         /* FIXME: missing !klass->blittable test, see bug #61134 */
689                         if (mono_class_is_auto_layout (klass))
690                                 return (gpointer)-1;
691                         return (char*)obj + sizeof (MonoObject);
692                 }
693         }
694         return NULL;
695 }
696
697 MonoBoolean
698 mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle)
699 {
700         return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
701 }
702
703 static MonoCoopSem finalizer_sem;
704 static volatile gboolean finished;
705
706 /*
707  * mono_gc_finalize_notify:
708  *
709  *   Notify the finalizer thread that finalizers etc.
710  * are available to be processed.
711  * This is async signal safe.
712  */
713 void
714 mono_gc_finalize_notify (void)
715 {
716 #ifdef DEBUG
717         g_message ( "%s: prodding finalizer", __func__);
718 #endif
719
720         if (mono_gc_is_null ())
721                 return;
722
723         mono_coop_sem_post (&finalizer_sem);
724 }
725
726 /*
727 This is the number of entries allowed in the hazard free queue before
728 we explicitly cycle the finalizer thread to trigger pumping the queue.
729
730 It was picked empirically by running the corlib test suite in a stress
731 scenario where all hazard entries are queued.
732
733 In this extreme scenario we double the number of times we cycle the finalizer
734 thread compared to just GC calls.
735
736 Entries are usually in the order of 100's of bytes each, so we're limiting
737 floating garbage to be in the order of a dozen kb.
738 */
739 static gboolean finalizer_thread_pulsed;
740 #define HAZARD_QUEUE_OVERFLOW_SIZE 20
741
742 static void
743 hazard_free_queue_is_too_big (size_t size)
744 {
745         if (size < HAZARD_QUEUE_OVERFLOW_SIZE)
746                 return;
747
748         if (finalizer_thread_pulsed || InterlockedCompareExchange (&finalizer_thread_pulsed, TRUE, FALSE))
749                 return;
750
751         mono_gc_finalize_notify ();
752 }
753
754 static void
755 hazard_free_queue_pump (void)
756 {
757         mono_thread_hazardous_try_free_all ();
758         finalizer_thread_pulsed = FALSE;
759 }
760
761 #ifdef HAVE_BOEHM_GC
762
763 static void
764 collect_objects (gpointer key, gpointer value, gpointer user_data)
765 {
766         GPtrArray *arr = (GPtrArray*)user_data;
767         g_ptr_array_add (arr, key);
768 }
769
770 #endif
771
772 /*
773  * finalize_domain_objects:
774  *
775  *  Run the finalizers of all finalizable objects in req->domain.
776  */
777 static void
778 finalize_domain_objects (void)
779 {
780         DomainFinalizationReq *req = NULL;
781         MonoDomain *domain;
782
783         if (domains_to_finalize) {
784                 mono_finalizer_lock ();
785                 if (domains_to_finalize) {
786                         req = (DomainFinalizationReq *)domains_to_finalize->data;
787                         domains_to_finalize = g_slist_remove (domains_to_finalize, req);
788                 }
789                 mono_finalizer_unlock ();
790         }
791
792         if (!req)
793                 return;
794
795         domain = req->domain;
796
797         /* Process finalizers which are already in the queue */
798         mono_gc_invoke_finalizers ();
799
800 #ifdef HAVE_BOEHM_GC
801         while (g_hash_table_size (domain->finalizable_objects_hash) > 0) {
802                 int i;
803                 GPtrArray *objs;
804                 /* 
805                  * Since the domain is unloading, nobody is allowed to put
806                  * new entries into the hash table. But finalize_object might
807                  * remove entries from the hash table, so we make a copy.
808                  */
809                 objs = g_ptr_array_new ();
810                 g_hash_table_foreach (domain->finalizable_objects_hash, collect_objects, objs);
811                 /* printf ("FINALIZING %d OBJECTS.\n", objs->len); */
812
813                 for (i = 0; i < objs->len; ++i) {
814                         MonoObject *o = (MonoObject*)g_ptr_array_index (objs, i);
815                         /* FIXME: Avoid finalizing threads, etc */
816                         mono_gc_run_finalize (o, 0);
817                 }
818
819                 g_ptr_array_free (objs, TRUE);
820         }
821 #elif defined(HAVE_SGEN_GC)
822         mono_gc_finalize_domain (domain);
823         mono_gc_invoke_finalizers ();
824 #endif
825
826         /* cleanup the reference queue */
827         reference_queue_clear_for_domain (domain);
828         
829         /* printf ("DONE.\n"); */
830         mono_coop_sem_post (&req->done);
831
832         if (InterlockedDecrement (&req->ref) == 0) {
833                 /* mono_domain_finalize already returned, and
834                  * doesn't hold a reference to req anymore. */
835                 mono_coop_sem_destroy (&req->done);
836                 g_free (req);
837         }
838 }
839
840 static gsize WINAPI
841 finalizer_thread (gpointer unused)
842 {
843         MonoError error;
844         gboolean wait = TRUE;
845
846         MonoString *finalizer = mono_string_new_checked (mono_get_root_domain (), "Finalizer", &error);
847         mono_error_assert_ok (&error);
848         mono_thread_set_name_internal (mono_thread_internal_current (), finalizer, FALSE, FALSE, &error);
849         mono_error_assert_ok (&error);
850
851         /* Register a hazard free queue pump callback */
852         mono_hazard_pointer_install_free_queue_size_callback (hazard_free_queue_is_too_big);
853
854         while (!finished) {
855                 /* Wait to be notified that there's at least one
856                  * finaliser to run
857                  */
858
859                 g_assert (mono_domain_get () == mono_get_root_domain ());
860                 mono_gc_set_skip_thread (TRUE);
861
862                 if (wait) {
863                         /* An alertable wait is required so this thread can be suspended on windows */
864                         mono_coop_sem_wait (&finalizer_sem, MONO_SEM_FLAGS_ALERTABLE);
865                 }
866                 wait = TRUE;
867
868                 mono_gc_set_skip_thread (FALSE);
869
870                 mono_threads_perform_thread_dump ();
871
872                 mono_console_handle_async_ops ();
873
874                 mono_attach_maybe_start ();
875
876                 finalize_domain_objects ();
877
878                 MONO_PROFILER_RAISE (gc_finalizing, ());
879
880                 /* If finished == TRUE, mono_gc_cleanup has been called (from mono_runtime_cleanup),
881                  * before the domain is unloaded.
882                  */
883                 mono_gc_invoke_finalizers ();
884
885                 MONO_PROFILER_RAISE (gc_finalized, ());
886
887                 mono_threads_join_threads ();
888
889                 reference_queue_proccess_all ();
890
891                 mono_w32process_signal_finished ();
892
893                 hazard_free_queue_pump ();
894
895                 /* Avoid posting the pending done event until there are pending finalizers */
896                 if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == MONO_SEM_TIMEDWAIT_RET_SUCCESS) {
897                         /* Don't wait again at the start of the loop */
898                         wait = FALSE;
899                 } else {
900 #ifdef TARGET_WIN32
901                         SetEvent (pending_done_event);
902 #else
903                         mono_coop_mutex_lock (&pending_done_mutex);
904                         pending_done = TRUE;
905                         mono_coop_cond_signal (&pending_done_cond);
906                         mono_coop_mutex_unlock (&pending_done_mutex);
907 #endif
908                 }
909         }
910
911         mono_finalizer_lock ();
912         finalizer_thread_exited = TRUE;
913         mono_coop_cond_signal (&exited_cond);
914         mono_finalizer_unlock ();
915
916         return 0;
917 }
918
919 #ifndef LAZY_GC_THREAD_CREATION
920 static
921 #endif
922 void
923 mono_gc_init_finalizer_thread (void)
924 {
925         MonoError error;
926         gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, MONO_THREAD_CREATE_FLAGS_NONE, &error);
927         mono_error_assert_ok (&error);
928 }
929
930 void
931 mono_gc_init (void)
932 {
933         mono_coop_mutex_init_recursive (&finalizer_mutex);
934         mono_coop_mutex_init_recursive (&reference_queue_mutex);
935
936         mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.minor_gc_count);
937         mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.major_gc_count);
938         mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time);
939         mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time);
940         mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent);
941
942         mono_gc_base_init ();
943
944         if (mono_gc_is_disabled ()) {
945                 gc_disabled = TRUE;
946                 return;
947         }
948
949 #ifdef TARGET_WIN32
950         pending_done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
951         g_assert (pending_done_event);
952 #else
953         mono_coop_cond_init (&pending_done_cond);
954         mono_coop_mutex_init (&pending_done_mutex);
955 #endif
956
957         mono_coop_cond_init (&exited_cond);
958         mono_coop_sem_init (&finalizer_sem, 0);
959
960 #ifndef LAZY_GC_THREAD_CREATION
961         mono_gc_init_finalizer_thread ();
962 #endif
963 }
964
965 void
966 mono_gc_cleanup (void)
967 {
968 #ifdef DEBUG
969         g_message ("%s: cleaning up finalizer", __func__);
970 #endif
971
972         if (mono_gc_is_null ())
973                 return;
974
975         if (!gc_disabled) {
976
977                 /* Stop all worker threads before signalling the finalizer to stop
978                  * That way the finalizer has a chance to clean up the worker threads */
979                 mono_gc_base_cleanup ();
980
981                 finished = TRUE;
982                 if (mono_thread_internal_current () != gc_thread) {
983                         int ret;
984                         gint64 start;
985                         const gint64 timeout = 40 * 1000;
986
987                         mono_gc_finalize_notify ();
988
989                         start = mono_msec_ticks ();
990
991                         /* Finishing the finalizer thread, so wait a little bit... */
992                         /* MS seems to wait for about 2 seconds per finalizer thread */
993                         /* and 40 seconds for all finalizers to finish */
994                         for (;;) {
995                                 gint64 elapsed;
996
997                                 if (finalizer_thread_exited) {
998                                         /* Wait for the thread to actually exit. We don't want the wait
999                                          * to be alertable, because we assert on the result to be SUCCESS_0 */
1000                                         ret = guarded_wait (gc_thread->handle, MONO_INFINITE_WAIT, FALSE);
1001                                         g_assert (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0);
1002
1003                                         /* Clean up the finalizer (and other threads that might still wait to be joined) */
1004                                         mono_threads_join_threads ();
1005                                         break;
1006                                 }
1007
1008                                 elapsed = mono_msec_ticks () - start;
1009                                 if (elapsed >= timeout) {
1010                                         /* timeout */
1011
1012                                         /* Set a flag which the finalizer thread can check */
1013                                         suspend_finalizers = TRUE;
1014                                         mono_gc_suspend_finalizers ();
1015
1016                                         /* Try to abort the thread, in the hope that it is running managed code */
1017                                         mono_thread_internal_abort (gc_thread);
1018
1019                                         /* Wait for it to stop */
1020                                         ret = guarded_wait (gc_thread->handle, 100, FALSE);
1021                                         if (ret == MONO_THREAD_INFO_WAIT_RET_TIMEOUT) {
1022                                                 /* The finalizer thread refused to exit, suspend it forever. */
1023                                                 mono_thread_internal_suspend_for_shutdown (gc_thread);
1024                                                 break;
1025                                         }
1026
1027                                         g_assert (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0);
1028
1029                                         /* Clean up the finalizer (and other threads that might still wait to be joined) */
1030                                         mono_threads_join_threads ();
1031                                         break;
1032                                 }
1033
1034                                 mono_finalizer_lock ();
1035                                 if (!finalizer_thread_exited)
1036                                         mono_coop_cond_timedwait (&exited_cond, &finalizer_mutex, timeout - elapsed);
1037                                 mono_finalizer_unlock ();
1038                         }
1039                 }
1040                 gc_thread = NULL;
1041         }
1042
1043         mono_reference_queue_cleanup ();
1044
1045         mono_coop_mutex_destroy (&finalizer_mutex);
1046         mono_coop_mutex_destroy (&reference_queue_mutex);
1047 }
1048
1049 gboolean
1050 mono_gc_is_finalizer_internal_thread (MonoInternalThread *thread)
1051 {
1052         return thread == gc_thread;
1053 }
1054
1055 /**
1056  * mono_gc_is_finalizer_thread:
1057  * \param thread the thread to test.
1058  *
1059  * In Mono objects are finalized asynchronously on a separate thread.
1060  * This routine tests whether the \p thread argument represents the
1061  * finalization thread.
1062  * 
1063  * \returns TRUE if \p thread is the finalization thread.
1064  */
1065 gboolean
1066 mono_gc_is_finalizer_thread (MonoThread *thread)
1067 {
1068         return mono_gc_is_finalizer_internal_thread (thread->internal_thread);
1069 }
1070
1071 #if defined(__MACH__)
1072 static pthread_t mach_exception_thread;
1073
1074 void
1075 mono_gc_register_mach_exception_thread (pthread_t thread)
1076 {
1077         mach_exception_thread = thread;
1078 }
1079
1080 pthread_t
1081 mono_gc_get_mach_exception_thread (void)
1082 {
1083         return mach_exception_thread;
1084 }
1085 #endif
1086
1087 static MonoReferenceQueue *ref_queues;
1088
1089 static void
1090 ref_list_remove_element (RefQueueEntry **prev, RefQueueEntry *element)
1091 {
1092         do {
1093                 /* Guard if head is changed concurrently. */
1094                 while (*prev != element)
1095                         prev = &(*prev)->next;
1096         } while (prev && InterlockedCompareExchangePointer ((volatile gpointer *)prev, element->next, element) != element);
1097 }
1098
1099 static void
1100 ref_list_push (RefQueueEntry **head, RefQueueEntry *value)
1101 {
1102         RefQueueEntry *current;
1103         do {
1104                 current = *head;
1105                 value->next = current;
1106                 STORE_STORE_FENCE; /*Must make sure the previous store is visible before the CAS. */
1107         } while (InterlockedCompareExchangePointer ((volatile gpointer *)head, value, current) != current);
1108 }
1109
1110 static void
1111 reference_queue_proccess (MonoReferenceQueue *queue)
1112 {
1113         RefQueueEntry **iter = &queue->queue;
1114         RefQueueEntry *entry;
1115         while ((entry = *iter)) {
1116                 if (queue->should_be_deleted || !mono_gchandle_get_target (entry->gchandle)) {
1117                         mono_gchandle_free ((guint32)entry->gchandle);
1118                         ref_list_remove_element (iter, entry);
1119                         queue->callback (entry->user_data);
1120                         g_free (entry);
1121                 } else {
1122                         iter = &entry->next;
1123                 }
1124         }
1125 }
1126
1127 static void
1128 reference_queue_proccess_all (void)
1129 {
1130         MonoReferenceQueue **iter;
1131         MonoReferenceQueue *queue = ref_queues;
1132         for (; queue; queue = queue->next)
1133                 reference_queue_proccess (queue);
1134
1135 restart:
1136         mono_coop_mutex_lock (&reference_queue_mutex);
1137         for (iter = &ref_queues; *iter;) {
1138                 queue = *iter;
1139                 if (!queue->should_be_deleted) {
1140                         iter = &queue->next;
1141                         continue;
1142                 }
1143                 if (queue->queue) {
1144                         mono_coop_mutex_unlock (&reference_queue_mutex);
1145                         reference_queue_proccess (queue);
1146                         goto restart;
1147                 }
1148                 *iter = queue->next;
1149                 g_free (queue);
1150         }
1151         mono_coop_mutex_unlock (&reference_queue_mutex);
1152 }
1153
1154 static void
1155 mono_reference_queue_cleanup (void)
1156 {
1157         MonoReferenceQueue *queue = ref_queues;
1158         for (; queue; queue = queue->next)
1159                 queue->should_be_deleted = TRUE;
1160         reference_queue_proccess_all ();
1161 }
1162
1163 static void
1164 reference_queue_clear_for_domain (MonoDomain *domain)
1165 {
1166         MonoReferenceQueue *queue = ref_queues;
1167         for (; queue; queue = queue->next) {
1168                 RefQueueEntry **iter = &queue->queue;
1169                 RefQueueEntry *entry;
1170                 while ((entry = *iter)) {
1171                         if (entry->domain == domain) {
1172                                 mono_gchandle_free ((guint32)entry->gchandle);
1173                                 ref_list_remove_element (iter, entry);
1174                                 queue->callback (entry->user_data);
1175                                 g_free (entry);
1176                         } else {
1177                                 iter = &entry->next;
1178                         }
1179                 }
1180         }
1181 }
1182 /**
1183  * mono_gc_reference_queue_new:
1184  * \param callback callback used when processing collected entries.
1185  *
1186  * Create a new reference queue used to process collected objects.
1187  * A reference queue let you add a pair of (managed object, user data)
1188  * using the \c mono_gc_reference_queue_add method.
1189  *
1190  * Once the managed object is collected \p callback will be called
1191  * in the finalizer thread with 'user data' as argument.
1192  *
1193  * The callback is called from the finalizer thread without any locks held.
1194  * When an AppDomain is unloaded, all callbacks for objects belonging to it
1195  * will be invoked.
1196  *
1197  * \returns the new queue.
1198  */
1199 MonoReferenceQueue*
1200 mono_gc_reference_queue_new (mono_reference_queue_callback callback)
1201 {
1202         MonoReferenceQueue *res = g_new0 (MonoReferenceQueue, 1);
1203         res->callback = callback;
1204
1205         mono_coop_mutex_lock (&reference_queue_mutex);
1206         res->next = ref_queues;
1207         ref_queues = res;
1208         mono_coop_mutex_unlock (&reference_queue_mutex);
1209
1210         return res;
1211 }
1212
1213 /**
1214  * mono_gc_reference_queue_add:
1215  * \param queue the queue to add the reference to.
1216  * \param obj the object to be watched for collection
1217  * \param user_data parameter to be passed to the queue callback
1218  *
1219  * Queue an object to be watched for collection, when the \p obj is
1220  * collected, the callback that was registered for the \p queue will
1221  * be invoked with \p user_data as argument.
1222  *
1223  * \returns FALSE if the queue is scheduled to be freed.
1224  */
1225 gboolean
1226 mono_gc_reference_queue_add (MonoReferenceQueue *queue, MonoObject *obj, void *user_data)
1227 {
1228         RefQueueEntry *entry;
1229         if (queue->should_be_deleted)
1230                 return FALSE;
1231
1232         g_assert (obj != NULL);
1233
1234         entry = g_new0 (RefQueueEntry, 1);
1235         entry->user_data = user_data;
1236         entry->domain = mono_object_domain (obj);
1237
1238         entry->gchandle = mono_gchandle_new_weakref (obj, TRUE);
1239         mono_object_register_finalizer (obj);
1240
1241         ref_list_push (&queue->queue, entry);
1242         return TRUE;
1243 }
1244
1245 /**
1246  * mono_gc_reference_queue_free:
1247  * \param queue the queue that should be freed.
1248  *
1249  * This operation signals that \p queue should be freed. This operation is deferred
1250  * as it happens on the finalizer thread.
1251  *
1252  * After this call, no further objects can be queued. It's the responsibility of the
1253  * caller to make sure that no further attempt to access queue will be made.
1254  */
1255 void
1256 mono_gc_reference_queue_free (MonoReferenceQueue *queue)
1257 {
1258         queue->should_be_deleted = TRUE;
1259 }