root/trunk/libffado/src/libieee1394/IsoHandlerManager.h

Revision 1005, 7.2 kB (checked in by ppalmers, 13 years ago)

Improve thread synchronisation. Switch back to separate threads for transmit and
receive since it is not possible to statically schedule things properly. One
of the threads (i.e. the client thread) is out of our control, hence it's
execution can't be controlled. Using separate threads and correct priorities
will shift this problem to the OS. Note that the priority of the packet
receive thread should be lower than the client thread (such that the client
thread is woken ASAP), and the priority of the transmit thread should be
higher than the client thread (such that packets are queued ASAP).
Extra benefit: multi-cores are used.

Some other startup improvements.

Line 
1 /*
2  * Copyright (C) 2005-2008 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 2 of the License, or
12  * (at your option) version 3 of the License.
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 #ifndef __FFADO_ISOHANDLERMANAGER__
25 #define __FFADO_ISOHANDLERMANAGER__
26
27 #include "config.h"
28 #include "debugmodule/debugmodule.h"
29
30 #include "libutil/Thread.h"
31
32 #include "IsoHandler.h"
33
34 #include <sys/poll.h>
35 #include <errno.h>
36 #include <vector>
37 #include <semaphore.h>
38
39 class Ieee1394Service;
40 //class IsoHandler;
41 //enum IsoHandler::EHandlerType;
42
43 namespace Streaming {
44     class StreamProcessor;
45     class StreamProcessorManager;
46     typedef std::vector<StreamProcessor *> StreamProcessorVector;
47     typedef std::vector<StreamProcessor *>::iterator StreamProcessorVectorIterator;
48 }
49
50 typedef std::vector<IsoHandler *> IsoHandlerVector;
51 typedef std::vector<IsoHandler *>::iterator IsoHandlerVectorIterator;
52
53 class IsoHandlerManager;
54
55 // threads that will handle the packet framing
56 // one thread per direction, as a compromise for one per
57 // channel and one for all
58 class IsoTask : public Util::RunnableInterface
59 {
60     public:
61         IsoTask(IsoHandlerManager& manager, enum IsoHandler::EHandlerType);
62         virtual ~IsoTask();
63
64     public:
65         bool Init();
66         bool Execute();
67
68         /**
69          * @brief requests the thread to sync it's stream map with the manager
70          */
71         bool requestShadowMapUpdate();
72         enum eActivityResult {
73             eAR_Activity,
74             eAR_Timeout,
75             eAR_Interrupted,
76             eAR_Error
77         };
78
79         /**
80          * @brief signals that something happened in one of the clients of this task
81          */
82         void signalActivity();
83         /**
84          * @brief wait until something happened in one of the clients of this task
85          */
86         enum eActivityResult waitForActivity();
87
88         void setVerboseLevel(int i);
89     protected:
90         IsoHandlerManager& m_manager;
91
92         // the event request structure
93         SInt32 request_update;
94
95         // static allocation due to RT constraints
96         // this is the map used by the actual thread
97         // it is a shadow of the m_StreamProcessors vector
98         struct pollfd   m_poll_fds_shadow[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT];
99         IsoHandler *    m_IsoHandler_map_shadow[ISOHANDLERMANAGER_MAX_ISO_HANDLERS_PER_PORT];
100         unsigned int    m_poll_nfds_shadow;
101         IsoHandler *    m_SyncIsoHandler;
102
103         // updates the streams map
104         void updateShadowMapHelper();
105
106 #ifdef DEBUG
107         uint64_t m_last_loop_entry;
108         int m_successive_short_loops;
109 #endif
110
111         // activity signaling
112         sem_t m_activity_semaphore;
113
114         enum IsoHandler::EHandlerType m_handlerType;
115         // debug stuff
116         DECLARE_DEBUG_MODULE;
117 };
118
119 /*!
120 \brief The ISO Handler management class
121
122  This class manages the use of ISO handlers by ISO streams.
123  You can register an Streaming::StreamProcessor with an IsoHandlerManager. This
124  manager will assign an IsoHandler to the stream. If nescessary
125  the manager allocates a new handler. If there is already a handler
126  that can handle the Streaming::StreamProcessor (e.g. in case of multichannel receive),
127  it can be assigned.
128
129 */
130
131 class IsoHandlerManager
132 {
133     friend class IsoTask;
134
135     public:
136
137         IsoHandlerManager(Ieee1394Service& service);
138         IsoHandlerManager(Ieee1394Service& service, bool run_rt, int rt_prio);
139         virtual ~IsoHandlerManager();
140
141         bool setThreadParameters(bool rt, int priority);
142
143         void setVerboseLevel(int l); ///< set the verbose level
144
145         void dumpInfo(); ///< print some information about the manager to stdout/stderr
146
147         bool registerStream(Streaming::StreamProcessor *); ///< register an iso stream with the manager
148         bool unregisterStream(Streaming::StreamProcessor *); ///< unregister an iso stream from the manager
149
150         bool startHandlers(); ///< start the managed ISO handlers
151         bool startHandlers(int cycle); ///< start the managed ISO handlers
152         bool stopHandlers(); ///< stop the managed ISO handlers
153
154         bool reset(); ///< reset the ISO manager and all streams
155         bool init();
156
157         bool disable(IsoHandler *); ///< disables a handler
158         bool enable(IsoHandler *); ///< enables a handler
159
160         /**
161          * @brief signals that something happened in one of the clients
162          */
163         void signalActivityTransmit();
164         void signalActivityReceive();
165
166         ///> disables the handler attached to the stream
167         bool stopHandlerForStream(Streaming::StreamProcessor *);
168         ///> starts the handler attached to the specific stream
169         bool startHandlerForStream(Streaming::StreamProcessor *);
170         ///> starts the handler attached to the specific stream on a specific cycle
171         bool startHandlerForStream(Streaming::StreamProcessor *, int cycle);
172
173         /**
174          * returns the latency of a wake-up for this stream.
175          * The latency is the time it takes for a packet is delivered to the
176          * stream after it has been received (was on the wire).
177          * expressed in cycles
178          */
179         int getPacketLatencyForStream(Streaming::StreamProcessor *);
180
181         void flushHandlerForStream(Streaming::StreamProcessor *stream);
182
183         Ieee1394Service& get1394Service() {return m_service;};
184
185         void requestShadowMapUpdate();
186
187     // the state machine
188     private:
189         enum eHandlerStates {
190             E_Created,
191             E_Prepared,
192             E_Running,
193             E_Error
194         };
195
196         enum eHandlerStates m_State;
197         const char *eHSToString(enum eHandlerStates);
198
199     private:
200         Ieee1394Service&  m_service;
201         // note: there is a disctinction between streams and handlers
202         // because one handler can serve multiple streams (in case of
203         // multichannel receive)
204
205         // only streams are allowed to be registered externally.
206         // we allocate a handler if we need one, otherwise the stream
207         // is assigned to another handler
208
209         // the collection of handlers
210         IsoHandlerVector m_IsoHandlers;
211
212         bool registerHandler(IsoHandler *);
213         bool unregisterHandler(IsoHandler *);
214         void pruneHandlers();
215
216         // the collection of streams
217         Streaming::StreamProcessorVector m_StreamProcessors;
218
219         // handler thread/task
220         bool            m_realtime;
221         int             m_priority;
222         Util::Thread *  m_IsoThreadTransmit;
223         IsoTask *       m_IsoTaskTransmit;
224         Util::Thread *  m_IsoThreadReceive;
225         IsoTask *       m_IsoTaskReceive;
226
227         // debug stuff
228         DECLARE_DEBUG_MODULE;
229
230 };
231
232 #endif /* __FFADO_ISOHANDLERMANAGER__  */
233
234
235
Note: See TracBrowser for help on using the browser.