root/trunk/libfreebob/src/libfreebobstreaming/thread.c

Revision 159, 5.2 kB (checked in by pieterpalmers, 18 years ago)

- Added streaming API
- Added test programs for the streaming API

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*
2
3   Modifications for FreeBoB by Pieter Palmers
4  
5   Capabilities code removed
6  
7   Copied from the jackd sources
8   function names changed in order to avoid naming problems when using this in
9   a jackd backend.
10  
11   Copyright (C) 2004 Paul Davis
12  
13   This program is free software; you can redistribute it and/or modify
14   it under the terms of the GNU Lesser General Public License as published by
15   the Free Software Foundation; either version 2.1 of the License, or
16   (at your option) any later version.
17
18   This program is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU Lesser General Public License for more details.
22
23   You should have received a copy of the GNU Lesser General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26
27   Thread creation function including workarounds for real-time scheduling
28   behaviour on different glibc versions.
29
30   $Id$
31
32 */
33
34 #include <config.h>
35
36 //#define DEBUG
37 #include "freebob_debug.h"
38 #include "libfreebob/freebob_streaming.h"
39
40 //#include <jack/jack.h>
41 #include <thread.h>
42 //#include <jack/internal.h>
43
44 #include <pthread.h>
45 #include <sched.h>
46 #include <stdio.h>
47 #include <string.h>
48 #include <errno.h>
49
50 // #include "local.h"
51
52 #ifdef FREEBOB_USE_MACH_THREADS
53 #include <sysdeps/pThreadUtilities.h>
54 #endif
55
56 static inline void
57 log_result (char *msg, int res)
58 {
59         char outbuf[500];
60         snprintf(outbuf, sizeof(outbuf),
61                  "freebob_create_thread: error %d %s: %s",
62                  res, msg, strerror(res));
63         printMessage("%s",outbuf);
64 }
65
66 static void*
67 freebob_thread_proxy (void* varg)
68 {
69         freebob_thread_arg_t* arg = (freebob_thread_arg_t*) varg;
70         void* (*work)(void*);
71         void* warg;
72 //      freebob_device_t* dev = arg->device;
73
74         if (arg->realtime) {
75                 freebob_acquire_real_time_scheduling (pthread_self(), arg->priority);
76         }
77
78         warg = arg->arg;
79         work = arg->work_function;
80
81         free (arg);
82        
83         return work (warg);
84 }
85
86 int
87 freebob_streaming_create_thread (freebob_device_t* dev,
88                            pthread_t* thread,
89                            int priority,
90                            int realtime,
91                            void*(*start_routine)(void*),
92                            void* arg)
93 {
94 #ifndef FREEBOB_USE_MACH_THREADS
95         pthread_attr_t attr;
96         freebob_thread_arg_t* thread_args;
97 #endif /* !FREEBOB_USE_MACH_THREADS */
98
99         int result = 0;
100
101         if (!realtime) {
102                 result = pthread_create (thread, 0, start_routine, arg);
103                 if (result) {
104                         log_result("creating thread with default parameters",
105                                    result);
106                 }
107                 return result;
108         }
109
110         /* realtime thread. this disgusting mess is a reflection of
111          * the 2nd-class nature of RT programming under POSIX in
112          * general and Linux in particular.
113          */
114
115 #ifndef FREEBOB_USE_MACH_THREADS
116
117         pthread_attr_init(&attr);
118         result = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED);
119         if (result) {
120                 log_result("requesting explicit scheduling", result);
121                 return result;
122         }
123         result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
124         if (result) {
125                 log_result("requesting joinable thread creation", result);
126                 return result;
127         }
128         result = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
129         if (result) {
130                 log_result("requesting system scheduling scope", result);
131                 return result;
132         }
133
134         thread_args = (freebob_thread_arg_t *) malloc (sizeof (freebob_thread_arg_t));
135
136         thread_args->device = dev;
137         thread_args->work_function = start_routine;
138         thread_args->arg = arg;
139         thread_args->realtime = 1;
140         thread_args->priority = priority;
141
142         result = pthread_create (thread, &attr, freebob_thread_proxy, thread_args);
143         if (result) {
144                 log_result ("creating realtime thread", result);
145                 return result;
146         }
147
148 #else /* FREEBOB_USE_MACH_THREADS */
149
150         result = pthread_create (thread, 0, start_routine, arg);
151         if (result) {
152                 log_result ("creating realtime thread", result);
153                 return result;
154         }
155
156         /* time constraint thread */
157         setThreadToPriority (*thread, 96, TRUE, 10000000);
158        
159 #endif /* FREEBOB_USE_MACH_THREADS */
160
161         return 0;
162 }
163
164 #if FREEBOB_USE_MACH_THREADS
165
166 int
167 freebob_drop_real_time_scheduling (pthread_t thread)
168 {
169         setThreadToPriority(thread, 31, FALSE, 10000000);
170         return 0;       
171 }
172
173 int
174 freebob_acquire_real_time_scheduling (pthread_t thread, int priority)
175         //priority is unused
176 {
177         setThreadToPriority(thread, 96, TRUE, 10000000);
178         return 0;
179 }
180
181 #else /* !FREEBOB_USE_MACH_THREADS */
182
183 int
184 freebob_drop_real_time_scheduling (pthread_t thread)
185 {
186         struct sched_param rtparam;
187         int x;
188        
189         memset (&rtparam, 0, sizeof (rtparam));
190         rtparam.sched_priority = 0;
191
192         if ((x = pthread_setschedparam (thread, SCHED_OTHER, &rtparam)) != 0) {
193                 printError ("cannot switch to normal scheduling priority(%s)\n",
194                             strerror (errno));
195                 return -1;
196         }
197         return 0;
198 }
199
200 int
201 freebob_acquire_real_time_scheduling (pthread_t thread, int priority)
202 {
203         struct sched_param rtparam;
204         int x;
205        
206         memset (&rtparam, 0, sizeof (rtparam));
207         rtparam.sched_priority = priority;
208        
209         if ((x = pthread_setschedparam (thread, SCHED_FIFO, &rtparam)) != 0) {
210                 printError ("cannot use real-time scheduling (FIFO at priority %d) "
211                             "[for thread %d, from thread %d] (%d: %s)",
212                             rtparam.sched_priority,
213                             (int)thread, (int)pthread_self(),
214                             x, strerror (x));
215                 return -1;
216         }
217
218         return 0;
219 }
220
221 #endif /* FREEBOB_USE_MACH_THREADS */
222
Note: See TracBrowser for help on using the browser.