git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@1349 0c269be4-1314-0410-8aa9-9f06e86f4224tags/0.61
@@ -26,6 +26,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackGlobals.h" | |||
#include "JackTime.h" | |||
#include "JackExports.h" | |||
#ifdef __APPLE__ | |||
#include "JackMachThread.h" | |||
#elif WIN32 | |||
#include "JackWinThread.h" | |||
#else | |||
#include "JackPosixThread.h" | |||
#endif | |||
#include <math.h> | |||
using namespace Jack; | |||
@@ -1073,8 +1080,13 @@ EXPORT void jack_reset_max_delayed_usecs(jack_client_t* ext_client) | |||
EXPORT int jack_acquire_real_time_scheduling(pthread_t thread, int priority) | |||
{ | |||
JackLog("jack_acquire_real_time_scheduling: not yet implemented\n"); | |||
return -1; | |||
#ifdef __APPLE__ | |||
return JackMachThread::AcquireRealTimeImp(thread, 0, 500 * 1000, 500 * 1000); | |||
#elif WIN32 | |||
return JackWinThread::AcquireRealTimeImp(thread, priority); | |||
#else | |||
return JackPosixThread::AcquireRealTimeImp(thread, priority); | |||
#endif | |||
} | |||
EXPORT int jack_client_create_thread(jack_client_t* client, | |||
@@ -1084,14 +1096,24 @@ EXPORT int jack_client_create_thread(jack_client_t* client, | |||
void *(*start_routine)(void*), | |||
void *arg) | |||
{ | |||
JackLog("jack_client_create_thread: not yet implemented\n"); | |||
return -1; | |||
#ifdef __APPLE__ | |||
return JackPosixThread::StartImp(thread, priority, realtime, start_routine, arg); | |||
#elif WIN32 | |||
return JackWinThread::StartImp(thread, priority, realtime, start_routine, arg); | |||
#else | |||
return JackPosixThread::StartImp(thread, priority, realtime, start_routine, arg); | |||
#endif | |||
} | |||
EXPORT int jack_drop_real_time_scheduling(pthread_t thread) | |||
{ | |||
JackLog("jack_drop_real_time_scheduling: not yet implemented\n"); | |||
return -1; | |||
#ifdef __APPLE__ | |||
return JackMachThread::DropRealTimeImp(thread); | |||
#elif WIN32 | |||
return JackWinThread::DropRealTimeImp(thread); | |||
#else | |||
return JackPosixThread::DropRealTimeImp(thread); | |||
#endif | |||
} | |||
// intclient.h | |||
@@ -56,10 +56,22 @@ void* JackPosixThread::ThreadHandler(void* arg) | |||
int JackPosixThread::Start() | |||
{ | |||
int res; | |||
fRunning = true; | |||
fRunning = true; | |||
// Check if the thread was correctly started | |||
if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { | |||
fRunning = false; | |||
return -1; | |||
} else { | |||
return 0; | |||
} | |||
} | |||
if (fRealTime) { | |||
int JackPosixThread::StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg) | |||
{ | |||
int res; | |||
if (realtime) { | |||
JackLog("Create RT thread\n"); | |||
@@ -98,14 +110,14 @@ int JackPosixThread::Start() | |||
} | |||
memset(&rt_param, 0, sizeof(rt_param)); | |||
rt_param.sched_priority = fPriority; | |||
rt_param.sched_priority = priority; | |||
if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) { | |||
jack_error("Cannot set scheduling priority for RT thread %d %s", res, strerror(errno)); | |||
return -1; | |||
} | |||
if ((res = pthread_create(&fThread, &attributes, ThreadHandler, this))) { | |||
if ((res = pthread_create(thread, &attributes, start_routine, arg))) { | |||
jack_error("Cannot set create thread %d %s", res, strerror(errno)); | |||
return -1; | |||
} | |||
@@ -114,7 +126,7 @@ int JackPosixThread::Start() | |||
} else { | |||
JackLog("Create non RT thread\n"); | |||
if ((res = pthread_create(&fThread, 0, ThreadHandler, this))) { | |||
if ((res = pthread_create(thread, 0, start_routine, arg))) { | |||
jack_error("Cannot set create thread %d %s", res, strerror(errno)); | |||
return -1; | |||
} | |||
@@ -159,18 +171,25 @@ int JackPosixThread::Stop() | |||
int JackPosixThread::AcquireRealTime() | |||
{ | |||
struct sched_param rtparam; | |||
int res; | |||
return (fThread) ? AcquireRealTimeImp(fThread, fPriority) : -1; | |||
} | |||
if (!fThread) | |||
return -1; | |||
int JackPosixThread::AcquireRealTime(int priority) | |||
{ | |||
fPriority = priority; | |||
return AcquireRealTime(); | |||
} | |||
int JackPosixThread::AcquireRealTimeImp(pthread_t thread, int priority) | |||
{ | |||
struct sched_param rtparam; | |||
int res; | |||
memset(&rtparam, 0, sizeof(rtparam)); | |||
rtparam.sched_priority = fPriority; | |||
rtparam.sched_priority = priority; | |||
//if ((res = pthread_setschedparam(fThread, SCHED_FIFO, &rtparam)) != 0) { | |||
if ((res = pthread_setschedparam(fThread, SCHED_RR, &rtparam)) != 0) { | |||
if ((res = pthread_setschedparam(thread, SCHED_RR, &rtparam)) != 0) { | |||
jack_error("Cannot use real-time scheduling (FIFO/%d) " | |||
"(%d: %s)", rtparam.sched_priority, res, | |||
strerror(res)); | |||
@@ -179,24 +198,19 @@ int JackPosixThread::AcquireRealTime() | |||
return 0; | |||
} | |||
int JackPosixThread::AcquireRealTime(int priority) | |||
int JackPosixThread::DropRealTime() | |||
{ | |||
fPriority = priority; | |||
return AcquireRealTime(); | |||
return (fThread) ? DropRealTimeImp(fThread) : -1; | |||
} | |||
int JackPosixThread::DropRealTime() | |||
int JackPosixThread::DropRealTimeImp(pthread_t thread) | |||
{ | |||
struct sched_param rtparam; | |||
struct sched_param rtparam; | |||
int res; | |||
if (!fThread) | |||
return -1; | |||
memset(&rtparam, 0, sizeof(rtparam)); | |||
rtparam.sched_priority = 0; | |||
if ((res = pthread_setschedparam(fThread, SCHED_OTHER, &rtparam)) != 0) { | |||
if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) { | |||
jack_error("Cannot switch to normal scheduling priority(%s)\n", strerror(errno)); | |||
return -1; | |||
} | |||
@@ -37,7 +37,6 @@ class JackPosixThread : public JackThread | |||
protected: | |||
pthread_t fThread; | |||
static void* ThreadHandler(void* arg); | |||
public: | |||
@@ -65,6 +64,11 @@ class JackPosixThread : public JackThread | |||
virtual int DropRealTime(); | |||
pthread_t GetThreadID(); | |||
static int AcquireRealTimeImp(pthread_t thread, int priority); | |||
static int DropRealTimeImp(pthread_t thread); | |||
static int StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); | |||
}; | |||
} // end of namespace | |||
@@ -2567,7 +2567,7 @@ extern "C" | |||
capture = TRUE; | |||
if (strcmp (param->value.str, "none") != 0) { | |||
capture_pcm_name = strdup (param->value.str); | |||
printf("capture device %s\n", capture_pcm_name); | |||
printf("capture device %s\n", capture_pcm_name); | |||
} | |||
break; | |||
@@ -2575,7 +2575,7 @@ extern "C" | |||
playback = TRUE; | |||
if (strcmp (param->value.str, "none") != 0) { | |||
playback_pcm_name = strdup (param->value.str); | |||
printf("playback device %s\n", playback_pcm_name); | |||
printf("playback device %s\n", playback_pcm_name); | |||
} | |||
break; | |||
@@ -2587,8 +2587,8 @@ extern "C" | |||
case 'd': | |||
playback_pcm_name = strdup (param->value.str); | |||
capture_pcm_name = strdup (param->value.str); | |||
printf("playback device %s\n", playback_pcm_name); | |||
printf("capture device %s\n", capture_pcm_name); | |||
printf("playback device %s\n", playback_pcm_name); | |||
printf("capture device %s\n", capture_pcm_name); | |||
break; | |||
case 'H': | |||
@@ -152,34 +152,33 @@ int JackMachThread::Kill() | |||
} | |||
} | |||
/* | |||
int JackMachThread::AcquireRealTime() | |||
{ | |||
JackLog("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld\n", | |||
long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); | |||
return (fThread) ? SetThreadToPriority(fThread, 96, true, fPeriod, fComputation, fConstraint) : -1; | |||
return (fThread) ? AcquireRealTimeImp(fThread, fPeriod, fComputation, fConstraint) : -1; | |||
} | |||
*/ | |||
int JackMachThread::AcquireRealTime() | |||
int JackMachThread::AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint) | |||
{ | |||
JackLog("JackMachThread::AcquireRealTime fPeriod = %ld fComputation = %ld fConstraint = %ld\n", | |||
long(fPeriod / 1000), long(fComputation / 1000), long(fConstraint / 1000)); | |||
if (fThread) { | |||
SetThreadToPriority(fThread, 96, true, fPeriod, fComputation, fConstraint); | |||
UInt64 fPeriod; | |||
UInt64 fComputation; | |||
UInt64 fConstraint; | |||
GetParams(&fPeriod, &fComputation, &fConstraint); | |||
return 0; | |||
} else | |||
return -1; | |||
SetThreadToPriority(thread, 96, true, period, computation, constraint); | |||
UInt64 int_period; | |||
UInt64 int_computation; | |||
UInt64 int_constraint; | |||
GetParams(&int_period, &int_computation, &int_constraint); | |||
return 0; | |||
} | |||
int JackMachThread::DropRealTime() | |||
{ | |||
//return (fThread) ? SetThreadToPriority(fThread, 31, false, 0, 0, 0) : -1; | |||
return (fThread) ? SetThreadToPriority(fThread, 63, false, 0, 0, 0) : -1; | |||
return (fThread) ? DropRealTimeImp(fThread) : -1; | |||
} | |||
int JackMachThread::DropRealTimeImp(pthread_t thread) | |||
{ | |||
SetThreadToPriority(thread, 63, false, 0, 0, 0); | |||
return 0; | |||
} | |||
void JackMachThread::SetParams(UInt64 period, UInt64 computation, UInt64 constraint) | |||
@@ -114,6 +114,9 @@ class JackMachThread : public JackPosixThread | |||
void SetParams(UInt64 period, UInt64 computation, UInt64 constraint); | |||
static int GetParams(UInt64* period, UInt64* computation, UInt64* constraint); | |||
static int SetThreadToPriority(pthread_t thread, UInt32 inPriority, Boolean inIsFixed, UInt64 period, UInt64 computation, UInt64 constraint); | |||
static int AcquireRealTimeImp(pthread_t thread, UInt64 period, UInt64 computation, UInt64 constraint); | |||
static int DropRealTimeImp(pthread_t thread); | |||
}; | |||
} // end of namespace | |||
@@ -68,98 +68,109 @@ JackWinThread::~JackWinThread() | |||
CloseHandle(fEvent); | |||
} | |||
int JackWinThread::Start() | |||
{ | |||
DWORD id; | |||
fEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | |||
if (fEvent == NULL) { | |||
jack_error("Cannot create event error = %d", GetLastError()); | |||
return -1; | |||
} | |||
fRunning = true; | |||
if (fRealTime) { | |||
JackLog("Create RT thread\n"); | |||
fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id); | |||
if (fThread == NULL) { | |||
jack_error("Cannot create thread error = %d", GetLastError()); | |||
return -1; | |||
} | |||
if (!SetThreadPriority(fThread, THREAD_PRIORITY_TIME_CRITICAL)) { | |||
jack_error("Cannot set priority class = %d", GetLastError()); | |||
return -1; | |||
} | |||
return 0; | |||
} else { | |||
JackLog("Create non RT thread\n"); | |||
fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id); | |||
if (fThread == NULL) { | |||
jack_error("Cannot create thread error = %d", GetLastError()); | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
} | |||
int JackWinThread::StartSync() | |||
{ | |||
DWORD id; | |||
fEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | |||
if (fEvent == NULL) { | |||
jack_error("Cannot create event error = %d", GetLastError()); | |||
return -1; | |||
} | |||
if (fRealTime) { | |||
JackLog("Create RT thread\n"); | |||
fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id); | |||
if (fThread == NULL) { | |||
jack_error("Cannot create thread error = %d", GetLastError()); | |||
return -1; | |||
} | |||
if (WaitForSingleObject(fEvent, 3000) != WAIT_OBJECT_0) { // wait 3 sec | |||
jack_error("Thread has not started"); | |||
return -1; | |||
} | |||
if (!SetThreadPriority(fThread, THREAD_PRIORITY_TIME_CRITICAL)) { | |||
jack_error("Cannot set priority class = %d", GetLastError()); | |||
return -1; | |||
} | |||
return 0; | |||
} else { | |||
JackLog("Create non RT thread\n"); | |||
fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id); | |||
if (fThread == NULL) { | |||
jack_error("Cannot create thread error = %d", GetLastError()); | |||
return -1; | |||
} | |||
if (WaitForSingleObject(fEvent, 3000) != WAIT_OBJECT_0) { // wait 3 sec | |||
jack_error("Thread has not started"); | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
int JackWinThread::Start() | |||
{ | |||
fEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | |||
if (fEvent == NULL) { | |||
jack_error("Cannot create event error = %d", GetLastError()); | |||
return -1; | |||
} | |||
fRunning = true; | |||
// Check if the thread was correctly started | |||
if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { | |||
fRunning = false; | |||
return -1; | |||
} else { | |||
return 0; | |||
} | |||
} | |||
int JackWinThread::StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); | |||
{ | |||
DWORD id; | |||
if (realtime) { | |||
JackLog("Create RT thread\n"); | |||
*thread = CreateThread(NULL, 0, start_routine, arg, 0, &id); | |||
if (*thread == NULL) { | |||
jack_error("Cannot create thread error = %d", GetLastError()); | |||
return -1; | |||
} | |||
if (!SetThreadPriority(*thread, THREAD_PRIORITY_TIME_CRITICAL)) { | |||
jack_error("Cannot set priority class = %d", GetLastError()); | |||
return -1; | |||
} | |||
return 0; | |||
} else { | |||
JackLog("Create non RT thread\n"); | |||
*thread = CreateThread(NULL, 0, start_routine, arg, 0, &id); | |||
if (fThread == NULL) { | |||
jack_error("Cannot create thread error = %d", GetLastError()); | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
} | |||
int JackWinThread::StartSync() | |||
{ | |||
DWORD id; | |||
fEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | |||
if (fEvent == NULL) { | |||
jack_error("Cannot create event error = %d", GetLastError()); | |||
return -1; | |||
} | |||
if (fRealTime) { | |||
JackLog("Create RT thread\n"); | |||
fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id); | |||
if (fThread == NULL) { | |||
jack_error("Cannot create thread error = %d", GetLastError()); | |||
return -1; | |||
} | |||
if (WaitForSingleObject(fEvent, 3000) != WAIT_OBJECT_0) { // wait 3 sec | |||
jack_error("Thread has not started"); | |||
return -1; | |||
} | |||
if (!SetThreadPriority(fThread, THREAD_PRIORITY_TIME_CRITICAL)) { | |||
jack_error("Cannot set priority class = %d", GetLastError()); | |||
return -1; | |||
} | |||
return 0; | |||
} else { | |||
JackLog("Create non RT thread\n"); | |||
fThread = CreateThread(NULL, 0, ThreadHandler, (void*)this, 0, &id); | |||
if (fThread == NULL) { | |||
jack_error("Cannot create thread error = %d", GetLastError()); | |||
return -1; | |||
} | |||
if (WaitForSingleObject(fEvent, 3000) != WAIT_OBJECT_0) { // wait 3 sec | |||
jack_error("Thread has not started"); | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
} | |||
// voir http://www.microsoft.com/belux/msdn/nl/community/columns/ldoc/multithread1.mspx | |||
@@ -167,9 +178,9 @@ int JackWinThread::StartSync() | |||
int JackWinThread::Kill() | |||
{ | |||
if (fThread) { // If thread has been started | |||
TerminateThread(fThread, 0); | |||
TerminateThread(fThread, 0); | |||
WaitForSingleObject(fThread, INFINITE); | |||
CloseHandle(fThread); | |||
CloseHandle(fThread); | |||
JackLog("JackWinThread::Kill 2\n"); | |||
fThread = NULL; | |||
fRunning = false; | |||
@@ -195,6 +206,7 @@ int JackWinThread::Stop() | |||
int JackWinThread::AcquireRealTime() | |||
{ | |||
/* | |||
JackLog("JackWinThread::AcquireRealTime\n"); | |||
if (fThread) { | |||
@@ -207,14 +219,33 @@ int JackWinThread::AcquireRealTime() | |||
} else { | |||
return -1; | |||
} | |||
*/ | |||
return (fThread) ? AcquireRealTimeImp(fThread, fPriority) : -1; | |||
} | |||
int JackWinThread::AcquireRealTime(int priority) | |||
{ | |||
JackLog("JackWinThread::AcquireRealTime priority = %ld\n", priority); | |||
return AcquireRealTime(); | |||
//JackLog("JackWinThread::AcquireRealTime priority = %ld\n", priority); | |||
//return AcquireRealTime(); | |||
fPriority = priority; | |||
return AcquireRealTime(); | |||
} | |||
int JackWinThread::AcquireRealTimeImp(pthread_t thread, int priority) | |||
{ | |||
JackLog("JackWinThread::AcquireRealTime\n"); | |||
if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) { | |||
JackLog("JackWinThread::AcquireRealTime OK\n"); | |||
return 0; | |||
} else { | |||
jack_error("Cannot set thread priority = %d", GetLastError()); | |||
return -1; | |||
} | |||
} | |||
/* | |||
int JackWinThread::DropRealTime() | |||
{ | |||
if (fThread) { | |||
@@ -227,6 +258,21 @@ int JackWinThread::DropRealTime() | |||
return -1; | |||
} | |||
} | |||
*/ | |||
int JackWinThread::DropRealTime() | |||
{ | |||
return DropRealTime(fThread); | |||
} | |||
int JackWinThread::DropRealTime(pthread_t thread) | |||
{ | |||
if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) { | |||
return 0; | |||
} else { | |||
jack_error("Cannot set thread priority = %d", GetLastError()); | |||
return -1; | |||
} | |||
} | |||
pthread_t JackWinThread::GetThreadID() | |||
{ | |||
@@ -57,6 +57,11 @@ class JackWinThread : public JackThread | |||
int DropRealTime(); | |||
pthread_t GetThreadID(); | |||
static int AcquireRealTimeImp(pthread_t thread, int priority); | |||
static int DropRealTimeImp(pthread_t thread); | |||
static int StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); | |||
}; | |||
} // end of namespace | |||