Browse Source

Merge branch 'server_no_deadlock'

git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@3901 0c269be4-1314-0410-8aa9-9f06e86f4224
tags/v1.9.5
sletz 16 years ago
parent
commit
1aa8420bc7
7 changed files with 89 additions and 111 deletions
  1. +30
    -61
      common/JackEngine.cpp
  2. +9
    -1
      common/JackEngine.h
  3. +2
    -1
      common/JackEngineControl.cpp
  4. +1
    -1
      common/JackEngineControl.h
  5. +41
    -41
      common/JackLockedEngine.h
  6. +2
    -4
      common/JackMutex.h
  7. +4
    -2
      posix/JackPosixMutex.h

+ 30
- 61
common/JackEngine.cpp View File

@@ -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,14 +345,9 @@ 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);
return 0;
} else {
return -1;
}
strncpy(name_res, client->GetClientControl()->fName, JACK_CLIENT_NAME_SIZE);
return 0;
}

int JackEngine::InternalClientHandle(const char* client_name, int* status, int* int_ref)
@@ -378,7 +370,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,26 +583,19 @@ error:
// Used for external clients
int JackEngine::ClientExternalClose(int refnum)
{
AssertRefnum(refnum);
JackClientInterface* client = fClientTable[refnum];

if (client) {
fEngineControl->fTransport.ResetTimebase(refnum);
int res = ClientCloseAux(refnum, client, true);
client->Close();
delete client;
return res;
} else {
return -1;
}
fEngineControl->fTransport.ResetTimebase(refnum);
int res = ClientCloseAux(refnum, client, true);
client->Close();
delete client;
return res;
}

// 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;
return ClientCloseAux(refnum, client, wait);
}

int JackEngine::ClientCloseAux(int refnum, JackClientInterface* client, bool wait)
@@ -656,11 +640,9 @@ 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,11 +659,7 @@ 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;

jack_log("JackEngine::ClientDeactivate ref = %ld name = %s", refnum, client->GetClientControl()->fName);

// Disconnect all ports ==> notifications are sent
@@ -717,9 +695,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);
@@ -738,9 +714,7 @@ int JackEngine::PortRegister(int refnum, const char* name, const char *type, uns
int JackEngine::PortUnRegister(int refnum, jack_port_id_t port_index)
{
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 +729,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 +739,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 +774,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 +784,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 +820,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);


+ 9
- 1
common/JackEngine.h View File

@@ -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:



+ 2
- 1
common/JackEngineControl.cpp View File

@@ -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;


+ 1
- 1
common/JackEngineControl.h View File

@@ -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;


+ 41
- 41
common/JackLockedEngine.h View File

@@ -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,21 +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);
JackLock lock(&fEngine);
// Client is tested in fEngine.InternalClientUnload
return fEngine.InternalClientUnload(refnum, status);
CATCH_EXCEPTION_RETURN
}
@@ -175,53 +176,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 +242,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 +278,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 +286,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 +294,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 +302,7 @@ class SERVER_EXPORT JackLockedEngine : public JackLockAble
void NotifyQuit()
{
TRY_CALL
JackLock lock(this);
JackLock lock(&fEngine);
return fEngine.NotifyQuit();
CATCH_EXCEPTION
}


+ 2
- 4
common/JackMutex.h View File

@@ -36,11 +36,9 @@ namespace Jack
class JackLockAble
{

private:

JackMutex fMutex;

protected:
JackMutex fMutex;

JackLockAble()
{}


+ 4
- 2
posix/JackPosixMutex.h View File

@@ -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);
}

};


Loading…
Cancel
Save