void gd_ht_kill(hash_table_mname *table, boolean_t contents) /* wipe out the hash table corresponding to a gld */ { ht_ent_mname *tabent, *topent; gvnh_reg_t *gvnh_reg; gv_namehead *gvt; if (contents) { for (tabent = table->base, topent = tabent + table->size; tabent < topent; tabent++) { if (HTENT_VALID_MNAME(tabent, gvnh_reg_t, gvnh_reg)) { gvt = gvnh_reg->gvt; gvt->regcnt--; if (!gvt->regcnt) targ_free(gvt); free(gvnh_reg); } } } free((char *)table->base); /* We don't do a free(table) in this generic routine because it is called both by GT.M and GT.CM * and GT.CM retains the table for reuse while GT.M doesn't. GT.M fgncal_rundown() takes care of * this by freeing it up explicitly (after a call to ht_kill) in gd_rundown() [dpgbldir.c] */ return; }
/* Delete all aliases and the data they point to. * * Two things need to happen: * 1) Scan the hash table for aliased base variables and remove them. * 2) Scan ALL subscripted vars for containers, delete the data they point to maintaining * proper maintenance of reference counts and unmark the container making it a normal value. * * Since an alias with two references ceases being an alias if a reference is killed, we * cannot just do a simple scan and delete references. We will leave "klingons" who used to * be aliases but now are not. So we do this in a 3 step procedure: * 1) Identify all overt aliases in the hash table. * 2) For the entries that are not aliases but which contain alias containers, scan those * arrays for containers, remove the container attribute and do the necessary refcnt * cleanup. When all containers have been removed (including step 3), any remaining * orphaned data will be recovered by the next LVGC. * 3) Go through the list of HTEs recorded in step one and kill their hash table reference. */ void op_killaliasall(void) { ht_ent_mname *tabent, *tabent_top; lv_val *lvp, *lvp_top, *lvrefp; symval *symv; int lowest_symvlvl; ht_ent_mname **htearraycur = NULL, **htearray = NULL, **htearraytop; SET_ACTIVE_LV(NULL, TRUE, actlv_op_killaliasall); /* If we get here, subscript set was successful. * Clear active_lv to avoid later cleanup issues */ lowest_symvlvl = MAXPOSINT4; /* First pass through hash table we record HTEs that have > 1 trefcnt. We will delete these in a later * loop but don't want to delete any until all are found. */ for (tabent = curr_symval->h_symtab.base, tabent_top = curr_symval->h_symtab.top; tabent < tabent_top; tabent++) { if (HTENT_VALID_MNAME(tabent, lv_val, lvp) && lvp && (1 < lvp->stats.trefcnt)) { /* Verify room in the table, expand if necessary */ assert(LV_IS_BASE_VAR(lvp)); ADD_TO_STPARRAY(tabent, htearray, htearraycur, htearraytop, ht_ent_mname); /* Need to find the lowest level symval that is affected by this kill * so we can mark all necessary * symvals as having had alias activity. */ lvp = (lv_val *)tabent->value; symv = LV_GET_SYMVAL(lvp); if (lowest_symvlvl > symv->symvlvl) lowest_symvlvl = symv->symvlvl; } } /* This next, less scenic trip through the hash table entries we scan any arrays we * find for containers that must be dealt with. We couldn't deal with these until all * the "blatant" aliases were identified. */ for (tabent = curr_symval->h_symtab.base, tabent_top = curr_symval->h_symtab.top; tabent < tabent_top; tabent++) { if (HTENT_VALID_MNAME(tabent, lv_val, lvp) && lvp && (1 == lvp->stats.trefcnt)) { /* Var was not an alias but now need to check if var has any containers in it * that likewise need to be processed (and de-container-ized). */ assert(LV_IS_BASE_VAR(lvp)); KILL_CNTNRS_IN_TREE(lvp); /* Note macro has LV_GET_CHILD() check in it */ } } /* Now we can go through the hash table entries we identified in the first step and delete them. */ for (htearraytop = htearraycur, htearraycur = htearray; htearraycur < htearraytop; ++htearraycur) { assert(htearraycur); tabent = *htearraycur; lvp = (lv_val *)tabent->value; assert(lvp); assert(LV_IS_BASE_VAR(lvp)); assert(0 < lvp->stats.trefcnt); /* Clone var if necessary */ if (dollar_tlevel && (NULL != lvp->tp_var) && !lvp->tp_var->var_cloned) TP_VAR_CLONE(lvp); /* Decrement reference count and cleanup if necessary */ DECR_BASE_REF(tabent, lvp, TRUE); } /* Now mark all symvals from the earliest affected by our command to the current as having had alias activity */ MARK_ALIAS_ACTIVE(lowest_symvlvl); }