diff --git a/source/backend/engine/CarlaEngineBridge.cpp b/source/backend/engine/CarlaEngineBridge.cpp index b63584663..997c72e4d 100644 --- a/source/backend/engine/CarlaEngineBridge.cpp +++ b/source/backend/engine/CarlaEngineBridge.cpp @@ -175,7 +175,7 @@ struct BridgeRtClientControl : public CarlaRingBufferControl { WaitHelper(BridgeRtClientControl& c) noexcept : data(c.data), - ok(jackbridge_sem_timedwait(&data->sem.server, 5)) {} + ok(jackbridge_sem_timedwait(&data->sem.server, 5000)) {} ~WaitHelper() noexcept { @@ -494,7 +494,7 @@ public: carla_stdout(" sizeof(BridgeNonRtClientData): %i/" P_SIZE, shmNonRtClientDataSize, sizeof(BridgeNonRtClientData)); carla_stdout(" sizeof(BridgeNonRtServerData): %i/" P_SIZE, shmNonRtServerDataSize, sizeof(BridgeNonRtServerData)); - if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) + if (shmRtClientDataSize != sizeof(BridgeRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) return false; // tell backend we're live diff --git a/source/backend/plugin/CarlaPluginBridge.cpp b/source/backend/plugin/CarlaPluginBridge.cpp index 1996ce796..c932df612 100644 --- a/source/backend/plugin/CarlaPluginBridge.cpp +++ b/source/backend/plugin/CarlaPluginBridge.cpp @@ -240,13 +240,13 @@ struct BridgeRtClientControl : public CarlaRingBufferControl { setRingBuffer(nullptr, false); } - bool waitForClient(const uint secs) noexcept + bool waitForClient(const uint msecs) noexcept { CARLA_SAFE_ASSERT_RETURN(data != nullptr, false); jackbridge_sem_post(&data->sem.server); - return jackbridge_sem_timedwait(&data->sem.client, secs); + return jackbridge_sem_timedwait(&data->sem.client, msecs); } void writeOpcode(const PluginBridgeRtClientOpcode opcode) noexcept @@ -738,6 +738,7 @@ public: fSaved(true), fTimedOut(false), fTimedError(false), + fProcWaitTime(0), fLastPongTime(-1), fBridgeBinary(), fBridgeThread(engine, this), @@ -783,7 +784,7 @@ public: fShmRtClientControl.commitWrite(); if (! fTimedOut) - waitForClient("stopping", 3); + waitForClient("stopping", 3000); } fBridgeThread.stopThread(3000); @@ -1379,7 +1380,7 @@ public: fTimedOut = false; try { - waitForClient("activate", 2); + waitForClient("activate", 2000); } CARLA_SAFE_EXCEPTION("activate - waitForClient"); } @@ -1397,7 +1398,7 @@ public: fTimedOut = false; try { - waitForClient("deactivate", 2); + waitForClient("deactivate", 2000); } CARLA_SAFE_EXCEPTION("deactivate - waitForClient"); } @@ -1780,7 +1781,7 @@ public: fShmRtClientControl.commitWrite(); } - waitForClient("process", 1); + waitForClient("process", fProcWaitTime); if (fTimedOut) { @@ -1875,7 +1876,10 @@ public: fShmNonRtClientControl.commitWrite(); } - waitForClient("buffersize", 1); + //fProcWaitTime = newBufferSize*1000/pData->engine->getSampleRate(); + fProcWaitTime = 1000; + + waitForClient("buffersize", 1000); } void sampleRateChanged(const double newSampleRate) override @@ -1887,7 +1891,10 @@ public: fShmNonRtClientControl.commitWrite(); } - waitForClient("samplerate", 1); + //fProcWaitTime = pData->engine->getBufferSize()*1000/newSampleRate; + fProcWaitTime = 1000; + + waitForClient("samplerate", 1000); } void offlineModeChanged(const bool isOffline) override @@ -1898,7 +1905,7 @@ public: fShmNonRtClientControl.commitWrite(); } - waitForClient("offline", 1); + waitForClient("offline", 1000); } // ------------------------------------------------------------------- @@ -2509,6 +2516,10 @@ public: fShmNonRtClientControl.commitWrite(); + // testing dummy message + fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull); + fShmRtClientControl.commitWrite(); + // init bridge thread { char shmIdsStr[6*4+1]; @@ -2599,6 +2610,7 @@ private: bool fSaved; bool fTimedOut; bool fTimedError; + uint fProcWaitTime; int64_t fLastPongTime; @@ -2650,15 +2662,15 @@ private: fShmRtClientControl.writeULong(static_cast(fShmAudioPool.size)); fShmRtClientControl.commitWrite(); - waitForClient("resize-pool", 5); + waitForClient("resize-pool", 5000); } - void waitForClient(const char* const action, const uint secs) + void waitForClient(const char* const action, const uint msecs) { CARLA_SAFE_ASSERT_RETURN(! fTimedOut,); CARLA_SAFE_ASSERT_RETURN(! fTimedError,); - if (fShmRtClientControl.waitForClient(secs)) + if (fShmRtClientControl.waitForClient(msecs)) return; fTimedOut = true; diff --git a/source/jackbridge/JackBridge.hpp b/source/jackbridge/JackBridge.hpp index c45eda5cd..61e6fc22f 100644 --- a/source/jackbridge/JackBridge.hpp +++ b/source/jackbridge/JackBridge.hpp @@ -397,7 +397,7 @@ JACKBRIDGE_API bool jackbridge_set_property_change_callback(jack_client_t* clien JACKBRIDGE_API bool jackbridge_sem_init(void* sem) noexcept; JACKBRIDGE_API void jackbridge_sem_destroy(void* sem) noexcept; JACKBRIDGE_API void jackbridge_sem_post(void* sem) noexcept; -JACKBRIDGE_API bool jackbridge_sem_timedwait(void* sem, uint secs) noexcept; +JACKBRIDGE_API bool jackbridge_sem_timedwait(void* sem, uint msecs) noexcept; JACKBRIDGE_API bool jackbridge_shm_is_valid(const void* shm) noexcept; JACKBRIDGE_API void jackbridge_shm_init(void* shm) noexcept; diff --git a/source/jackbridge/JackBridge2.cpp b/source/jackbridge/JackBridge2.cpp index 54865d1f5..4df9955d6 100644 --- a/source/jackbridge/JackBridge2.cpp +++ b/source/jackbridge/JackBridge2.cpp @@ -52,14 +52,14 @@ void jackbridge_sem_post(void* sem) noexcept #endif } -bool jackbridge_sem_timedwait(void* sem, uint secs) noexcept +bool jackbridge_sem_timedwait(void* sem, uint msecs) noexcept { CARLA_SAFE_ASSERT_RETURN(sem != nullptr, false); #ifdef JACKBRIDGE_DUMMY return false; #else - return carla_sem_timedwait(*(carla_sem_t*)sem, secs); + return carla_sem_timedwait(*(carla_sem_t*)sem, msecs); #endif } diff --git a/source/jackbridge/JackBridgeExport.cpp b/source/jackbridge/JackBridgeExport.cpp index 836d5807e..ab013ba79 100644 --- a/source/jackbridge/JackBridgeExport.cpp +++ b/source/jackbridge/JackBridgeExport.cpp @@ -548,9 +548,9 @@ void jackbridge_sem_post(void* sem) noexcept getBridgeInstance().sem_post_ptr(sem); } -bool jackbridge_sem_timedwait(void* sem, uint secs) noexcept +bool jackbridge_sem_timedwait(void* sem, uint msecs) noexcept { - return getBridgeInstance().sem_timedwait_ptr(sem, secs); + return getBridgeInstance().sem_timedwait_ptr(sem, msecs); } bool jackbridge_shm_is_valid(const void* shm) noexcept diff --git a/source/utils/CarlaSemUtils.hpp b/source/utils/CarlaSemUtils.hpp index 798b3b2ed..9c1fa99e0 100644 --- a/source/utils/CarlaSemUtils.hpp +++ b/source/utils/CarlaSemUtils.hpp @@ -22,15 +22,24 @@ #include +#define CARLA_USE_FUTEXES + #ifdef CARLA_OS_WIN struct carla_sem_t { HANDLE handle; }; #elif defined(CARLA_OS_MAC) // TODO struct carla_sem_t { char dummy; }; +#elif defined(CARLA_USE_FUTEXES) +# include +# include +# include +# include +struct carla_sem_t { int count; }; #else +# include +# include # include # include -# include struct carla_sem_t { sem_t sem; }; #endif @@ -40,6 +49,7 @@ struct carla_sem_t { sem_t sem; }; static inline bool carla_sem_create2(carla_sem_t& sem) noexcept { + carla_zeroStruct(sem); #if defined(CARLA_OS_WIN) SECURITY_ATTRIBUTES sa; carla_zeroStruct(sa); @@ -51,6 +61,9 @@ bool carla_sem_create2(carla_sem_t& sem) noexcept return (sem.handle != INVALID_HANDLE_VALUE); #elif defined(CARLA_OS_MAC) return false; // TODO +#elif defined(CARLA_USE_FUTEXES) + sem.count = 0; + return true; #else return (::sem_init(&sem.sem, 1, 0) == 0); #endif @@ -83,6 +96,9 @@ void carla_sem_destroy2(carla_sem_t& sem) noexcept ::CloseHandle(sem.handle); #elif defined(CARLA_OS_MAC) // TODO +#elif defined(CARLA_USE_FUTEXES) + // nothing to do + (void)sem; #else ::sem_destroy(&sem.sem); #endif @@ -110,6 +126,10 @@ void carla_sem_post(carla_sem_t& sem) noexcept ::ReleaseSemaphore(sem.handle, 1, nullptr); #elif defined(CARLA_OS_MAC) // TODO +#elif defined(CARLA_USE_FUTEXES) + const bool unlocked = __sync_bool_compare_and_swap(&sem.count, 0, 1); + CARLA_SAFE_ASSERT_RETURN(unlocked,); + ::syscall(__NR_futex, &sem.count, FUTEX_WAKE, 1, nullptr, nullptr, 0); #else ::sem_post(&sem.sem); #endif @@ -119,21 +139,42 @@ void carla_sem_post(carla_sem_t& sem) noexcept * Wait for a semaphore (lock). */ static inline -bool carla_sem_timedwait(carla_sem_t& sem, const uint secs) noexcept +bool carla_sem_timedwait(carla_sem_t& sem, const uint msecs) noexcept { - CARLA_SAFE_ASSERT_RETURN(secs > 0, false); + CARLA_SAFE_ASSERT_RETURN(msecs > 0, false); #if defined(CARLA_OS_WIN) return (::WaitForSingleObject(sem.handle, secs*1000) == WAIT_OBJECT_0); #elif defined(CARLA_OS_MAC) - // TODO + return false; // TODO +#elif defined(CARLA_USE_FUTEXES) + timespec timeout; + timeout.tv_sec = static_cast(msecs / 1000); + timeout.tv_nsec = static_cast(msecs % 1000); + + for (; ! __sync_bool_compare_and_swap(&sem.count, 1, 0);) + { + if (syscall(__NR_futex, &sem.count, FUTEX_WAIT, 0, &timeout, nullptr, 0) == 0) + { + __sync_fetch_and_sub(&sem.count, 1); + return true; + } + + //if (errno == EAGAIN) + // continue; + + return false; + } + + return true; #else if (::sem_trywait(&sem.sem) == 0) return true; timespec timeout; ::clock_gettime(CLOCK_REALTIME, &timeout); - timeout.tv_sec += static_cast(secs); + timeout.tv_sec += static_cast(msecs / 1000); + timeout.tv_nsec += static_cast(msecs % 1000); try { return (::sem_timedwait(&sem.sem, &timeout) == 0);