From b82cc00be9f34937b37a70841447242114aac277 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 11 Apr 2014 13:26:46 +0000 Subject: [PATCH] Experiment with mlock and barriers --- source/backend/plugin/BridgePlugin.cpp | 3 +++ source/utils/CarlaMathUtils.hpp | 16 ++++++++++++ source/utils/CarlaRingBuffer.hpp | 34 ++++++++++++++++++++++++++ source/utils/Lv2AtomQueue.hpp | 11 ++++++--- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/source/backend/plugin/BridgePlugin.cpp b/source/backend/plugin/BridgePlugin.cpp index 8fb3cc989..c5ce60ff2 100644 --- a/source/backend/plugin/BridgePlugin.cpp +++ b/source/backend/plugin/BridgePlugin.cpp @@ -1896,6 +1896,9 @@ public: carla_stdout(" sizeof(BridgeShmControl): " P_SIZE, sizeof(BridgeShmControl)); carla_stdout(" sizeof(BridgeTimeInfo): " P_SIZE, sizeof(BridgeTimeInfo)); + // lock memory + fShmControl.lockMemory(); + // initial values fShmControl.writeOpcode(kPluginBridgeOpcodeNull); fShmControl.writeInt(static_cast(sizeof(BridgeShmControl))); diff --git a/source/utils/CarlaMathUtils.hpp b/source/utils/CarlaMathUtils.hpp index f691ad98b..ca8c90ac9 100644 --- a/source/utils/CarlaMathUtils.hpp +++ b/source/utils/CarlaMathUtils.hpp @@ -79,6 +79,22 @@ const T& carla_fixValue(const T& min, const T& max, const T& value) noexcept return value; } +/* + * Get next power of 2. + */ +static inline +uint32_t carla_nextPowerOf2(uint32_t size) +{ + // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + --size; + size |= size >> 1; + size |= size >> 2; + size |= size >> 4; + size |= size >> 8; + size |= size >> 16; + return ++size; +} + // ----------------------------------------------------------------------- // math functions (extended) diff --git a/source/utils/CarlaRingBuffer.hpp b/source/utils/CarlaRingBuffer.hpp index 5c3eff6e6..47142506b 100644 --- a/source/utils/CarlaRingBuffer.hpp +++ b/source/utils/CarlaRingBuffer.hpp @@ -20,6 +20,13 @@ #include "CarlaUtils.hpp" +#ifndef CARLA_OS_WIN +# include +# ifdef CARLA_OS_MAC +# include +# endif +#endif + // ----------------------------------------------------------------------- // RingBuffer structs @@ -97,6 +104,7 @@ public: if (fBuffer->invalidateCommit) { + memoryBarrier(); fBuffer->written = fBuffer->head; fBuffer->invalidateCommit = false; return false; @@ -115,6 +123,19 @@ public: return (fBuffer->head != fBuffer->tail); } + void lockMemory() const noexcept + { + CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,); + +#ifdef CARLA_OS_WIN + ::VirtualLock(fBuffer, sizeof(BufferStruct)); + ::VirtualLock(fBuffer->buf, fBuffer->size); +#else + ::mlock(fBuffer, sizeof(BufferStruct)); + ::mlock(fBuffer->buf, fBuffer->size); +#endif + } + // ------------------------------------------------------------------- char readChar() noexcept @@ -219,6 +240,7 @@ protected: std::memcpy(charbuf, fBuffer->buf + tail, size); } + memoryBarrier(); fBuffer->tail = static_cast(readto); } @@ -261,12 +283,24 @@ protected: std::memcpy(fBuffer->buf + wrtn, charbuf, size); } + memoryBarrier(); fBuffer->written = static_cast(writeto); } private: BufferStruct* fBuffer; + static void memoryBarrier() + { +#if defined(CARLA_OS_MAC) + ::OSMemoryBarrier(); +#elif defined(CARLA_OS_WIN) + ::MemoryBarrier(); +#elif (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) + ::__sync_synchronize(); +#endif + } + CARLA_PREVENT_HEAP_ALLOCATION CARLA_DECLARE_NON_COPY_CLASS(RingBufferControl) }; diff --git a/source/utils/Lv2AtomQueue.hpp b/source/utils/Lv2AtomQueue.hpp index 47704aacb..f3595fe2c 100644 --- a/source/utils/Lv2AtomQueue.hpp +++ b/source/utils/Lv2AtomQueue.hpp @@ -18,6 +18,7 @@ #ifndef LV2_ATOM_QUEUE_HPP_INCLUDED #define LV2_ATOM_QUEUE_HPP_INCLUDED +#include "CarlaMathUtils.hpp" #include "CarlaMutex.hpp" #include "CarlaRingBuffer.hpp" @@ -49,6 +50,9 @@ public: void createBuffer(const uint32_t size) noexcept { + if (fLv2Buffer.size == size && ! fIsDummy) + return; + if (fLv2Buffer.buf != nullptr) { if (! fIsDummy) @@ -59,9 +63,10 @@ public: // shouldn't really happen please... CARLA_SAFE_ASSERT_RETURN(size > 0,); - fLv2Buffer.size = size; - fLv2Buffer.buf = new char[size]; + fLv2Buffer.size = carla_nextPowerOf2(size); + fLv2Buffer.buf = new char[fLv2Buffer.size]; setRingBuffer(&fLv2Buffer, true); + lockMemory(); } // used for tmp buffers only @@ -182,7 +187,7 @@ public: if (! fRingBufferCtrl.isDataAvailable()) return false; - if (const LV2_Atom* retAtom = fRingBufferCtrl.readAtom(portIndex)) + if (const LV2_Atom* const retAtom = fRingBufferCtrl.readAtom(portIndex)) { *atom = retAtom; return true;