bool ObjectMemory::inflate_lock_count_overflow(STATE, ObjectHeader* obj, int count) { utilities::thread::SpinLock::LockGuard guard(inflation_lock_); HeaderWord orig = obj->header; if(orig.f.inflated) { return false; } InflatedHeader* header = inflated_headers_->allocate(obj); header->update(state, orig); header->initialize_mutex(state->vm()->thread_id(), count); while(!obj->set_inflated_header(state, header, orig)) { orig = obj->header; if(orig.f.inflated) { return false; } header->update(state, orig); header->initialize_mutex(state->vm()->thread_id(), count); } return true; }
bool ObjectMemory::inflate_lock_count_overflow(STATE, ObjectHeader* obj, int count) { utilities::thread::SpinLock::LockGuard guard(inflation_lock_); HeaderWord orig = obj->header; if(orig.f.meaning == eAuxWordInflated) { return false; } uint32_t ih_header = 0; InflatedHeader* ih = inflated_headers_->allocate(state, obj, &ih_header); ih->update(state, orig); ih->initialize_mutex(state->vm()->thread_id(), count); ih->mark(this, mark_); while(!obj->set_inflated_header(state, ih_header, orig)) { orig = obj->header; if(orig.f.meaning == eAuxWordInflated) { return false; } ih->update(state, orig); ih->initialize_mutex(state->vm()->thread_id(), count); } return true; }
bool ObjectMemory::inflate_lock_count_overflow(STATE, ObjectHeader* obj, int count) { utilities::thread::SpinLock::LockGuard guard(inflation_lock_); // Inflation always happens with the ObjectMemory lock held, so we don't // need to worry about another thread concurrently inflating it. // // But we do need to check that it's not already inflated. if(obj->inflated_header_p()) return false; InflatedHeader* ih = inflated_headers_->allocate(obj); if(!obj->set_inflated_header(state, ih)) { if(obj->inflated_header_p()) return false; // Now things are really in a weird state, just abort. rubinius::bug("Massive header state confusion detected. Call a doctor."); } ih->initialize_mutex(state->vm()->thread_id(), count); return true; }
bool ObjectMemory::inflate_and_lock(STATE, ObjectHeader* obj) { utilities::thread::SpinLock::LockGuard guard(inflation_lock_); InflatedHeader* ih = 0; uint32_t ih_index = 0; int initial_count = 0; HeaderWord orig = obj->header; switch(orig.f.meaning) { case eAuxWordEmpty: // ERROR, we can not be here because it's empty. This is only to // be called when the header is already in use. return false; case eAuxWordObjID: // We could be have made a header before trying again, so // keep using the original one. ih = inflated_headers_->allocate(state, obj, &ih_index); ih->set_object_id(orig.f.aux_word); break; case eAuxWordLock: // We have to locking the object to inflate it, thats the law. if(orig.f.aux_word >> cAuxLockTIDShift != state->vm()->thread_id()) { return false; } ih = inflated_headers_->allocate(state, obj, &ih_index); initial_count = orig.f.aux_word & cAuxLockRecCountMask; break; case eAuxWordHandle: // Handle in use so inflate and update handle ih = inflated_headers_->allocate(state, obj, &ih_index); ih->set_handle(state, obj->handle(state)); break; case eAuxWordInflated: // Already inflated. ERROR, let the caller sort it out. if(cDebugThreading) { std::cerr << "[LOCK " << state->vm()->thread_id() << " asked to inflated already inflated lock]" << std::endl; } return false; } ih->initialize_mutex(state->vm()->thread_id(), initial_count); ih->mark(this, mark_); while(!obj->set_inflated_header(state, ih_index, orig)) { // The header can't have been inflated by another thread, the // inflation process holds the OM lock. // // So some other bits must have changed, so lets just spin and // keep trying to update it. // Sanity check that the meaning is still the same, if not, then // something is really wrong. if(orig.f.meaning != obj->header.f.meaning) { if(cDebugThreading) { std::cerr << "[LOCK object header consistence error detected.]" << std::endl; } return false; } orig = obj->header; if(orig.f.meaning == eAuxWordInflated) { return false; } } return true; }