JackPosixThread.cpp

00001 /*
00002 Copyright (C) 2001 Paul Davis 
00003 Copyright (C) 2004-2006 Grame
00004 
00005 This program is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019 */
00020 
00021 #include "JackPosixThread.h"
00022 #include "JackError.h"
00023 #include <string.h> // for memset
00024 
00025 namespace Jack
00026 {
00027 
00028 void* JackPosixThread::ThreadHandler(void* arg)
00029 {
00030     JackPosixThread* obj = (JackPosixThread*)arg;
00031     JackRunnableInterface* runnable = obj->fRunnable;
00032     int err;
00033 
00034     if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) {
00035         jack_error("pthread_setcanceltype err = %s", strerror(err));
00036     }
00037 
00038     // Call Init method
00039     if (!runnable->Init()) {
00040         jack_error("Thread init fails: thread quits");
00041         return 0;
00042     }
00043 
00044     JackLog("ThreadHandler: start\n");
00045 
00046         // If Init succeed, start the thread loop
00047         bool res = true;
00048     while (obj->fRunning && res) {
00049         res = runnable->Execute();
00050         //pthread_testcancel();
00051     }
00052 
00053     JackLog("ThreadHandler: exit\n");
00054     return 0;
00055 }
00056 
00057 int JackPosixThread::Start()
00058 {
00059     int res;
00060     fRunning = true;
00061 
00062     if (fRealTime) {
00063 
00064         JackLog("Create RT thread\n");
00065 
00066         /* Get the client thread to run as an RT-FIFO
00067            scheduled thread of appropriate priority.
00068         */
00069         pthread_attr_t attributes;
00070         struct sched_param rt_param;
00071         pthread_attr_init(&attributes);
00072                 
00073                 if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) {
00074             jack_error("Cannot request explicit scheduling for RT thread  %d %s", res, strerror(errno));
00075             return -1;
00076         }
00077                 
00078         if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
00079             jack_error("Cannot request joinable thread creation for RT thread  %d %s", res, strerror(errno));
00080             return -1;
00081         }
00082                 
00083         if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
00084             jack_error("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
00085             return -1;
00086         }
00087 
00088         //if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO))) {
00089 
00090         if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_RR))) {
00091             jack_error("Cannot set FIFO scheduling class for RT thread  %d %s", res, strerror(errno));
00092             return -1;
00093         }
00094 
00095         if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
00096             jack_error("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
00097             return -1;
00098         }
00099 
00100         memset(&rt_param, 0, sizeof(rt_param));
00101         rt_param.sched_priority = fPriority;
00102 
00103         if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
00104             jack_error("Cannot set scheduling priority for RT thread %d %s", res, strerror(errno));
00105             return -1;
00106         }
00107 
00108         if ((res = pthread_create(&fThread, &attributes, ThreadHandler, this))) {
00109             jack_error("Cannot set create thread %d %s", res, strerror(errno));
00110             return -1;
00111         }
00112 
00113         return 0;
00114     } else {
00115         JackLog("Create non RT thread\n");
00116 
00117         if ((res = pthread_create(&fThread, 0, ThreadHandler, this))) {
00118             jack_error("Cannot set create thread %d %s", res, strerror(errno));
00119             return -1;
00120         }
00121         return 0;
00122     }
00123 }
00124 
00125 int JackPosixThread::StartSync()
00126 {
00127     jack_error("Not implemented yet");
00128     return -1;
00129 }
00130 
00131 int JackPosixThread::Kill()
00132 {
00133     if (fThread) { // If thread has been started
00134         JackLog("JackPosixThread::Kill\n");
00135         void* status;
00136         pthread_cancel(fThread);
00137         pthread_join(fThread, &status);
00138                 fRunning = false; 
00139                 fThread = (pthread_t)NULL;
00140         return 0;
00141     } else {
00142         return -1;
00143     }
00144 }
00145 
00146 int JackPosixThread::Stop()
00147 {
00148     if (fThread) { // If thread has been started
00149         JackLog("JackPosixThread::Stop\n");
00150         void* status;
00151         fRunning = false; // Request for the thread to stop
00152         pthread_join(fThread, &status);
00153                 fThread = (pthread_t)NULL;
00154         return 0;
00155     } else {
00156         return -1;
00157     }
00158 }
00159 
00160 int JackPosixThread::AcquireRealTime()
00161 {
00162     struct sched_param rtparam;
00163     int res;
00164 
00165     if (!fThread)
00166         return -1;
00167 
00168     memset(&rtparam, 0, sizeof(rtparam));
00169     rtparam.sched_priority = fPriority;
00170 
00171     //if ((res = pthread_setschedparam(fThread, SCHED_FIFO, &rtparam)) != 0) {
00172 
00173     if ((res = pthread_setschedparam(fThread, SCHED_RR, &rtparam)) != 0) {
00174         jack_error("Cannot use real-time scheduling (FIFO/%d) "
00175                    "(%d: %s)", rtparam.sched_priority, res,
00176                    strerror(res));
00177         return -1;
00178     }
00179     return 0;
00180 }
00181 
00182 int JackPosixThread::AcquireRealTime(int priority)
00183 {
00184     fPriority = priority;
00185     return AcquireRealTime();
00186 }
00187 
00188 int JackPosixThread::DropRealTime()
00189 {
00190     struct sched_param rtparam;
00191     int res;
00192 
00193     if (!fThread)
00194         return -1;
00195 
00196     memset(&rtparam, 0, sizeof(rtparam));
00197     rtparam.sched_priority = 0;
00198 
00199     if ((res = pthread_setschedparam(fThread, SCHED_OTHER, &rtparam)) != 0) {
00200         jack_error("Cannot switch to normal scheduling priority(%s)\n", strerror(errno));
00201         return -1;
00202     }
00203     return 0;
00204 }
00205 
00206 pthread_t JackPosixThread::GetThreadID()
00207 {
00208     return fThread;
00209 }
00210 
00211 } // end of namespace
00212 

Generated on Wed Jan 10 11:42:46 2007 for Jackdmp by  doxygen 1.4.5