Skip to content

Commit

Permalink
Use linked-list & spinlock to avoid non-safe functions. Closes baldur…
Browse files Browse the repository at this point in the history
…k#1102

* Most functions - including pthreads, malloc, free, etc are not safe to use in
  signal handlers. So we use a simple spin-lock and manual linked-list to manage
  our list of PIDs to wait on.
  • Loading branch information
baldurk committed Sep 17, 2018
1 parent 834bbe6 commit d8294d8
Show file tree
Hide file tree
Showing 9 changed files with 350 additions and 21 deletions.
1 change: 1 addition & 0 deletions renderdoc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ set(sources
common/threading.h
common/timing.h
common/wrapped_pool.h
common/threading_tests.cpp
core/core.cpp
core/image_viewer.cpp
core/core.h
Expand Down
27 changes: 27 additions & 0 deletions renderdoc/common/threading.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,36 @@ class ScopedWriteLock
private:
RWLock *m_RW;
};

class SpinLock
{
public:
void Lock()
{
while(!Trylock())
{
// spin!
}
}
bool Trylock() { return Atomic::CmpExch32(&val, 0, 1) == 0; }
void Unlock() { Atomic::CmpExch32(&val, 1, 0); }
private:
volatile int32_t val = 0;
};

class ScopedSpinLock
{
public:
ScopedSpinLock(SpinLock &spin) : m_Spin(&spin) { m_Spin->Lock(); }
~ScopedSpinLock() { m_Spin->Unlock(); }
private:
SpinLock *m_Spin;
};
};

#define SCOPED_LOCK(cs) Threading::ScopedLock CONCAT(scopedlock, __LINE__)(cs);

#define SCOPED_READLOCK(rw) Threading::ScopedReadLock CONCAT(scopedlock, __LINE__)(rw);
#define SCOPED_WRITELOCK(rw) Threading::ScopedWriteLock CONCAT(scopedlock, __LINE__)(rw);

#define SCOPED_SPINLOCK(cs) Threading::SpinLock CONCAT(scopedlock, __LINE__)(cs);
74 changes: 74 additions & 0 deletions renderdoc/common/threading_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2017-2018 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/

#include "common/threading.h"
#include "os/os_specific.h"

#if ENABLED(ENABLE_UNIT_TESTS)

#include "3rdparty/catch/catch.hpp"

static int value = 0;

TEST_CASE("Test spin lock", "[threading]")
{
int finalValue = 0;

std::vector<Threading::ThreadHandle> threads;
std::vector<int> threadcount;

threads.resize(8);
threadcount.resize(8);

Threading::SpinLock lock;

for(int i = 0; i < 8; i++)
{
threadcount[i] = (rand() & 0xff) << 4;

finalValue += threadcount[i];
}

for(int i = 0; i < 8; i++)
{
threads[i] = Threading::CreateThread([&lock, &threadcount, i]() {
for(int c = 0; c < threadcount[i]; c++)
{
lock.Lock();
value++;
lock.Unlock();
}
});
}

for(Threading::ThreadHandle t : threads)
{
Threading::JoinThread(t);
Threading::CloseThread(t);
}

CHECK(finalValue == value);
}

#endif // ENABLED(ENABLE_UNIT_TESTS)
2 changes: 2 additions & 0 deletions renderdoc/core/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,8 @@ RenderDoc::~RenderDoc()
m_RemoteThread = 0;
}

Process::Shutdown();

Network::Shutdown();

Threading::Shutdown();
Expand Down
2 changes: 2 additions & 0 deletions renderdoc/os/os_specific.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ ExecuteResult LaunchAndInjectIntoProcess(const char *app, const char *workingDir
void *LoadModule(const char *module);
void *GetFunctionAddress(void *module, const char *function);
uint32_t GetCurrentPID();

void Shutdown();
};

namespace Timing
Expand Down
Loading

0 comments on commit d8294d8

Please sign in to comment.