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