Commit 49cac802 authored by Stéphane LETZ's avatar Stéphane LETZ
Browse files

Release JackEngine mutex before sending notifications.

parent f1ccdba0
......@@ -35,8 +35,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack
{
#define AssertRefnum(ref) assert(ref >= 0 && ref < CLIENT_NUM);
JackEngine::JackEngine(JackGraphManager* manager,
JackSynchro* table,
JackEngineControl* control)
......@@ -213,28 +211,28 @@ void JackEngine::NotifyClient(int refnum, int event, int sync, const char* messa
JackClientInterface* client = fClientTable[refnum];
// The client may be notified by the RT thread while closing
if (!client) {
jack_log("JackEngine::NotifyClient: client not available anymore");
} else if (client->GetClientControl()->fCallback[event]) {
if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0)
jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2);
} else {
jack_log("JackEngine::NotifyClient: no callback for event = %ld", event);
if (client) {
if (client && client->GetClientControl()->fCallback[event]) {
/*
Important for internal clients : unlock before calling the notification callbacks.
*/
bool res = fMutex.Unlock();
if (client->ClientNotify(refnum, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0)
jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2);
if (res)
fMutex.Lock();
} else {
jack_log("JackEngine::NotifyClient: no callback for event = %ld", event);
}
}
}
void JackEngine::NotifyClients(int event, int sync, const char* message, int value1, int value2)
void JackEngine::NotifyClients(int event, int sync, const char* message, int value1, int value2)
{
for (int i = 0; i < CLIENT_NUM; i++) {
JackClientInterface* client = fClientTable[i];
if (client) {
if (client->GetClientControl()->fCallback[event]) {
if (client->ClientNotify(i, client->GetClientControl()->fName, event, sync, message, value1, value2) < 0)
jack_error("NotifyClient fails name = %s event = %ld val1 = %ld val2 = %ld", client->GetClientControl()->fName, event, value1, value2);
} else {
jack_log("JackEngine::NotifyClients: no callback for event = %ld", event);
}
}
NotifyClient(i, event, sync, message, value1, value2);
}
}
......@@ -274,8 +272,7 @@ void JackEngine::NotifyRemoveClient(const char* name, int refnum)
void JackEngine::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs)
{
// Use the audio thread => request thread communication channel
fEngineControl->ResetFrameTime(callback_usecs);
fEngineControl->NotifyXRun(delayed_usecs);
fEngineControl->NotifyXRun(callback_usecs, delayed_usecs);
fChannel.Notify(ALL_CLIENTS, kXRunCallback, 0);
}
......@@ -348,7 +345,6 @@ void JackEngine::NotifyActivate(int refnum)
int JackEngine::GetInternalClientName(int refnum, char* name_res)
{
AssertRefnum(refnum);
JackClientInterface* client = fClientTable[refnum];
if (client) {
strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE);
......@@ -378,7 +374,6 @@ int JackEngine::InternalClientHandle(const char* client_name, int* status, int*
int JackEngine::InternalClientUnload(int refnum, int* status)
{
AssertRefnum(refnum);
JackClientInterface* client = fClientTable[refnum];
if (client) {
int res = client->Close();
......@@ -592,7 +587,6 @@ error:
// Used for external clients
int JackEngine::ClientExternalClose(int refnum)
{
AssertRefnum(refnum);
JackClientInterface* client = fClientTable[refnum];
if (client) {
......@@ -609,7 +603,6 @@ int JackEngine::ClientExternalClose(int refnum)
// Used for server internal clients or drivers when the RT thread is stopped
int JackEngine::ClientInternalClose(int refnum, bool wait)
{
AssertRefnum(refnum);
JackClientInterface* client = fClientTable[refnum];
return (client) ? ClientCloseAux(refnum, client, wait) : -1;
}
......@@ -656,10 +649,8 @@ int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wai
int JackEngine::ClientActivate(int refnum, bool is_real_time)
{
AssertRefnum(refnum);
JackClientInterface* client = fClientTable[refnum];
assert(fClientTable[refnum]);
jack_log("JackEngine::ClientActivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);
if (is_real_time)
fGraphManager->Activate(refnum);
......@@ -677,7 +668,6 @@ int JackEngine::ClientActivate(int refnum, bool is_real_time)
// May be called without client
int JackEngine::ClientDeactivate(int refnum)
{
AssertRefnum(refnum);
JackClientInterface* client = fClientTable[refnum];
if (client == NULL)
return -1;
......@@ -717,9 +707,7 @@ int JackEngine::ClientDeactivate(int refnum)
int JackEngine::PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port_index)
{
jack_log("JackEngine::PortRegister ref = %ld name = %s type = %s flags = %d buffer_size = %d", refnum, name, type, flags, buffer_size);
AssertRefnum(refnum);
assert(fClientTable[refnum]);
// Check if port name already exists
if (fGraphManager->GetPort(name) != NO_PORT) {
jack_error("port_name \"%s\" already exists", name);
......@@ -737,10 +725,9 @@ int JackEngine::PortRegister(int refnum, const char* name, const char *type, uns
int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index)
{
JackLock lock(this);
jack_log("JackEngine::PortUnRegister ref = %ld port_index = %ld", refnum, port_index);
AssertRefnum(refnum);
assert(fClientTable[refnum]);
// Disconnect port ==> notification is sent
PortDisconnect(refnum, port_index, ALL_PORTS);
......@@ -755,7 +742,6 @@ int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index)
int JackEngine::PortConnect(int refnum, const char* src, const char* dst)
{
jack_log("JackEngine::PortConnect src = %s dst = %s", src, dst);
AssertRefnum(refnum);
jack_port_id_t port_src, port_dst;
return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0)
......@@ -766,7 +752,6 @@ int JackEngine::PortConnect(int refnum, const char* src, const char* dst)
int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
{
jack_log("JackEngine::PortConnect src = %d dst = %d", src, dst);
AssertRefnum(refnum);
JackClientInterface* client;
int ref;
......@@ -802,7 +787,6 @@ int JackEngine::PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
int JackEngine::PortDisconnect(int refnum, const char* src, const char* dst)
{
jack_log("JackEngine::PortDisconnect src = %s dst = %s", src, dst);
AssertRefnum(refnum);
jack_port_id_t port_src, port_dst;
return (fGraphManager->GetTwoPorts(src, dst, &port_src, &port_dst) < 0)
......@@ -813,8 +797,7 @@ int JackEngine::PortDisconnect(int refnum, const char* src, const char* dst)
int JackEngine::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
{
jack_log("JackEngine::PortDisconnect src = %d dst = %d", src, dst);
AssertRefnum(refnum);
if (dst == ALL_PORTS) {
jack_int_t connections[CONNECTION_NUM_FOR_PORT];
......@@ -850,7 +833,6 @@ int JackEngine::PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t ds
int JackEngine::PortRename(int refnum, jack_port_id_t port, const char* name)
{
AssertRefnum(refnum);
char old_name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
strcpy(old_name, fGraphManager->GetPort(port)->GetName());
fGraphManager->GetPort(port)->SetName(name);
......
......@@ -23,6 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackConstants.h"
#include "JackGraphManager.h"
#include "JackSynchro.h"
#include "JackMutex.h"
#include "JackTransportEngine.h"
#include "JackPlatformPlug.h"
......@@ -37,8 +38,10 @@ class JackExternalClient;
\brief Engine description.
*/
class SERVER_EXPORT JackEngine
class SERVER_EXPORT JackEngine : public JackLockAble
{
friend class JackLockedEngine;
private:
JackGraphManager* fGraphManager;
......@@ -71,6 +74,11 @@ class SERVER_EXPORT JackEngine
void NotifyPortConnect(jack_port_id_t src, jack_port_id_t dst, bool onoff);
void NotifyPortRename(jack_port_id_t src, const char* old_name);
void NotifyActivate(int refnum);
bool CheckClient(int refnum)
{
return (refnum >= 0 && refnum < CLIENT_NUM && fClientTable[refnum] != NULL);
}
public:
......
......@@ -81,8 +81,9 @@ void JackEngineControl::ResetRollingUsecs()
fRollingInterval = int(floor((JACK_ENGINE_ROLLING_INTERVAL * 1000.f) / fPeriodUsecs));
}
void JackEngineControl::NotifyXRun(float delayed_usecs)
void JackEngineControl::NotifyXRun(jack_time_t callback_usecs, float delayed_usecs)
{
ResetFrameTime(callback_usecs);
fXrunDelayedUsecs = delayed_usecs;
if (delayed_usecs > fMaxDelayedUsecs)
fMaxDelayedUsecs = delayed_usecs;
......
......@@ -162,7 +162,7 @@ struct SERVER_EXPORT JackEngineControl : public JackShmMem
}
// XRun
void NotifyXRun(float delayed_usecs);
void NotifyXRun(jack_time_t callback_usecs, float delayed_usecs);
void ResetXRun()
{
fMaxDelayedUsecs = 0.f;
......
......@@ -37,7 +37,6 @@ See : http://groups.google.com/group/comp.programming.threads/browse_thread/thre
catch (...) {
// Assuming thread cancellation, must rethrow
throw;
}
*/
......@@ -62,11 +61,12 @@ catch (...) {
throw; \
} \
/*!
\brief Locked Engine, access to methods is serialized using a mutex.
*/
class SERVER_EXPORT JackLockedEngine : public JackLockAble
class SERVER_EXPORT JackLockedEngine
{
private:
......@@ -99,21 +99,21 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
int ClientCheck(const char* name, char* name_res, int protocol, int options, int* status)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.ClientCheck(name, name_res, protocol, options, status);
CATCH_EXCEPTION_RETURN
}
int ClientExternalOpen(const char* name, int pid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.ClientExternalOpen(name, pid, ref, shared_engine, shared_client, shared_graph_manager);
CATCH_EXCEPTION_RETURN
}
int ClientInternalOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, bool wait)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.ClientInternalOpen(name, ref, shared_engine, shared_manager, client, wait);
CATCH_EXCEPTION_RETURN
}
......@@ -121,30 +121,30 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
int ClientExternalClose(int refnum)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientExternalClose(refnum);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.ClientExternalClose(refnum) : - 1;
CATCH_EXCEPTION_RETURN
}
int ClientInternalClose(int refnum, bool wait)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientInternalClose(refnum, wait);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.ClientInternalClose(refnum, wait) : -1;
CATCH_EXCEPTION_RETURN
}
int ClientActivate(int refnum, bool is_real_time)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientActivate(refnum, is_real_time);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.ClientActivate(refnum, is_real_time) : -1;
CATCH_EXCEPTION_RETURN
}
int ClientDeactivate(int refnum)
{
TRY_CALL
JackLock lock(this);
return fEngine.ClientDeactivate(refnum);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.ClientDeactivate(refnum) : -1;
CATCH_EXCEPTION_RETURN
}
......@@ -152,22 +152,22 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
int GetInternalClientName(int int_ref, char* name_res)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.GetInternalClientName(int_ref, name_res);
CATCH_EXCEPTION_RETURN
}
int InternalClientHandle(const char* client_name, int* status, int* int_ref)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.InternalClientHandle(client_name, status, int_ref);
CATCH_EXCEPTION_RETURN
}
int InternalClientUnload(int refnum, int* status)
{
TRY_CALL
JackLock lock(this);
return fEngine.InternalClientUnload(refnum, status);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.InternalClientUnload(refnum, status) : -1;
CATCH_EXCEPTION_RETURN
}
......@@ -175,53 +175,53 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
int PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortRegister(refnum, name, type, flags, buffer_size, port);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.PortRegister(refnum, name, type, flags, buffer_size, port) : -1;
CATCH_EXCEPTION_RETURN
}
int PortUnRegister(int refnum, jack_port_id_t port)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortUnRegister(refnum, port);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.PortUnRegister(refnum, port) : -1;
CATCH_EXCEPTION_RETURN
}
int PortConnect(int refnum, const char* src, const char* dst)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortConnect(refnum, src, dst);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.PortConnect(refnum, src, dst) : -1;
CATCH_EXCEPTION_RETURN
}
int PortDisconnect(int refnum, const char* src, const char* dst)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortDisconnect(refnum, src, dst);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.PortDisconnect(refnum, src, dst) : -1;
CATCH_EXCEPTION_RETURN
}
int PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortConnect(refnum, src, dst);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.PortConnect(refnum, src, dst) : -1;
CATCH_EXCEPTION_RETURN
}
int PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortDisconnect(refnum, src, dst);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.PortDisconnect(refnum, src, dst) : -1;
CATCH_EXCEPTION_RETURN
}
int PortRename(int refnum, jack_port_id_t port, const char* name)
{
TRY_CALL
JackLock lock(this);
return fEngine.PortRename(refnum, port, name);
JackLock lock(&fEngine);
return (fEngine.CheckClient(refnum)) ? fEngine.PortRename(refnum, port, name) : -1;
CATCH_EXCEPTION_RETURN
}
......@@ -241,36 +241,35 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
void NotifyXRun(int refnum)
{
TRY_CALL
JackLock lock(this);
// RT : no lock
fEngine.NotifyXRun(refnum);
CATCH_EXCEPTION
}
void NotifyGraphReorder()
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
fEngine.NotifyGraphReorder();
CATCH_EXCEPTION
}
void NotifyBufferSize(jack_nframes_t buffer_size)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
fEngine.NotifyBufferSize(buffer_size);
CATCH_EXCEPTION
}
void NotifySampleRate(jack_nframes_t sample_rate)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
fEngine.NotifySampleRate(sample_rate);
CATCH_EXCEPTION
}
void NotifyFreewheel(bool onoff)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
fEngine.NotifyFreewheel(onoff);
CATCH_EXCEPTION
}
......@@ -278,7 +277,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
void NotifyFailure(int code, const char* reason)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
fEngine.NotifyFailure(code, reason);
CATCH_EXCEPTION
}
......@@ -286,7 +285,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
int GetClientPID(const char* name)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.GetClientPID(name);
CATCH_EXCEPTION_RETURN
}
......@@ -294,7 +293,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
int GetClientRefNum(const char* name)
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.GetClientRefNum(name);
CATCH_EXCEPTION_RETURN
}
......@@ -302,7 +301,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
void NotifyQuit()
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.NotifyQuit();
CATCH_EXCEPTION
}
......
......@@ -36,11 +36,9 @@ namespace Jack
class JackLockAble
{
private:
JackMutex fMutex;
protected:
JackMutex fMutex;
JackLockAble()
{}
......
This diff is collapsed.
......@@ -103,11 +103,12 @@ class JackPosixMutex
pthread_mutex_destroy(&fMutex);
}
void Lock()
bool Lock()
{
int res = pthread_mutex_lock(&fMutex);
if (res != 0)
jack_error("JackPosixMutex::Lock res = %d", res);
return (res == 0);
}
bool Trylock()
......@@ -115,11 +116,12 @@ class JackPosixMutex
return (pthread_mutex_trylock(&fMutex) == 0);
}
void Unlock()
bool Unlock()
{
int res = pthread_mutex_unlock(&fMutex);
if (res != 0)
jack_error("JackPosixMutex::Unlock res = %d", res);
return (res == 0);
}
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment