EXTERN void val_gc(value v, finalizer f ) { if( !val_is_abstract(v) ) failure("val_gc"); if( f ) GC_REGISTER_FINALIZER_NO_ORDER(v,(GC_finalization_proc)__on_finalize,f,0,0); else GC_REGISTER_FINALIZER_NO_ORDER(v,NULL,NULL,0,0); }
void rvmRegisterReference(Env* env, Object* reference, Object* referent) { if (referent) { // Add 'reference' to the references list for 'referent' in the referents hashtable rvmLockMutex(&referentsLock); ReferenceList* l = rvmAllocateMemory(env, sizeof(ReferenceList)); if (!l) goto done; // OOM thrown l->reference = reference; void* key = (void*) GC_HIDE_POINTER(referent); // Hide the pointer from the GC so that it doesn't prevent the referent from being GCed. ReferentEntry* referentEntry; HASH_FIND_PTR(referents, &key, referentEntry); if (!referentEntry) { // referent is not in the hashtable. Add it. referentEntry = rvmAllocateMemory(env, sizeof(ReferentEntry)); if (!referentEntry) goto done; // OOM thrown referentEntry->key = key; HASH_ADD_PTR(referents, key, referentEntry); } // Add the reference to the referent's list of references LL_PREPEND(referentEntry->references, l); // Register the referent for finalization GC_REGISTER_FINALIZER_NO_ORDER(referent, _finalizeObject, NULL, NULL, NULL); done: rvmUnlockMutex(&referentsLock); } }
void scm_i_set_finalizer (void *obj, scm_t_finalizer_proc proc, void *data) { GC_finalization_proc prev; void *prev_data; GC_REGISTER_FINALIZER_NO_ORDER (obj, proc, data, &prev, &prev_data); }
static void finalizeObject(Env* env, Object* obj) { // TRACEF("finalizeObject: %p (%s)\n", obj, obj->clazz->name); rvmLockMutex(&referentsLock); void* key = (void*) GC_HIDE_POINTER(obj); ReferentEntry* referentEntry; HASH_FIND_PTR(referents, &key, referentEntry); assert(referentEntry != NULL); if (referentEntry->references == NULL) { // The object is not referenced by any type of reference and can never be resurrected. HASH_DEL(referents, referentEntry); rvmUnlockMutex(&referentsLock); return; } Object* softReferences = NULL; Object* weakReferences = NULL; Object* finalizerReferences = NULL; Object* phantomReferences = NULL; Object* clearedReferences = NULL; ReferenceList* refNode; while (referentEntry->references != NULL) { refNode = referentEntry->references; LL_DELETE(referentEntry->references, refNode); Object** list = NULL; Object* reference = refNode->reference; if (rvmIsSubClass(java_lang_ref_SoftReference, reference->clazz)) { list = &softReferences; } else if (rvmIsSubClass(java_lang_ref_WeakReference, reference->clazz)) { list = &weakReferences; } else if (rvmIsSubClass(java_lang_ref_FinalizerReference, reference->clazz)) { list = &finalizerReferences; } else if (rvmIsSubClass(java_lang_ref_PhantomReference, reference->clazz)) { list = &phantomReferences; } enqueuePendingReference(env, reference, list); } assert(referentEntry->references == NULL); clearAndEnqueueReferences(env, &softReferences, &clearedReferences); clearAndEnqueueReferences(env, &weakReferences, &clearedReferences); enqueueFinalizerReferences(env, &finalizerReferences, &clearedReferences); clearAndEnqueueReferences(env, &phantomReferences, &clearedReferences); // Reregister for finalization. If no new references have been added to the list of references for the referent the // next time it gets finalized we know it will never be resurrected. GC_REGISTER_FINALIZER_NO_ORDER(obj, _finalizeObject, NULL, NULL, NULL); rvmUnlockMutex(&referentsLock); if (clearedReferences != NULL) { rvmCallVoidClassMethod(env, java_lang_ref_ReferenceQueue, java_lang_ref_ReferenceQueue_add, clearedReferences); assert(rvmExceptionOccurred(env) == NULL); } }
pthread_cond_t* dfsch_create_finalized_cvar(){ pthread_cond_t* cvar = GC_MALLOC_ATOMIC(sizeof(pthread_cond_t)); #ifdef DFSCH_THREADS_FINALIZE GC_REGISTER_FINALIZER_NO_ORDER(cvar, (GC_finalization_proc)cvar_finalizer, NULL, NULL, NULL); #endif pthread_cond_init(cvar, NULL); return cvar; }
pthread_mutex_t* dfsch_create_finalized_mutex(){ pthread_mutex_t* mutex = GC_MALLOC_ATOMIC(sizeof(pthread_mutex_t)); #ifdef DFSCH_THREADS_FINALIZE GC_REGISTER_FINALIZER_NO_ORDER(mutex, (GC_finalization_proc)mutex_finalizer, NULL, NULL, NULL); #endif pthread_mutex_init(mutex, NULL); return mutex; }
void mono_gc_register_for_finalization (MonoObject *obj, void *user_data) { guint offset = 0; #ifndef GC_DEBUG /* This assertion is not valid when GC_DEBUG is defined */ g_assert (GC_base (obj) == (char*)obj - offset); #endif GC_REGISTER_FINALIZER_NO_ORDER ((char*)obj - offset, user_data, GUINT_TO_POINTER (offset), NULL, NULL); }
void scm_i_add_resuscitator (void *obj, scm_t_finalizer_proc proc, void *data) { struct scm_t_chained_finalizer *chained_data; chained_data = scm_gc_malloc (sizeof (*chained_data), "chained finalizer"); chained_data->resuscitating_p = 1; chained_data->proc = proc; chained_data->data = data; GC_REGISTER_FINALIZER_NO_ORDER (obj, chained_finalizer, chained_data, &chained_data->prev, &chained_data->prev_data); }
void registerCleanupHandler(Env* env, Object* object, CleanupHandler handler) { rvmLockMutex(&referentsLock); CleanupHandlerList* l = rvmAllocateMemory(env, sizeof(CleanupHandlerList)); if (!l) goto done; // OOM thrown l->handler = handler; ReferentEntry* referentEntry = getReferentEntryForObject(env, object); if (!referentEntry) goto done; // Add the handler to the object's list of cleanup handlers LL_PREPEND(referentEntry->cleanupHandlers, l); // Register the referent for finalization GC_REGISTER_FINALIZER_NO_ORDER(object, _finalizeObject, NULL, NULL, NULL); done: rvmUnlockMutex(&referentsLock); }
/* * Some of our objects may point to a different address than the address returned by GC_malloc() * (because of the GetHashCode hack), but we need to pass the real address to register_finalizer. * This also means that in the callback we need to adjust the pointer to get back the real * MonoObject*. * We also need to be consistent in the use of the GC_debug* variants of malloc and register_finalizer, * since that, too, can cause the underlying pointer to be offset. */ static void object_register_finalizer (MonoObject *obj, void (*callback)(void *, void*)) { #if HAVE_BOEHM_GC guint offset = 0; MonoDomain *domain; if (obj == NULL) mono_raise_exception (mono_get_exception_argument_null ("obj")); domain = obj->vtable->domain; #ifndef GC_DEBUG /* This assertion is not valid when GC_DEBUG is defined */ g_assert (GC_base (obj) == (char*)obj - offset); #endif if (mono_domain_is_unloading (domain) && (callback != NULL)) /* * Can't register finalizers in a dying appdomain, since they * could be invoked after the appdomain has been unloaded. */ return; mono_domain_finalizers_lock (domain); if (callback) g_hash_table_insert (domain->finalizable_objects_hash, obj, obj); else g_hash_table_remove (domain->finalizable_objects_hash, obj); mono_domain_finalizers_unlock (domain); GC_REGISTER_FINALIZER_NO_ORDER ((char*)obj - offset, callback, GUINT_TO_POINTER (offset), NULL, NULL); #elif defined(HAVE_SGEN_GC) if (obj == NULL) mono_raise_exception (mono_get_exception_argument_null ("obj")); /* * If we register finalizers for domains that are unloading we might * end up running them while or after the domain is being cleared, so * the objects will not be valid anymore. */ if (!mono_domain_is_unloading (obj->vtable->domain)) mono_gc_register_for_finalization (obj, callback); #endif }
void rvmRegisterReference(Env* env, Object* reference, Object* referent) { if (referent) { // Add 'reference' to the references list for 'referent' in the referents hashtable rvmLockMutex(&referentsLock); ReferenceList* l = rvmAllocateMemory(env, sizeof(ReferenceList)); if (!l) goto done; // OOM thrown l->reference = reference; ReferentEntry* referentEntry = getReferentEntryForObject(env, referent); if (!referentEntry) goto done; // Add the reference to the referent's list of references LL_PREPEND(referentEntry->references, l); // Register the referent for finalization GC_REGISTER_FINALIZER_NO_ORDER(referent, _finalizeObject, NULL, NULL, NULL); done: rvmUnlockMutex(&referentsLock); } }
void Scm_UnregisterFinalizer(ScmObj z) { GC_finalization_proc ofn; void *ocd; GC_REGISTER_FINALIZER_NO_ORDER(z, (GC_finalization_proc)NULL, NULL, &ofn, &ocd); }
/*============================================================= * Finalization. Scheme finalizers are added as NO_ORDER. */ void Scm_RegisterFinalizer(ScmObj z, ScmFinalizerProc finalizer, void *data) { GC_finalization_proc ofn; void *ocd; GC_REGISTER_FINALIZER_NO_ORDER(z, (GC_finalization_proc)finalizer, data, &ofn, &ocd); }
void ILGCRegisterFinalizer(void *block, ILGCFinalizer func, void *data) { /* We use the Java-style finalization algorithm, which ignores cycles in the object structure */ GC_REGISTER_FINALIZER_NO_ORDER(block, func, data, 0, 0); }
void smem_set_filnalizer(SExp s, void (*func)(SExp)) { #ifndef DONT_USE_GC void* ptr = S2PTR(s); GC_REGISTER_FINALIZER_NO_ORDER(ptr, (GC_finalization_proc)func, ptr, NULL, NULL); #endif }