Skip to content

Commit

Permalink
SL-20743 Use LLMutex in LLImageBase for internal data thread-safety
Browse files Browse the repository at this point in the history
  • Loading branch information
LLGuru committed Dec 21, 2023
1 parent e104f7c commit 74c8b02
Show file tree
Hide file tree
Showing 53 changed files with 631 additions and 137 deletions.
2 changes: 1 addition & 1 deletion indra/llappearance/llavatarappearance.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class LLAvatarAppearance : public LLCharacter
//--------------------------------------------------------------------
public:
void addMaskedMorph(LLAvatarAppearanceDefines::EBakedTextureIndex index, LLVisualParam* morph_target, BOOL invert, std::string layer);
virtual void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0;
virtual void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components, LLAvatarAppearanceDefines::EBakedTextureIndex index = LLAvatarAppearanceDefines::BAKED_NUM_INDICES) = 0;

/** Rendering
** **
Expand Down
4 changes: 2 additions & 2 deletions indra/llappearance/llpolymorph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex )
//-----------------------------------------------------------------------------
// applyMask()
//-----------------------------------------------------------------------------
void LLPolyMorphTarget::applyMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert)
void LLPolyMorphTarget::applyMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert)
{
LLVector4a *clothing_weights = getInfo()->mIsClothingMorph ? mMesh->getWritableClothingWeights() : NULL;

Expand Down Expand Up @@ -780,7 +780,7 @@ LLPolyVertexMask::~LLPolyVertexMask()
//-----------------------------------------------------------------------------
// generateMask()
//-----------------------------------------------------------------------------
void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights)
void LLPolyVertexMask::generateMask(const U8 *maskTextureData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights)
{
// RN debug output that uses Image Debugger (http://www.cs.unc.edu/~baxter/projects/imdebug/)
// BOOL debugImg = FALSE;
Expand Down
4 changes: 2 additions & 2 deletions indra/llappearance/llpolymorph.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class LLPolyVertexMask
LLPolyVertexMask(const LLPolyVertexMask& pOther);
~LLPolyVertexMask();

void generateMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights);
void generateMask(const U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert, LLVector4a *clothing_weights);
F32* getMorphMaskWeights();


Expand Down Expand Up @@ -170,7 +170,7 @@ class alignas(16) LLPolyMorphTarget : public LLViewerVisualParam
/*virtual*/ const LLVector4a* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh);
/*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh);

void applyMask(U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert);
void applyMask(const U8 *maskData, S32 width, S32 height, S32 num_components, BOOL invert);
void addPendingMorphMask() { mNumMorphMasksPending++; }

void applyVolumeChanges(F32 delta_weight); // SL-315 - for resetSkeleton()
Expand Down
2 changes: 1 addition & 1 deletion indra/llappearance/lltexlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height,
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}

void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components)
void LLTexLayerSet::applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components)
{
mAvatarAppearance->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex);
}
Expand Down
2 changes: 1 addition & 1 deletion indra/llappearance/lltexlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class LLTexLayerSet
void renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false);

BOOL isBodyRegion(const std::string& region) const;
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
void applyMorphMask(const U8* tex_data, S32 width, S32 height, S32 num_components);
BOOL isMorphValid() const;
virtual void requestUpdate() = 0;
void invalidateMorphMasks();
Expand Down
2 changes: 1 addition & 1 deletion indra/llcommon/llapr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb
}

//static
S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
{
LL_PROFILE_ZONE_SCOPED;
apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
Expand Down
2 changes: 1 addition & 1 deletion indra/llcommon/llapr.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable

// Returns bytes read/written, 0 if read/write fails:
static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);
static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
static S32 writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
//*******************************************************************************************************************************
};

Expand Down
186 changes: 178 additions & 8 deletions indra/llcommon/llmutex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,20 @@
#include "llthread.h"
#include "lltimer.h"

//============================================================================

//---------------------------------------------------------------------
//
// LLMutex
//
LLMutex::LLMutex() :
mCount(0)
{
}


LLMutex::~LLMutex()
{
}


void LLMutex::lock()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
Expand Down Expand Up @@ -112,7 +113,7 @@ LLThread::id_t LLMutex::lockingThread() const
bool LLMutex::trylock()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
if(isSelfLocked())
if (isSelfLocked())
{ //redundant lock
mCount++;
return true;
Expand All @@ -135,19 +136,185 @@ bool LLMutex::trylock()
return true;
}

//============================================================================

//---------------------------------------------------------------------
//
// LLSharedMutex
//
LLSharedMutex::LLSharedMutex()
: mLockingThreads(2) // Reserve 2 slots in the map hash table
, mIsShared(false)
{
}

bool LLSharedMutex::isLocked() const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
std::lock_guard<std::mutex> lock(mLockMutex);

return !mLockingThreads.empty();
}

bool LLSharedMutex::isThreadLocked() const
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);

const_iterator it = mLockingThreads.find(current_thread);
return it != mLockingThreads.end();
}

void LLSharedMutex::lockShared()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();

mLockMutex.lock();
iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
it->second++;
}
else
{
// Acquire the mutex immediately if the mutex is not locked exclusively
// or enter a locking state if the mutex is already locked exclusively
mLockMutex.unlock();
mSharedMutex.lock_shared();
mLockMutex.lock();
// Continue after acquiring the mutex
mLockingThreads.emplace(std::make_pair(current_thread, 1));
mIsShared = true;
}
mLockMutex.unlock();
}

void LLSharedMutex::lockExclusive()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();

mLockMutex.lock();
if (mLockingThreads.size() == 1 && mLockingThreads.begin()->first == current_thread)
{
mLockingThreads.begin()->second++;
}
else
{
// Acquire the mutex immediately if mLockingThreads is empty
// or enter a locking state if mLockingThreads is not empty
mLockMutex.unlock();
mSharedMutex.lock();
mLockMutex.lock();
// Continue after acquiring the mutex (and possible quitting the locking state)
mLockingThreads.emplace(std::make_pair(current_thread, 1));
mIsShared = false;
}
mLockMutex.unlock();
}

bool LLSharedMutex::trylockShared()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);

iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
it->second++;
}
else
{
if (!mSharedMutex.try_lock_shared())
return false;

mLockingThreads.emplace(std::make_pair(current_thread, 1));
mIsShared = true;
}

return true;
}

bool LLSharedMutex::trylockExclusive()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);

if (mLockingThreads.size() == 1 && mLockingThreads.begin()->first == current_thread)
{
mLockingThreads.begin()->second++;
}
else
{
if (!mSharedMutex.try_lock())
return false;

mLockingThreads.emplace(std::make_pair(current_thread, 1));
mIsShared = false;
}

return true;
}

void LLSharedMutex::unlockShared()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);

iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
if (it->second > 1)
{
it->second--;
}
else
{
mLockingThreads.erase(it);
mSharedMutex.unlock_shared();
}
}
}

void LLSharedMutex::unlockExclusive()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
LLThread::id_t current_thread = LLThread::currentID();
std::lock_guard<std::mutex> lock(mLockMutex);

iterator it = mLockingThreads.find(current_thread);
if (it != mLockingThreads.end())
{
if (it->second > 1)
{
it->second--;
}
else
{
mLockingThreads.erase(it);
mSharedMutex.unlock();
}
}
}


//---------------------------------------------------------------------
//
// LLCondition
//
LLCondition::LLCondition() :
LLMutex()
{
}


LLCondition::~LLCondition()
{
}


void LLCondition::wait()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD
Expand All @@ -168,7 +335,10 @@ void LLCondition::broadcast()
}



//---------------------------------------------------------------------
//
// LLMutexTrylock
//
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex)
: mMutex(mutex),
mLocked(false)
Expand Down
Loading

0 comments on commit 74c8b02

Please sign in to comment.