JackPosixThread.cpp

00001 /*
00002 Copyright (C) 2001 Paul Davis 
00003 Copyright (C) 2004-2008 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     }
00051 
00052     JackLog("ThreadHandler: exit\n");
00053     return 0;
00054 }
00055 
00056 int JackPosixThread::Start()
00057 {
00058         fRunning = true;
00059         
00060         // Check if the thread was correctly started
00061         if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { 
00062                 fRunning = false;
00063                 return -1;
00064         } else {
00065                 return 0;
00066         }
00067 }
00068 
00069 int JackPosixThread::StartImp(pthread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg)
00070 {
00071     int res;
00072  
00073     if (realtime) {
00074 
00075         JackLog("Create RT thread\n");
00076 
00077         /* Get the client thread to run as an RT-FIFO
00078            scheduled thread of appropriate priority.
00079         */
00080         pthread_attr_t attributes;
00081         struct sched_param rt_param;
00082         pthread_attr_init(&attributes);
00083                 
00084                 if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) {
00085             jack_error("Cannot request explicit scheduling for RT thread  %d %s", res, strerror(errno));
00086             return -1;
00087         }
00088                 
00089         if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
00090             jack_error("Cannot request joinable thread creation for RT thread  %d %s", res, strerror(errno));
00091             return -1;
00092         }
00093                 
00094         if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
00095             jack_error("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
00096             return -1;
00097         }
00098 
00099         //if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO))) {
00100 
00101         if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_RR))) {
00102             jack_error("Cannot set FIFO scheduling class for RT thread  %d %s", res, strerror(errno));
00103             return -1;
00104         }
00105 
00106         if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
00107             jack_error("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
00108             return -1;
00109         }
00110 
00111         memset(&rt_param, 0, sizeof(rt_param));
00112         rt_param.sched_priority = priority;
00113 
00114         if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
00115             jack_error("Cannot set scheduling priority for RT thread %d %s", res, strerror(errno));
00116             return -1;
00117         }
00118                 
00119            if ((res = pthread_attr_setstacksize(&attributes, THREAD_STACK))) {
00120                         jack_error("setting thread stack size%d %s", res, strerror(errno));
00121                         return -1;
00122         }
00123 
00124         if ((res = pthread_create(thread, &attributes, start_routine, arg))) {
00125             jack_error("Cannot set create thread %d %s", res, strerror(errno));
00126             return -1;
00127         }
00128 
00129         return 0;
00130     } else {
00131         JackLog("Create non RT thread\n");
00132 
00133         if ((res = pthread_create(thread, 0, start_routine, arg))) {
00134             jack_error("Cannot set create thread %d %s", res, strerror(errno));
00135             return -1;
00136         }
00137         return 0;
00138     }
00139 }
00140 
00141 int JackPosixThread::StartSync()
00142 {
00143     jack_error("Not implemented yet");
00144     return -1;
00145 }
00146 
00147 int JackPosixThread::Kill()
00148 {
00149     if (fThread) { // If thread has been started
00150         JackLog("JackPosixThread::Kill\n");
00151         void* status;
00152         pthread_cancel(fThread);
00153         pthread_join(fThread, &status);
00154                 fRunning = false; 
00155                 fThread = (pthread_t)NULL;
00156         return 0;
00157     } else {
00158         return -1;
00159     }
00160 }
00161 
00162 int JackPosixThread::Stop()
00163 {
00164     if (fThread) { // If thread has been started
00165         JackLog("JackPosixThread::Stop\n");
00166         void* status;
00167         fRunning = false; // Request for the thread to stop
00168         pthread_join(fThread, &status);
00169                 fThread = (pthread_t)NULL;
00170         return 0;
00171     } else {
00172         return -1;
00173     }
00174 }
00175 
00176 int JackPosixThread::AcquireRealTime()
00177 {
00178         return (fThread) ? AcquireRealTimeImp(fThread, fPriority) : -1;
00179 }
00180 
00181 int JackPosixThread::AcquireRealTime(int priority)
00182 {
00183         fPriority = priority;
00184     return AcquireRealTime();
00185 }
00186 
00187 int JackPosixThread::AcquireRealTimeImp(pthread_t thread, int priority)
00188 {
00189    struct sched_param rtparam;
00190     int res;
00191     memset(&rtparam, 0, sizeof(rtparam));
00192     rtparam.sched_priority = priority;
00193 
00194     //if ((res = pthread_setschedparam(fThread, SCHED_FIFO, &rtparam)) != 0) {
00195 
00196     if ((res = pthread_setschedparam(thread, SCHED_RR, &rtparam)) != 0) {
00197         jack_error("Cannot use real-time scheduling (FIFO/%d) "
00198                    "(%d: %s)", rtparam.sched_priority, res,
00199                    strerror(res));
00200         return -1;
00201     }
00202     return 0;
00203 }
00204 
00205 int JackPosixThread::DropRealTime()
00206 {
00207     return (fThread) ? DropRealTimeImp(fThread) : -1;
00208 }
00209 
00210 int JackPosixThread::DropRealTimeImp(pthread_t thread)
00211 {
00212         struct sched_param rtparam;
00213     int res;
00214     memset(&rtparam, 0, sizeof(rtparam));
00215     rtparam.sched_priority = 0;
00216 
00217     if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) {
00218         jack_error("Cannot switch to normal scheduling priority(%s)\n", strerror(errno));
00219         return -1;
00220     }
00221     return 0;
00222 }
00223 
00224 pthread_t JackPosixThread::GetThreadID()
00225 {
00226     return fThread;
00227 }
00228 
00229 void JackPosixThread::Terminate()
00230 {
00231         JackLog("JackPosixThread::Terminate\n");
00232         pthread_exit(0);
00233 }
00234 
00235 } // end of namespace
00236 

Generated on Thu Feb 14 11:16:02 2008 for Jackdmp by  doxygen 1.5.1