| @@ -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<int32_t>(sizeof(BridgeShmControl))); | |||
| @@ -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) | |||
| @@ -20,6 +20,13 @@ | |||
| #include "CarlaUtils.hpp" | |||
| #ifndef CARLA_OS_WIN | |||
| # include <sys/mman.h> | |||
| # ifdef CARLA_OS_MAC | |||
| # include <libkern/OSAtomic.h> | |||
| # 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<int32_t>(readto); | |||
| } | |||
| @@ -261,12 +283,24 @@ protected: | |||
| std::memcpy(fBuffer->buf + wrtn, charbuf, size); | |||
| } | |||
| memoryBarrier(); | |||
| fBuffer->written = static_cast<int32_t>(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) | |||
| }; | |||
| @@ -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; | |||