void gsl_data_cache_unref (GslDataCache *dcache) { g_return_if_fail (dcache != NULL); restart: g_return_if_fail (dcache->ref_count > 0); if (dcache->ref_count == 1) /* possible destruction, need global lock */ { g_return_if_fail (dcache->open_count == 0); GSL_SPIN_LOCK (&global_dcache_mutex); GSL_SPIN_LOCK (&dcache->mutex); if (dcache->ref_count != 1) { /* damn, some other thread trapped in, restart */ GSL_SPIN_UNLOCK (&dcache->mutex); GSL_SPIN_UNLOCK (&global_dcache_mutex); goto restart; } dcache->ref_count = 0; global_dcache_list = sfi_ring_remove (global_dcache_list, dcache); GSL_SPIN_UNLOCK (&dcache->mutex); global_dcache_count--; global_dcache_n_aged_nodes -= dcache->n_nodes; GSL_SPIN_UNLOCK (&global_dcache_mutex); dcache_free (dcache); } else { GSL_SPIN_LOCK (&dcache->mutex); if (dcache->ref_count < 2) { /* damn, some other thread trapped in, restart */ GSL_SPIN_UNLOCK (&dcache->mutex); goto restart; } dcache->ref_count--; GSL_SPIN_UNLOCK (&dcache->mutex); } }
static void target_dcache_cleanup (struct address_space *aspace, void *arg) { dcache_free ((DCACHE *) arg); }