bool runtime_addfinalizer(void *p, FuncVal *f, const struct __go_func_type *ft) { Fintab *tab; byte *base; if(debug) { if(!runtime_mlookup(p, &base, nil, nil) || p != base) runtime_throw("addfinalizer on invalid pointer"); } tab = TAB(p); runtime_lock(tab); if(f == nil) { lookfintab(tab, p, true, nil); runtime_unlock(tab); return true; } if(lookfintab(tab, p, false, nil)) { runtime_unlock(tab); return false; } if(tab->nkey >= tab->max/2+tab->max/4) { // keep table at most 3/4 full: // allocate new table and rehash. resizefintab(tab); } addfintab(tab, p, f, ft); runtime_setblockspecial(p, true); runtime_unlock(tab); return true; }
bool runtime·addfinalizer(void *p, void (*f)(void*), int32 nret) { Fintab *tab; byte *base; if(debug) { if(!runtime·mlookup(p, &base, nil, nil) || p != base) runtime·throw("addfinalizer on invalid pointer"); } tab = TAB(p); runtime·lock(tab); if(f == nil) { lookfintab(tab, p, true, nil); runtime·unlock(tab); return true; } if(lookfintab(tab, p, false, nil)) { runtime·unlock(tab); return false; } if(tab->nkey >= tab->max/2+tab->max/4) { // keep table at most 3/4 full: // allocate new table and rehash. resizefintab(tab); } addfintab(tab, p, f, nret); runtime·setblockspecial(p, true); runtime·unlock(tab); return true; }
bool runtime_addfinalizer(void *p, void (*f)(void*), const struct __go_func_type *ft) { Fintab *tab; byte *base; bool ret = false; if(debug) { if(!runtime_mlookup(p, &base, nil, nil) || p != base) runtime_throw("addfinalizer on invalid pointer"); } if(!__sync_bool_compare_and_swap(&m->holds_finlock, 0, 1)) runtime_throw("finalizer deadlock"); tab = TAB(p); runtime_lock(tab); if(f == nil) { if(lookfintab(tab, p, true, nil)) runtime_setblockspecial(p, false); ret = true; goto unlock; } if(lookfintab(tab, p, false, nil)) { ret = false; goto unlock; } if(tab->nkey >= tab->max/2+tab->max/4) { // keep table at most 3/4 full: // allocate new table and rehash. resizefintab(tab); } addfintab(tab, p, f, ft); runtime_setblockspecial(p, true); ret = true; unlock: runtime_unlock(tab); __sync_bool_compare_and_swap(&m->holds_finlock, 1, 0); if(__sync_bool_compare_and_swap(&m->gcing_for_finlock, 1, 0)) { __go_run_goroutine_gc(200); } return ret; }