word intern_indirect(indirect_table *tab, word val, int create ARG_LD) { Word idata = addressIndirect(val); /* points at header */ size_t isize = wsizeofInd(*idata); /* include header */ unsigned int key = MurmurHashAligned2(idata+1, isize*sizeof(word), MURMUR_SEED); indirect_buckets *buckets; for(;;) { buckets = acquire_itable_buckets(tab); unsigned int ki = key & (buckets->size-1); indirect *head = buckets->buckets[ki]; indirect *h; acquire_itable_bucket(&buckets->buckets[ki]); for(h=buckets->buckets[ki]; h; h = h->next) { unsigned int ref = h->references; if ( INDIRECT_IS_VALID(ref) && idata[0] == h->header && memcmp(idata+1, h->data, isize*sizeof(word)) == 0 ) { if ( bump_ref(h, ref) ) { release_itable_buckets(); return h->handle; } } } if ( TIGHT(buckets, tab) ) { simpleMutexLock(&tab->mutex); rehash_indirect_table(tab); simpleMutexUnlock(&tab->mutex); } if ( buckets != tab->table || head != buckets->buckets[ki] ) continue; /* try again */ if ( create ) { indirect *h = reserve_indirect(tab, val PASS_LD); h->next = buckets->buckets[ki]; if ( !COMPARE_AND_SWAP(&buckets->buckets[ki], head, h) || buckets != tab->table ) { PL_free(h->data); h->references = 0; continue; /* try again */ } h->references = 1 | INDIRECT_VALID_REFERENCE | INDIRECT_RESERVED_REFERENCE; ATOMIC_INC(&tab->count); release_itable_buckets(); return h->handle; } else { release_itable_buckets(); return 0; } } }
bool AuthorizationSet::Reinitialize(const keymaster_key_param_t* elems, const size_t count) { FreeData(); if (!reserve_elems(count)) return false; if (!reserve_indirect(ComputeIndirectDataSize(elems, count))) return false; memcpy(elems_, elems, sizeof(keymaster_key_param_t) * count); elems_size_ = count; CopyIndirectData(); error_ = OK; return true; }
bool AuthorizationSet::push_back(const AuthorizationSet& set) { if (is_valid() != OK) return false; if (!reserve_elems(elems_size_ + set.elems_size_)) return false; if (!reserve_indirect(indirect_data_size_ + set.indirect_data_size_)) return false; for (size_t i = 0; i < set.size(); ++i) if (!push_back(set[i])) return false; return true; }
bool AuthorizationSet::push_back(keymaster_key_param_t elem) { if (is_valid() != OK) return false; if (elems_size_ >= elems_capacity_) if (!reserve_elems(elems_capacity_ ? elems_capacity_ * 2 : STARTING_ELEMS_CAPACITY)) return false; if (is_blob_tag(elem.tag)) { if (indirect_data_capacity_ - indirect_data_size_ < elem.blob.data_length) if (!reserve_indirect(2 * (indirect_data_capacity_ + elem.blob.data_length))) return false; memcpy(indirect_data_ + indirect_data_size_, elem.blob.data, elem.blob.data_length); elem.blob.data = indirect_data_ + indirect_data_size_; indirect_data_size_ += elem.blob.data_length; } elems_[elems_size_++] = elem; return true; }