git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2302 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.90
| @@ -24,6 +24,7 @@ Fernando Lopez-Lezcano | |||||
| * Correct JackEngine::PortUnRegister, JackEngine::ClientCloseAux and JackEngine::ClientDeactivate to correctly send notifications. | * Correct JackEngine::PortUnRegister, JackEngine::ClientCloseAux and JackEngine::ClientDeactivate to correctly send notifications. | ||||
| * New jack_get_client_pid API, implemented on server side. | * New jack_get_client_pid API, implemented on server side. | ||||
| * Better handling of graph state read functions : never wait when used in the real-time thread, current state is used. | |||||
| 2008-05-20 Stephane Letz <letz@grame.fr> | 2008-05-20 Stephane Letz <letz@grame.fr> | ||||
| @@ -248,12 +248,20 @@ static inline bool CheckBufferSize(jack_nframes_t buffer_size) | |||||
| static inline void WaitGraphChange() | static inline void WaitGraphChange() | ||||
| { | { | ||||
| JackGraphManager* manager = GetGraphManager(); | |||||
| JackEngineControl* control = GetEngineControl(); | |||||
| if (manager && control && manager->IsPendingChange()) { | |||||
| jack_log("WaitGraphChange..."); | |||||
| JackSleep(int(control->fPeriodUsecs * 1.1f)); | |||||
| /* | |||||
| TLS key that is set only in RT thread, so never waits for pending | |||||
| graph change in RT context (just read the current graph state). | |||||
| */ | |||||
| if (jack_tls_get(gRealTime) == NULL) { | |||||
| JackGraphManager* manager = GetGraphManager(); | |||||
| JackEngineControl* control = GetEngineControl(); | |||||
| assert(manager); | |||||
| assert(control); | |||||
| if (manager->IsPendingChange()) { | |||||
| jack_log("WaitGraphChange..."); | |||||
| JackSleep(int(control->fPeriodUsecs * 1.1f)); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -36,7 +36,7 @@ namespace Jack | |||||
| { | { | ||||
| #define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL)) | #define IsRealTime() ((fProcess != NULL) | (fThreadFun != NULL) | (fSync != NULL) | (fTimebase != NULL)) | ||||
| JackClient::JackClient() | JackClient::JackClient() | ||||
| {} | {} | ||||
| @@ -335,6 +335,9 @@ int JackClient::StartThread() | |||||
| */ | */ | ||||
| bool JackClient::Execute() | bool JackClient::Execute() | ||||
| { | { | ||||
| if (!jack_tls_set(gRealTime, this)) | |||||
| jack_error("failed to set thread realtime key"); | |||||
| if (fThreadFun) { | if (fThreadFun) { | ||||
| // Execute a dummy cycle to be sure thread has the correct properties (ensure thread creation is finished) | // Execute a dummy cycle to be sure thread has the correct properties (ensure thread creation is finished) | ||||
| WaitSync(); | WaitSync(); | ||||
| @@ -22,6 +22,43 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| JackFactoryImpl* JackGlobals::fInstance; | |||||
| JackFactoryImpl* JackGlobals::fInstance; | |||||
| } // end of namespace | } // end of namespace | ||||
| static bool gKeyRealtimeInitialized = false; | |||||
| jack_tls_key gRealTime; | |||||
| void jack_realtime_init() | |||||
| { | |||||
| if (!gKeyRealtimeInitialized) { | |||||
| gKeyRealtimeInitialized = jack_tls_allocate_key(&gRealTime); | |||||
| } | |||||
| } | |||||
| void jack_realtime_uninit() | |||||
| { | |||||
| if (gKeyRealtimeInitialized) { | |||||
| jack_tls_free_key(gRealTime); | |||||
| gKeyRealtimeInitialized = false; | |||||
| } | |||||
| } | |||||
| // Initialisation at library load time | |||||
| #ifdef WIN32 | |||||
| BOOL WINAPI DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) | |||||
| { | |||||
| switch (fdwReason) { | |||||
| case DLL_PROCESS_ATTACH: | |||||
| jack_realtime_init(); | |||||
| break; | |||||
| case DLL_PROCESS_DETACH: | |||||
| jack_realtime_uninit(); | |||||
| break; | |||||
| } | |||||
| return TRUE; | |||||
| } | |||||
| #endif | |||||
| @@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| #define __JackGlobals__ | #define __JackGlobals__ | ||||
| #include "JackError.h" | #include "JackError.h" | ||||
| #include "JackThread.h" | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| @@ -279,4 +280,18 @@ class JackGlobals | |||||
| } // end of namespace | } // end of namespace | ||||
| #ifdef __cplusplus | |||||
| extern "C" | |||||
| { | |||||
| #endif | |||||
| extern jack_tls_key gRealTime; | |||||
| void __attribute__ ((constructor)) jack_realtime_init(); | |||||
| void __attribute__ ((destructor)) jack_realtime_uninit(); | |||||
| #ifdef __cplusplus | |||||
| } | |||||
| #endif | |||||
| #endif | #endif | ||||
| @@ -48,7 +48,7 @@ struct JackLibGlobals | |||||
| #ifdef __APPLE__ | #ifdef __APPLE__ | ||||
| std::map<mach_port_t, JackClient*> fClientTable; /*! Client table */ | std::map<mach_port_t, JackClient*> fClientTable; /*! Client table */ | ||||
| #endif | #endif | ||||
| static int fClientCount; | static int fClientCount; | ||||
| static JackLibGlobals* fGlobals; | static JackLibGlobals* fGlobals; | ||||
| @@ -219,3 +219,49 @@ void JackPosixThread::Terminate() | |||||
| } // end of namespace | } // end of namespace | ||||
| bool jack_tls_allocate_key(jack_tls_key *key_ptr) | |||||
| { | |||||
| int ret; | |||||
| ret = pthread_key_create(key_ptr, NULL); | |||||
| if (ret != 0) | |||||
| { | |||||
| jack_error("pthread_key_create() failed with error %d errno %s", ret, strerror(errno)); | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool jack_tls_free_key(jack_tls_key key) | |||||
| { | |||||
| int ret; | |||||
| ret = pthread_key_delete(key); | |||||
| if (ret != 0) | |||||
| { | |||||
| jack_error("pthread_key_delete() failed with error %d errno %s", ret, strerror(errno)); | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool jack_tls_set(jack_tls_key key, void *data_ptr) | |||||
| { | |||||
| int ret; | |||||
| ret = pthread_setspecific(key, (const void *)data_ptr); | |||||
| if (ret != 0) | |||||
| { | |||||
| jack_error("pthread_setspecific() failed with error %d errno %s", ret, strerror(errno)); | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| void *jack_tls_get(jack_tls_key key) | |||||
| { | |||||
| return pthread_getspecific(key); | |||||
| } | |||||
| @@ -108,4 +108,16 @@ class JackThread | |||||
| } // end of namespace | } // end of namespace | ||||
| #if defined(WIN32) | |||||
| typedef DWORD jack_tls_key; | |||||
| #else | |||||
| typedef pthread_key_t jack_tls_key; | |||||
| #endif | |||||
| bool jack_tls_allocate_key(jack_tls_key *key_ptr); | |||||
| bool jack_tls_free_key(jack_tls_key key); | |||||
| bool jack_tls_set(jack_tls_key key, void *data_ptr); | |||||
| void *jack_tls_get(jack_tls_key key); | |||||
| #endif | #endif | ||||
| @@ -257,3 +257,44 @@ void JackWinThread::Terminate() | |||||
| } // end of namespace | } // end of namespace | ||||
| bool jack_tls_allocate_key(jack_tls_key *key_ptr) | |||||
| { | |||||
| DWORD key; | |||||
| key = TlsAlloc(); | |||||
| if (key == TLS_OUT_OF_INDEXES) | |||||
| { | |||||
| jack_error("TlsAlloc() failed. Error is %d", (unsigned int)GetLastError()); | |||||
| return false; | |||||
| } | |||||
| *key_ptr = key; | |||||
| return true; | |||||
| } | |||||
| bool jack_tls_free_key(jack_tls_key key) | |||||
| { | |||||
| if (!TlsFree(key)) | |||||
| { | |||||
| jack_error("TlsFree() failed. Error is %d", (unsigned int)GetLastError()); | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| bool jack_tls_set(jack_tls_key key, void *data_ptr) | |||||
| { | |||||
| if (!TlsSetValue(key, data_ptr)) | |||||
| { | |||||
| jack_error("TlsSetValue() failed. Error is %d", (unsigned int)GetLastError()); | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| void *jack_tls_get(jack_tls_key key) | |||||
| { | |||||
| return TlsGetValue(key); | |||||
| } | |||||