Changeset 233

Show
Ignore:
Timestamp:
05/29/06 11:40:23 (16 years ago)
Author:
pieterpalmers
Message:

- reworked the debug module to use RT safe messaging

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/libfreebob-2.0/libfreebob/freebob_streaming.h

    r227 r233  
    183183 * @return  
    184184 */ 
    185 bool freebob_streaming_prepare(freebob_device_t *dev); 
     185int freebob_streaming_prepare(freebob_device_t *dev); 
    186186 
    187187 
  • branches/libfreebob-2.0/src/debugmodule/debugmodule.cpp

    r232 r233  
    7373    va_start( arg, format ); 
    7474 
    75     //freebob_messagebuffer_va_add( format, arg ); 
     75    DebugModuleManager::instance()->va_print( format, arg ); 
    7676     
    7777    va_end( arg ); 
     
    9292    va_list arg; 
    9393    va_start( arg, format ); 
    94  
    95     //freebob_messagebuffer_add( "%s (%s)[%d] %s: ", getPreSequence( level ), 
    96     //             file,  line,  function ); 
    97     //freebob_messagebuffer_va_add( format, arg ); 
    98     //freebob_messagebuffer_add( "%s", getPostSequence( level ) ); 
     94    DebugModuleManager::instance()->print( "%s (%s)[%d] %s: ", getPreSequence( level ), 
     95                 file,  line,  function ); 
     96    DebugModuleManager::instance()->va_print( format, arg ); 
     97    DebugModuleManager::instance()->print( "%s", getPostSequence( level ) ); 
    9998    va_end( arg ); 
    10099} 
     
    123122 
    124123DebugModuleManager::DebugModuleManager() 
    125 
    126         freebob_messagebuffer_init(); 
     124    : mb_initialized(0) 
     125    , mb_inbuffer(0) 
     126    , mb_outbuffer(0) 
     127    , mb_overruns(0) 
     128 
     129
    127130 
    128131} 
     
    130133DebugModuleManager::~DebugModuleManager() 
    131134{ 
    132         freebob_messagebuffer_exit(); 
    133  
     135        // cleanin up leftover modules 
     136    for ( DebugModuleVectorIterator it = m_debugModules.begin(); 
     137          it != m_debugModules.end(); 
     138          ++it ) 
     139    { 
     140        fprintf(stderr,"Cleaning up leftover debug module: %s",(*it)->getName().c_str()); 
     141        m_debugModules.erase( it ); 
     142        delete *it; 
     143    } 
     144 
     145        if (!mb_initialized) 
     146                return; 
     147 
     148        pthread_mutex_lock(&mb_write_lock); 
     149        mb_initialized = 0; 
     150        pthread_cond_signal(&mb_ready_cond); 
     151        pthread_mutex_unlock(&mb_write_lock); 
     152 
     153        pthread_join(mb_writer_thread, NULL); 
     154        mb_flush(); 
     155 
     156        if (mb_overruns) 
     157                fprintf(stderr, "WARNING: %d message buffer overruns!\n", 
     158                        mb_overruns); 
     159        else 
     160                fprintf(stderr, "no message buffer overruns\n"); 
     161 
     162        pthread_mutex_destroy(&mb_write_lock); 
     163        pthread_cond_destroy(&mb_ready_cond); 
     164 
     165
     166 
     167bool 
     168DebugModuleManager::init() 
     169
     170        if (mb_initialized) 
     171                return true; 
     172                 
     173        fprintf(stderr, "DebugModuleManager init...\n"); 
     174 
     175        pthread_mutex_init(&mb_write_lock, NULL); 
     176        pthread_cond_init(&mb_ready_cond, NULL); 
     177 
     178        mb_overruns = 0; 
     179        mb_initialized = 1; 
     180 
     181        if (pthread_create(&mb_writer_thread, NULL, &mb_thread_func, (void *)this) != 0) 
     182                mb_initialized = 0; 
     183 
     184    return true; 
    134185} 
    135186 
     
    141192        if ( !m_instance ) { 
    142193            cerr << "DebugModuleManager::instance Failed to create " 
     194                 << "DebugModuleManager" << endl; 
     195        } 
     196        if ( !m_instance->init() ) { 
     197            cerr << "DebugModuleManager::instance Failed to init " 
    143198                 << "DebugModuleManager" << endl; 
    144199        } 
     
    187242         << name << ")" << endl; 
    188243    return false; 
     244} 
     245 
     246 
     247void 
     248DebugModuleManager::mb_flush() 
     249{ 
     250        /* called WITHOUT the mb_write_lock */ 
     251        while (mb_outbuffer != mb_inbuffer) { 
     252                fputs(mb_buffers[mb_outbuffer], stderr); 
     253                mb_outbuffer = MB_NEXT(mb_outbuffer); 
     254        } 
     255} 
     256 
     257void * 
     258DebugModuleManager::mb_thread_func(void *arg) 
     259{ 
     260 
     261    DebugModuleManager *m=static_cast<DebugModuleManager *>(arg); 
     262     
     263        /* The mutex is only to eliminate collisions between multiple 
     264         * writer threads and protect the condition variable. */ 
     265        pthread_mutex_lock(&m->mb_write_lock); 
     266 
     267        while (m->mb_initialized) { 
     268                pthread_cond_wait(&m->mb_ready_cond, &m->mb_write_lock); 
     269  
     270                /* releasing the mutex reduces contention */ 
     271                pthread_mutex_unlock(&m->mb_write_lock); 
     272                m->mb_flush(); 
     273                pthread_mutex_lock(&m->mb_write_lock); 
     274        } 
     275 
     276        pthread_mutex_unlock(&m->mb_write_lock); 
     277 
     278        return NULL; 
     279} 
     280 
     281void  
     282DebugModuleManager::print(const char *fmt, ...) 
     283{ 
     284        char msg[MB_BUFFERSIZE]; 
     285        va_list ap; 
     286 
     287        /* format the message first, to reduce lock contention */ 
     288        va_start(ap, fmt); 
     289        vsnprintf(msg, MB_BUFFERSIZE, fmt, ap); 
     290        va_end(ap); 
     291 
     292        if (!mb_initialized) { 
     293                /* Unable to print message with realtime safety. 
     294                 * Complain and print it anyway. */ 
     295                fprintf(stderr, "ERROR: messagebuffer not initialized: %s", 
     296                        msg); 
     297                return; 
     298        } 
     299        if (pthread_mutex_trylock(&mb_write_lock) == 0) { 
     300                strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE); 
     301                mb_inbuffer = MB_NEXT(mb_inbuffer); 
     302                pthread_cond_signal(&mb_ready_cond); 
     303                pthread_mutex_unlock(&mb_write_lock); 
     304        } else {                        /* lock collision */ 
     305//              atomic_add(&mb_overruns, 1); 
     306                // FIXME: atomicity 
     307                mb_overruns++; // skip the atomicness for now 
     308        } 
     309} 
     310 
     311 
     312void  
     313DebugModuleManager::va_print (const char *fmt, va_list ap) 
     314{ 
     315        char msg[MB_BUFFERSIZE]; 
     316         
     317        /* format the message first, to reduce lock contention */ 
     318        vsnprintf(msg, MB_BUFFERSIZE, fmt, ap); 
     319 
     320        if (!mb_initialized) { 
     321                /* Unable to print message with realtime safety. 
     322                 * Complain and print it anyway. */ 
     323                fprintf(stderr, "ERROR: messagebuffer not initialized: %s", 
     324                        msg); 
     325                return; 
     326        } 
     327 
     328        if (pthread_mutex_trylock(&mb_write_lock) == 0) { 
     329                strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE); 
     330                mb_inbuffer = MB_NEXT(mb_inbuffer); 
     331                pthread_cond_signal(&mb_ready_cond); 
     332                pthread_mutex_unlock(&mb_write_lock); 
     333        } else {                        /* lock collision */ 
     334//              atomic_add(&mb_overruns, 1); 
     335                // FIXME: atomicity 
     336                mb_overruns++; // skip the atomicness for now 
     337        } 
    189338} 
    190339 
  • branches/libfreebob-2.0/src/debugmodule/debugmodule.h

    r232 r233  
    2424#include "../fbtypes.h" 
    2525 
    26 #include "messagebuffer.h" 
    2726 
    2827#include <vector> 
     
    3029 
    3130typedef short debug_level_t; 
     31 
     32/* MB_NEXT() relies on the fact that MB_BUFFERS is a power of two */ 
     33#define MB_BUFFERS      128 
     34#define MB_NEXT(index) ((index+1) & (MB_BUFFERS-1)) 
     35#define MB_BUFFERSIZE   256             /* message length limit */ 
    3236 
    3337#define debugFatal( format, args... )                               \ 
     
    167171 
    168172    static DebugModuleManager* instance(); 
     173    ~DebugModuleManager(); 
     174     
    169175    bool setMgrDebugLevel( std::string name, debug_level_t level ); 
    170176 
     
    173179    bool unregisterModule( DebugModule& debugModule ); 
    174180 
     181    bool init(); 
     182     
     183    void print(const char *fmt, ...); 
     184    void va_print(const char *fmt, va_list); 
     185     
    175186private: 
    176187    DebugModuleManager(); 
    177     ~DebugModuleManager(); 
    178188 
    179189    typedef std::vector< DebugModule* > DebugModuleVector; 
    180190    typedef std::vector< DebugModule* >::iterator DebugModuleVectorIterator; 
    181191 
    182  
     192    char mb_buffers[MB_BUFFERS][MB_BUFFERSIZE]; 
     193    unsigned int mb_initialized; 
     194    unsigned int mb_inbuffer; 
     195    unsigned int mb_outbuffer; 
     196    unsigned int mb_overruns; 
     197    pthread_t mb_writer_thread; 
     198    pthread_mutex_t mb_write_lock; 
     199    pthread_cond_t mb_ready_cond; 
     200 
     201    static void *mb_thread_func(void *arg); 
     202    void mb_flush(); 
     203     
    183204    static DebugModuleManager* m_instance; 
    184205    DebugModuleVector          m_debugModules; 
  • branches/libfreebob-2.0/src/debugmodule/Makefile.am

    r232 r233  
    1818noinst_LTLIBRARIES = libdebugmodule.la 
    1919 
    20 noinst_HEADERS =                                \ 
    21                 debugmodule.h   messagebuffer.h         
     20noinst_HEADERS = debugmodule.h 
    2221 
    23 libdebugmodule_la_SOURCES =             \ 
    24                 debugmodule.cpp messagebuffer.c 
     22libdebugmodule_la_SOURCES = debugmodule.cpp 
    2523 
    2624 
  • branches/libfreebob-2.0/src/freebob.cpp

    r199 r233  
    4141IMPL_GLOBAL_DEBUG_MODULE( FreeBob, DEBUG_LEVEL_VERBOSE ); 
    4242 
     43#ifdef __cplusplus 
     44extern "C" { 
     45#endif 
     46 
     47// this is very much nescessary, as otherwise the  
     48// message buffer thread doesn't get killed when the  
     49// library is dlclose()'d  
     50 
     51static void exitfunc(void) __attribute__((destructor)); 
     52 
     53static void exitfunc(void) 
     54{ 
     55    delete DebugModuleManager::instance(); 
     56} 
     57#ifdef __cplusplus 
     58} 
     59#endif 
     60 
    4361const char* 
    4462freebob_get_version() { 
  • branches/libfreebob-2.0/src/libstreaming/AmdtpStreamProcessor.cpp

    r230 r233  
    143143       retval=RAW1394_ISO_DEFER; 
    144144    } 
     145     
     146    m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    145147 
    146148        return (int)retval; 
     
    174176 
    175177bool AmdtpTransmitStreamProcessor::prepare() { 
     178    m_PeriodStat.setName("XMT PERIOD"); 
     179    m_PacketStat.setName("XMT PACKET"); 
     180    m_WakeupStat.setName("XMT WAKEUP"); 
    176181 
    177182        debugOutput( DEBUG_LEVEL_VERBOSE, "Preparing...\n"); 
     
    367372 
    368373bool AmdtpTransmitStreamProcessor::transfer() { 
     374    m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    369375 
    370376        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
     
    768774                // can be important for sync though 
    769775        } 
     776         
     777    m_PacketStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    770778 
    771779        return (int)retval; 
     
    796804 
    797805bool AmdtpReceiveStreamProcessor::prepare() { 
     806 
     807    m_PeriodStat.setName("RCV PERIOD"); 
     808    m_PacketStat.setName("RCV PACKET"); 
     809    m_WakeupStat.setName("RCV WAKEUP"); 
    798810 
    799811        // prepare all non-device specific stuff 
     
    931943 
    932944bool AmdtpReceiveStreamProcessor::transfer() { 
     945 
     946    m_PeriodStat.mark(freebob_ringbuffer_read_space(m_event_buffer)/(4*m_dimension)); 
    933947 
    934948        debugOutput( DEBUG_LEVEL_VERY_VERBOSE, "Transferring period...\n"); 
  • branches/libfreebob-2.0/src/libstreaming/FreebobPosixThread.cpp

    r230 r233  
    2727#include "FreebobPosixThread.h" 
    2828// #include "FreebobError.h" 
    29 #include "debug.h" 
    3029#include <string.h> // for memset 
    3130#include <errno.h> 
     
    4544 
    4645    if ((err = pthread_setcanceltype(obj->fCancellation, NULL)) != 0) { 
    47         printError("pthread_setcanceltype err = %s", strerror(err)); 
     46        debugError("pthread_setcanceltype err = %s", strerror(err)); 
    4847    } 
    4948 
    5049    // Call Init method 
    5150    if (!runnable->Init()) { 
    52         printError("Thread init fails: thread quits"); 
     51        debugError("Thread init fails: thread quits"); 
    5352        return 0; 
    5453    } 
     
    8685 
    8786        if ((res = pthread_attr_setschedpolicy(&attributes, SCHED_RR))) { 
    88             printError("Cannot set FIFO scheduling class for RT thread  %d %s", res, strerror(errno)); 
     87            debugError("Cannot set FIFO scheduling class for RT thread  %d %s", res, strerror(errno)); 
    8988            return -1; 
    9089        } 
    9190 
    9291        if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) { 
    93             printError("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno)); 
     92            debugError("Cannot set scheduling scope for RT thread %d %s", res, strerror(errno)); 
    9493            return -1; 
    9594        } 
     
    9998 
    10099        if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) { 
    101             printError("Cannot set scheduling priority for RT thread %d %s", res, strerror(errno)); 
     100            debugError("Cannot set scheduling priority for RT thread %d %s", res, strerror(errno)); 
    102101            return -1; 
    103102        } 
    104103 
    105104        if ((res = pthread_create(&fThread, &attributes, ThreadHandler, this))) { 
    106             printError("Cannot set create thread %d %s", res, strerror(errno)); 
     105            debugError("Cannot set create thread %d %s", res, strerror(errno)); 
    107106            return -1; 
    108107        } 
     
    113112 
    114113        if ((res = pthread_create(&fThread, 0, ThreadHandler, this))) { 
    115             printError("Cannot set create thread %d %s", res, strerror(errno)); 
     114            debugError("Cannot set create thread %d %s", res, strerror(errno)); 
    116115            return -1; 
    117116        } 
     
    161160 
    162161    if ((res = pthread_setschedparam(fThread, SCHED_RR, &rtparam)) != 0) { 
    163         printError("Cannot use real-time scheduling (FIFO/%d) " 
     162        debugError("Cannot use real-time scheduling (FIFO/%d) " 
    164163                   "(%d: %s)", rtparam.sched_priority, res, 
    165164                   strerror(res)); 
     
    187186 
    188187    if ((res = pthread_setschedparam(fThread, SCHED_OTHER, &rtparam)) != 0) { 
    189         printError("Cannot switch to normal scheduling priority(%s)\n", strerror(errno)); 
     188        debugError("Cannot switch to normal scheduling priority(%s)\n", strerror(errno)); 
    190189        return -1; 
    191190    } 
  • branches/libfreebob-2.0/src/libstreaming/freebob_streaming.cpp

    r230 r233  
    3434 
    3535#include "libfreebob/freebob_streaming.h" 
    36 #include "messagebuffer.h" 
    3736#include "../devicemanager.h" 
    3837#include "../iavdevice.h" 
     
    7170 
    7271freebob_device_t *freebob_streaming_init (freebob_device_info_t *device_info, freebob_options_t options) { 
    73         freebob_messagebuffer_init(); 
    7472        int i=0; 
    7573 
     
    107105        } 
    108106         
     107    dev->processorManager->setThreadParameters(dev->options.realtime, dev->options.packetizer_priority); 
     108         
    109109        dev->processorManager->setVerboseLevel(DEBUG_LEVEL_VERBOSE); 
    110110        if(!dev->processorManager->init()) { 
     
    157157 * @return  
    158158 */ 
    159 bool freebob_streaming_prepare(freebob_device_t *dev) { 
     159int freebob_streaming_prepare(freebob_device_t *dev) { 
    160160        int i=0; 
    161161         
     
    173173        delete dev; 
    174174 
    175         freebob_messagebuffer_exit(); 
    176          
    177175        return; 
    178176} 
     
    192190                int j=0; 
    193191                for(j=0; j<device->getStreamCount();j++) { 
     192                debugOutput(DEBUG_LEVEL_VERBOSE,"Starting stream %d of device %d\n",j,i); 
    194193                        // start the stream 
    195194                        device->startStreamByIndex(j); 
     
    215214                assert(device); 
    216215                 
    217                 debugOutput(DEBUG_LEVEL_VERBOSE,"Stopping stream %d\n",i); 
    218216 
    219217                int j=0; 
    220218                for(j=0; j<device->getStreamCount();j++) { 
    221                         // start the stream 
     219                debugOutput(DEBUG_LEVEL_VERBOSE,"Stopping stream %d of device %d\n",j,i); 
     220                        // stop the stream 
    222221                        device->stopStreamByIndex(j); 
    223222                } 
     
    279278 
    280279int freebob_streaming_write(freebob_device_t *dev, int i, freebob_sample_t *buffer, int nsamples) { 
    281 //     debugFatal("Not implemented\n"); 
     280// debugFatal("Not implemented\n"); 
    282281        Port *p=dev->processorManager->getPortByIndex(i, Port::E_Playback); 
    283282        // use an assert here performancewise,  
  • branches/libfreebob-2.0/src/libstreaming/Makefile.am

    r225 r233  
    1818 
    1919noinst_LTLIBRARIES = libstreaming.la 
    20 noinst_HEADERS = messagebuffer.h cip.h debug.h FreebobPosixThread.h \ 
    21         FreebobThread.h FreebobAtomic.h IsoHandler.h IsoHandlerManager.h IsoStream.h \ 
    22         ringbuffer.h PacketBuffer.h PortManager.h Port.h StreamProcessor.h \ 
    23         StreamProcessorManager.h AmdtpPortInfo.h AmdtpPort.h AmdtpStreamProcessor.h StreamRunner.h \ 
    24         ringbuffer.h 
     20noinst_HEADERS = cip.h FreebobPosixThread.h FreebobThread.h FreebobAtomic.h \ 
     21        IsoHandler.h IsoHandlerManager.h IsoStream.h ringbuffer.h PacketBuffer.h \ 
     22        PortManager.h Port.h StreamProcessor.h StreamProcessorManager.h AmdtpPortInfo.h \ 
     23        AmdtpPort.h AmdtpStreamProcessor.h StreamRunner.h ringbuffer.h streamstatistics.h 
    2524 
    26 libstreaming_la_SOURCES = messagebuffer.c cip.c FreebobPosixThread.cpp \ 
    27         freebob_streaming.cpp IsoHandler.cpp IsoHandlerManager.cpp IsoStream.cpp PacketBuffer.cpp \ 
    28         PortManager.cpp Port.cpp StreamProcessor.cpp StreamProcessorManager.cpp \ 
    29         AmdtpPortInfo.cpp AmdtpPort.cpp AmdtpStreamProcessor.cpp StreamRunner.cpp
    30         ringbuffer.c 
     25libstreaming_la_SOURCES = cip.c FreebobPosixThread.cpp \ 
     26               freebob_streaming.cpp IsoHandler.cpp IsoHandlerManager.cpp IsoStream.cpp PacketBuffer.cpp \ 
     27               PortManager.cpp Port.cpp StreamProcessor.cpp StreamProcessorManager.cpp \ 
     28               AmdtpPortInfo.cpp AmdtpPort.cpp AmdtpStreamProcessor.cpp StreamRunner.cpp       ringbuffer.c
     29        streamstatistics.cpp 
    3130 
    3231INCLUDES = $(LIBRAW1394_CFLAGS) $(LIBIEC61883_CFLAGS) -I$(top_srcdir)/src \ 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessor.cpp

    r230 r233  
    6969        debugOutputShort( DEBUG_LEVEL_NORMAL, "  Enabled        : %d\n", !m_disabled); 
    7070         
     71    m_PeriodStat.dumpInfo(); 
     72    m_PacketStat.dumpInfo(); 
     73    m_WakeupStat.dumpInfo(); 
     74         
     75         
    7176}; 
    7277 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessor.h

    r230 r233  
    3333#include "IsoStream.h" 
    3434#include "PortManager.h" 
     35#include "streamstatistics.h" 
    3536 
    3637namespace FreebobStreaming { 
     
    117118        bool m_disabled; 
    118119 
    119      DECLARE_DEBUG_MODULE; 
     120    StreamStatistics m_PacketStat; 
     121    StreamStatistics m_PeriodStat; 
     122     
     123    StreamStatistics m_WakeupStat; 
     124     
     125 
     126    DECLARE_DEBUG_MODULE; 
    120127 
    121128 
     
    125132\brief Class providing a generic interface for receive Stream Processors 
    126133 
    127   
    128134*/ 
    129135class ReceiveStreamProcessor : public StreamProcessor { 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessorManager.cpp

    r230 r233  
    151151 
    152152        // and the tread that runs the runner 
    153         m_streamingThread=new FreebobPosixThread(this); 
     153        m_streamingThread=new FreebobPosixThread(this, m_thread_realtime, m_thread_priority, PTHREAD_CANCEL_DEFERRED); 
    154154        if(!m_streamingThread) { 
    155155                debugFatal("Could not create streaming thread\n"); 
     
    734734} 
    735735 
     736bool StreamProcessorManager::setThreadParameters(bool rt, int priority) { 
     737    m_thread_realtime=rt; 
     738    m_thread_priority=priority; 
     739    return true; 
     740} 
     741 
    736742 
    737743} // end of namespace 
  • branches/libfreebob-2.0/src/libstreaming/StreamProcessorManager.h

    r230 r233  
    9696        bool stop(); 
    9797 
     98    bool setThreadParameters(bool rt, int priority); 
     99 
    98100        // the ISO-side functions 
    99101protected: 
     
    107109 
    108110        bool m_xrun_happened;  
     111 
     112    bool m_thread_realtime; 
     113    int m_thread_priority; 
    109114 
    110115        // processor list