/* Symbol tables storing the FROM symbols of arcs do not necessarily have distinct address ranges. For example, somebody might request -k /_mcount to suppress any arcs into _mcount, while at the same time requesting -k a/b. Fortunately, those symbol tables don't get very big (the user has to type them!), so a linear search is probably tolerable. */ bfd_boolean sym_id_arc_is_present (Sym_Table *sym_tab, Sym *from, Sym *to) { Sym *sym; for (sym = sym_tab->base; sym < sym_tab->limit; ++sym) { if (from->addr >= sym->addr && from->addr <= sym->end_addr && arc_lookup (sym, to)) return TRUE; } return FALSE; }
// the returned object is retained, the caller must call arc_release_resource(obj) to release it arc_resource_t arc_lookup(arc_t *cache, const void *key, size_t len, void **valuep, int async) { // NOTE: this is an atomic operation ensured by the hashtable implementation, // we don't do any real copy in our callback but we just increase the refcount // of the object (if found) arc_object_t *obj = ht_get_deep_copy(cache->hash, (void *)key, len, NULL, retain_obj_cb, cache); if (obj) { if (!ATOMIC_READ(cache->mode) || UNLIKELY(ATOMIC_READ(obj->state) != &cache->mfu)) { if (UNLIKELY(arc_move(cache, obj, &cache->mfu) == -1)) { fprintf(stderr, "Can't move the object into the cache\n"); return NULL; } arc_balance(cache); } if (valuep) *valuep = obj->ptr; return obj; } obj = arc_object_create(cache, key, len); if (!obj) return NULL; // let our cache user initialize the underlying object cache->ops->init(key, len, async, (arc_resource_t)obj, obj->ptr, cache->ops->priv); obj->async = async; retain_ref(cache->refcnt, obj->node); // NOTE: atomicity here is ensured by the hashtable implementation int rc = ht_set_if_not_exists(cache->hash, (void *)key, len, obj, sizeof(arc_object_t)); switch(rc) { case -1: fprintf(stderr, "Can't set the new value in the internal hashtable\n"); release_ref(cache->refcnt, obj->node); break; case 1: // the object has been created in the meanwhile release_ref(cache->refcnt, obj->node); // XXX - yes, we have to release it twice release_ref(cache->refcnt, obj->node); return arc_lookup(cache, key, len, valuep, async); case 0: /* New objects are always moved to the MRU list. */ rc = arc_move(cache, obj, &cache->mru); if (rc >= 0) { arc_balance(cache); *valuep = obj->ptr; return obj; } break; default: fprintf(stderr, "Unknown return code from ht_set_if_not_exists() : %d\n", rc); release_ref(cache->refcnt, obj->node); break; } release_ref(cache->refcnt, obj->node); return NULL; }