root/trunk/libffado/src/libutil/PosixThread.cpp

Revision 750, 6.7 kB (checked in by ppalmers, 16 years ago)

Code refactoring. Tries to simplify things and tries to put all code where it belongs.

Line 
1 /*
2  * Copyright (C) 2005-2007 by Pieter Palmers
3  *
4  * This file is part of FFADO
5  * FFADO = Free Firewire (pro-)audio drivers for linux
6  *
7  * FFADO is based upon FreeBoB
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 /*
25  * Copied from the jackd/jackdmp sources
26  * function names changed in order to avoid naming problems when using this in
27  * a jackd backend.
28  */
29
30 /* Original license:
31  * Copyright (C) 2001 Paul Davis
32  * Copyright (C) 2004-2006 Grame
33  *
34  * this program is free software; you can redistribute it and/or modify
35  * it under the terms of the GNU General Public License as published by
36  * the Free Software Foundation; either version 2 of the License, or
37  * (at your option) any later version.
38  *
39  * This program is distributed in the hope that it will be useful,
40  * but WITHOUT ANY WARRANTY; without even the implied warranty of
41  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42  * GNU General Public License for more details.
43  *
44  * You should have received a copy of the GNU General Public License
45  * along with this program; if not, write to the Free Software
46  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
47  *
48  */
49
50 #include "PosixThread.h"
51 #include <string.h> // for memset
52 #include <errno.h>
53 #include <assert.h>
54
55 namespace Util
56 {
57
58 IMPL_DEBUG_MODULE( Thread, Thread, DEBUG_LEVEL_VERBOSE );
59
60 void* PosixThread::ThreadHandler(void* arg)
61 {
62     PosixThread* obj = (PosixThread*)arg;
63     RunnableInterface* runnable = obj->fRunnable;
64     int err;
65
66     if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) {
67         debugError("pthread_setcanceltype err = %s", strerror(err));
68     }
69
70     // Call Init method
71     if (!runnable->Init()) {
72         debugError("Thread init fails: thread quits");
73         return 0;
74     }
75
76     debugOutput( DEBUG_LEVEL_VERBOSE, "ThreadHandler: start %p\n", obj);
77
78     // If Init succeed start the thread loop
79     bool res = true;
80     while (obj->fRunning && res) {
81         res = runnable->Execute();
82         //pthread_testcancel();
83     }
84
85     debugOutput( DEBUG_LEVEL_VERBOSE, "ThreadHandler: exit %p\n", obj);
86     return 0;
87 }
88
89 int PosixThread::Start()
90 {
91     int res;
92     fRunning = true;
93
94     if (fRealTime) {
95
96         debugOutput( DEBUG_LEVEL_VERBOSE, "Create RT thread %p with priority %d\n", this, fPriority);
97
98         /* Get the client thread to run as an RT-FIFO
99            scheduled thread of appropriate priority.
100         */
101         pthread_attr_t attributes;
102         struct sched_param rt_param;
103         pthread_attr_init(&attributes);
104
105         if ((res = pthread_attr_setinheritsched(&attributes, PTHREAD_EXPLICIT_SCHED))) {
106             debugError("Cannot request explicit scheduling for RT thread  %d %s", res, strerror(errno));
107             return -1;
108         }
109         if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
110             debugError("Cannot request joinable thread creation for RT thread  %d %s", res, strerror(errno));
111             return -1;
112         }
113         if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
114             debugError("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno));
115             return -1;
116         }
117
118         if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO))) {
119
120         //if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_RR))) {
121             debugError("Cannot set FIFO scheduling class for RT thread  %d %s", res, strerror(errno));
122             return -1;
123         }
124
125         memset(&rt_param, 0, sizeof(rt_param));
126         rt_param.sched_priority = fPriority;
127
128         if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
129             debugError("Cannot set scheduling priority for RT thread %d %s", res, strerror(errno));
130             return -1;
131         }
132
133         if ((res = pthread_create(&fThread, &attributes, ThreadHandler, this))) {
134             debugError("Cannot set create thread %d %s", res, strerror(errno));
135             return -1;
136         }
137
138         return 0;
139     } else {
140         debugOutput( DEBUG_LEVEL_VERBOSE, "Create non RT thread %p\n", this);
141
142         if ((res = pthread_create(&fThread, 0, ThreadHandler, this))) {
143             debugError("Cannot set create thread %d %s", res, strerror(errno));
144             return -1;
145         }
146
147         return 0;
148     }
149 }
150
151 int PosixThread::Kill()
152 {
153     if (fThread) { // If thread has been started
154         debugOutput( DEBUG_LEVEL_VERBOSE, "PosixThread::Kill %p\n", this);
155         void* status;
156         pthread_cancel(fThread);
157         pthread_join(fThread, &status);
158         debugOutput( DEBUG_LEVEL_VERBOSE, "PosixThread::Killed %p\n", this);
159         return 0;
160     } else {
161         return -1;
162     }
163 }
164
165 int PosixThread::Stop()
166 {
167     if (fThread) { // If thread has been started
168         debugOutput( DEBUG_LEVEL_VERBOSE, "PosixThread::Stop %p\n", this);
169         void* status;
170         fRunning = false; // Request for the thread to stop
171         pthread_join(fThread, &status);
172         debugOutput( DEBUG_LEVEL_VERBOSE, "PosixThread::Stopped %p\n", this);
173         return 0;
174     } else {
175         return -1;
176     }
177 }
178
179 int PosixThread::AcquireRealTime()
180 {
181     struct sched_param rtparam;
182     int res;
183
184     if (!fThread)
185         return -1;
186
187     memset(&rtparam, 0, sizeof(rtparam));
188     rtparam.sched_priority = fPriority;
189
190     //if ((res = pthread_setschedparam(fThread, SCHED_FIFO, &rtparam)) != 0) {
191
192     if ((res = pthread_setschedparam(fThread, SCHED_FIFO, &rtparam)) != 0) {
193         debugError("Cannot use real-time scheduling (FIFO/%d) "
194                    "(%d: %s)", rtparam.sched_priority, res,
195                    strerror(res));
196         return -1;
197     }
198     return 0;
199 }
200
201 int PosixThread::AcquireRealTime(int priority)
202 {
203     fPriority = priority;
204     return AcquireRealTime();
205 }
206
207 int PosixThread::DropRealTime()
208 {
209     struct sched_param rtparam;
210     int res;
211
212     if (!fThread)
213         return -1;
214
215     memset(&rtparam, 0, sizeof(rtparam));
216     rtparam.sched_priority = 0;
217
218     if ((res = pthread_setschedparam(fThread, SCHED_OTHER, &rtparam)) != 0) {
219         debugError("Cannot switch to normal scheduling priority(%s)\n", strerror(errno));
220         return -1;
221     }
222     return 0;
223 }
224
225 pthread_t PosixThread::GetThreadID()
226 {
227     return fThread;
228 }
229
230 } // end of namespace
231
Note: See TracBrowser for help on using the browser.