Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Converted GlobControlLock to a read-write lock. #3014

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

maxsharabayko
Copy link
Collaborator

CUDTUnited::m_GlobControlLock is now a read-write lock (srt::sync::SharedMutex).

CUDTUnited::m_GlobControlLock guards all member containers of the CUDTUnited.

  • CUDTUnited::m_Groups - add/remove under exclusive lock, access - under non-exclusive lock.

  • CUDTUnited::m_Sockets - add/remove under exclusive lock, access - under non-exclusive lock.

  • CUDTUnited::m_PeerRec – record sockets from peers to avoid repeated connection request. Add/remove under exclusive lock, access - under non-exclusive lock.

  • CUDTUnited::m_ClosedSockets - add/remove under exclusive lock, access - under non-exclusive lock.

  • CUDTUnited::m_mMultiplexer - - add/remove and access under exclusive lock. ❗

Addresses #2393.

@maxsharabayko maxsharabayko added Type: Maintenance Work required to maintain or clean up the code [core] Area: Changes in SRT library core labels Aug 21, 2024
@maxsharabayko maxsharabayko added this to the v1.6.0 milestone Aug 21, 2024
@@ -191,7 +191,6 @@ srt::CUDTUnited::CUDTUnited()
// be a problem in general.
setupMutex(m_GCStopLock, "GCStop");
setupCond(m_GCStopCond, "GCStop");
setupMutex(m_GlobControlLock, "GlobControl");
setupMutex(m_IDLock, "ID");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to decide something about these calls. With the current locking implementation these are not needed and have been left here to allow implementation of the mutex tracker, which is still hanging around in one of the PRs. So, either add an appropriate empty function with that name to cover the stub, or we'll need to remove them all.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was a problem with an initialization of a conditional variable. There is a difference in POSIX on how you initialize the one in a global / static scope, and the one in runtime. That's what setupCond do on POSIX builds. And there was a crash if that initialization was done in the constructor.
setupMutex is indeed not needed except for the mutex tracker.

void Condition::init()
{
    pthread_condattr_t* attr = NULL;
#if SRT_SYNC_CLOCK == SRT_SYNC_CLOCK_GETTIME_MONOTONIC
    pthread_condattr_t  CondAttribs;
    pthread_condattr_init(&CondAttribs);
    pthread_condattr_setclock(&CondAttribs, CLOCK_MONOTONIC);
    attr = &CondAttribs;
#endif
    const int res = pthread_cond_init(&m_cv, attr);
    if (res != 0)
        throw std::runtime_error("pthread_cond_init monotonic failed");
}

s->core().closeInternal();
enterCS(m_GlobControlLock);
HLOGC(smlog.Debug, log << "GC/removeSocket: DELETING SOCKET @" << u);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was here to fix the problem of locking m_ConnectionLock after m_GlobControlLock. Why is that no longer necessary?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GlobControl "resource" is now held in a shared manner protecting containers from modification, but there is no mutex being locked. Hence no need for this unlock-lock trick.

@@ -407,7 +407,12 @@ class CUDTUnited
groups_t m_Groups;
#endif

sync::Mutex m_GlobControlLock; // used to synchronize UDT API
/// Guards all member containers of `CUDTUnited`. Protect UDT API from data races.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UDT???

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Guards all member containers of `CUDTUnited`. Protect UDT API from data races.
/// Guards all member containers of `CUDTUnited`. Protect SRT API from data races.

@@ -407,7 +407,12 @@ class CUDTUnited
groups_t m_Groups;
#endif

sync::Mutex m_GlobControlLock; // used to synchronize UDT API
/// Guards all member containers of `CUDTUnited`. Protect UDT API from data races.
/// Non-exclusive lock prohibits changes of containers (insert/remove), but allows modifications
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Shared lock" would be not unconfusing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Non-exclusive lock prohibits changes of containers (insert/remove), but allows modifications
/// A shared (non-exclusive) lock prohibits changes of containers (insert/remove), but allows modifications

CUDTGroup* g = m_parent->m_GroupOf;
if (g)
{
// TODO: Lock this group `g`??
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's likely a good idea. And also the shared lock suffices for that, while acquireSocketsGroup could be used here (that is, the constructor overload of GroupKeeper that uses this call).

@@ -8385,7 +8388,7 @@ void srt::CUDT::updateSndLossListOnACK(int32_t ackdata_seqno)
{
// m_RecvAckLock is ordered AFTER m_GlobControlLock, so this can only
// be done now that m_RecvAckLock is unlocked.
ScopedLock glock (uglobal().m_GlobControlLock);
SharedLock glock (uglobal().m_GlobControlLock);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this place you can consider using GroupKeeper instead of SharedLock on m_GlobControlLock - if possible.

Copy link
Collaborator

@ethouris ethouris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One comment describes a serious problem here, please fix. Others just to consider.

@@ -2141,7 +2141,7 @@ vector<CUDTSocket*> CUDTGroup::recv_WaitForReadReady(const vector<CUDTSocket*>&
}
}

leaveCS(CUDT::uglobal().m_GlobControlLock);
CUDT::uglobal().m_GlobControlLock.lock_shared();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be unlock_shared()?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agh, right.

Suggested change
CUDT::uglobal().m_GlobControlLock.lock_shared();
CUDT::uglobal().m_GlobControlLock.unlock_shared();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[core] Area: Changes in SRT library core Type: Maintenance Work required to maintain or clean up the code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants