Changeset 6201
- Timestamp:
- 08/28/07 18:42:11
- Files:
-
- gnuradio/trunk/configure.ac (modified) (1 diff)
- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_hier_block2.h (modified) (1 diff)
- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc (modified) (2 diffs)
- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.cc (modified) (1 diff)
- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.h (modified) (3 diffs)
- gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
gnuradio/trunk/configure.ac
r6044 r6201 131 131 AC_CHECK_FUNCS([mmap select socket strcspn strerror strspn getpagesize sysconf]) 132 132 AC_CHECK_FUNCS([snprintf gettimeofday nanosleep sched_setscheduler]) 133 AC_CHECK_FUNCS([modf sqrt sigaction sigprocmask ])133 AC_CHECK_FUNCS([modf sqrt sigaction sigprocmask pthread_sigmask]) 134 134 AC_CHECK_FUNCS([sched_setaffinity]) 135 135 gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_hier_block2.h
r6194 r6201 61 61 void connect(gr_basic_block_sptr src, int src_port, 62 62 gr_basic_block_sptr dst, int dst_port); 63 63 64 void disconnect(gr_basic_block_sptr src, int src_port, 64 65 gr_basic_block_sptr dst, int dst_port); 66 67 /*! 68 * Lock a flowgraph in preparation for reconfiguration. When an equal 69 * number of calls to lock() and unlock() have occurred, the flowgraph 70 * will be restarted automatically. 71 * 72 * N.B. lock() and unlock() cannot be called from a flowgraph thread 73 * (E.g., gr_block::work method) or deadlock will occur when 74 * reconfiguration happens. 75 */ 65 76 virtual void lock(); 77 78 /*! 79 * Lock a flowgraph in preparation for reconfiguration. When an equal 80 * number of calls to lock() and unlock() have occurred, the flowgraph 81 * will be restarted automatically. 82 * 83 * N.B. lock() and unlock() cannot be called from a flowgraph thread 84 * (E.g., gr_block::work method) or deadlock will occur when 85 * reconfiguration happens. 86 */ 66 87 virtual void unlock(); 67 88 gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_scheduler_thread.cc
r6193 r6201 55 55 gr_scheduler_thread::run_undetached(void *arg) 56 56 { 57 // First code to run in new thread context57 // This is the first code to run in the new thread context. 58 58 59 // Mask off SIGINT in this thread to gaurantee mainline thread gets signal 60 #ifdef HAVE_SIGPROCMASK 59 /* 60 * In general, on a *nix system, any thread of a process can receive 61 * any asynchronous signal. 62 * 63 * http://www.serpentine.com/blog/threads-faq/mixing-threads-and-signals-unix/ 64 * http://www.linuxjournal.com/article/2121 65 * 66 * We really don't want to be handling asynchronous signals such 67 * as SIGINT and SIGHUP here. We mask them off in the signal 68 * processing threads so that they'll get handled by the mainline 69 * thread. We leave the synchronous signals SIGQUIT, SIGBUS, 70 * SIGILL, SIGSEGV etc alone 71 * 72 * FIXME? It might be better to mask them all off in the parent 73 * thread then dedicate a single thread to handling all signals 74 * using sigwait. 75 */ 76 #if defined(HAVE_PTHREAD_SIGMASK) || defined(HAVE_SIGPROCMASK) 61 77 sigset_t old_set; 62 78 sigset_t new_set; 79 int r; 63 80 sigemptyset(&new_set); 64 81 sigaddset(&new_set, SIGINT); 65 sigprocmask(SIG_BLOCK, &new_set, &old_set); 82 sigaddset(&new_set, SIGHUP); 83 sigaddset(&new_set, SIGPIPE); 84 sigaddset(&new_set, SIGALRM); 85 sigaddset(&new_set, SIGCHLD); 86 87 #ifdef HAVE_PTHREAD_SIGMASK 88 r = pthread_sigmask(SIG_BLOCK, &new_set, &old_set); 89 if (r != 0) 90 perror("pthread_sigmask"); 91 #else 92 r = sigprocmask(SIG_BLOCK, &new_set, &old_set); 93 if (r != 0) 94 perror("sigprocmask"); 95 #endif 66 96 #endif 67 97 // Run the single-threaded scheduler … … 73 103 gr_scheduler_thread::stop() 74 104 { 75 if ( GR_SCHEDULER_THREAD_DEBUG)105 if (0 && GR_SCHEDULER_THREAD_DEBUG) // FIXME not safe to call from signal handler 76 106 std::cout << "gr_scheduler_thread::stop() " 77 107 << this << std::endl; gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.cc
r6187 r6201 47 47 gr_top_block::~gr_top_block() 48 48 { 49 stop(); 50 wait(); 51 49 52 delete d_impl; 50 53 } gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block.h
r6187 r6201 48 48 49 49 /*! 50 * Start the enclosed flowgraph. Creates an undetached scheduler thread for 51 * each flow graph partition. Returns to caller once created. 50 * \brief The simple interface to running a flowgraph. 51 * 52 * Calls start() then wait(). Used to run a flowgraph that will stop 53 * on its own, or to run a flowgraph indefinitely until SIGINT is 54 * received. 55 */ 56 void run(); 57 58 /*! 59 * Start the contained flowgraph. Creates one or more threads to 60 * execute the flow graph. Returns to the caller once the threads 61 * are created. 52 62 */ 53 63 void start(); 54 64 55 65 /*! 56 * Stop the running flowgraph. Tells each created scheduler thread57 * to exit, then returns to caller.66 * Stop the running flowgraph. Notifies each thread created by the 67 * scheduler to shutdown, then returns to caller. 58 68 */ 59 69 void stop(); 60 70 61 71 /*! 62 * Wait for a stopped flowgraph to complete. Joins each completed 63 * thread. 72 * Wait for a flowgraph to complete. Flowgraphs complete when 73 * either (1) all blocks indicate that they are done (typically only 74 * when using gr.file_source, or gr.head, or (2) after stop() has been 75 * called to request shutdown. 64 76 */ 65 77 void wait(); 66 67 /*!68 * Calls start(), then wait(). Used to run a flowgraph that will stop69 * on its own, or to run a flowgraph indefinitely until SIGKILL is70 * received().71 */72 void run();73 78 74 79 /*! … … 77 82 * will be restarted automatically. 78 83 * 79 * N.B. lock() and unlock() cannot be called from a flowgraph thread or 80 * deadlock will occur when reconfiguration happens. 84 * N.B. lock() and unlock() cannot be called from a flowgraph thread 85 * (E.g., gr_block::work method) or deadlock will occur when 86 * reconfiguration happens. 81 87 */ 82 88 virtual void lock(); … … 87 93 * will be restarted automatically. 88 94 * 89 * N.B. lock() and unlock() cannot be called from a flowgraph thread or 90 * deadlock will occur when reconfiguration happens. 95 * N.B. lock() and unlock() cannot be called from a flowgraph thread 96 * (E.g., gr_block::work method) or deadlock will occur when 97 * reconfiguration happens. 91 98 */ 92 99 virtual void unlock(); gnuradio/trunk/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc
r6194 r6201 33 33 #include <stdexcept> 34 34 #include <iostream> 35 #include <string.h> 35 36 36 37 #define GR_TOP_BLOCK_IMPL_DEBUG 0 … … 38 39 static gr_top_block_impl *s_impl = 0; 39 40 40 // Make a vector of gr_block from a vector of gr_basic_block 41 static 42 gr_block_vector_t 43 make_gr_block_vector(gr_basic_block_vector_t &blocks) 41 /*! 42 * Make a vector of gr_block from a vector of gr_basic_block 43 * 44 * Pass-by-value to avoid problem with possible asynchronous modification 45 */ 46 static gr_block_vector_t 47 make_gr_block_vector(gr_basic_block_vector_t blocks) 44 48 { 45 49 gr_block_vector_t result; … … 52 56 53 57 // FIXME: This prevents using more than one gr_top_block instance 58 54 59 static void 55 60 runtime_sigint_handler(int signum) 56 61 { 57 if (GR_TOP_BLOCK_IMPL_DEBUG) 58 std::cout << "SIGINT received, calling stop()" << std::endl; 62 if (GR_TOP_BLOCK_IMPL_DEBUG){ 63 char *msg = "SIGINT received, calling stop()\n"; 64 ::write(1, msg, strlen(msg)); // write is OK to call from signal handler 65 } 59 66 60 67 if (s_impl) 61 68 s_impl->stop(); 62 69 } 70 71 // ---------------------------------------------------------------- 63 72 64 73 gr_top_block_impl::gr_top_block_impl(gr_top_block *owner) … … 68 77 d_lock_count(0) 69 78 { 79 if (s_impl) 80 throw std::logic_error("gr_top_block_impl: multiple simultaneous gr_top_block's"); 81 70 82 s_impl = this; 71 83 } … … 116 128 } 117 129 130 /* 131 * N.B. as currently implemented, it is possible that this may be 132 * invoked by the SIGINT handler which is fragile as hell... 133 */ 118 134 void 119 135 gr_top_block_impl::stop() 120 136 { 121 if (GR_TOP_BLOCK_IMPL_DEBUG) 122 std::cout << "stop: entered" << std::endl; 137 if (GR_TOP_BLOCK_IMPL_DEBUG){ 138 char *msg = "stop: entered\n"; 139 ::write(1, msg, strlen(msg)); 140 } 123 141 124 142 for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) { 125 if (GR_TOP_BLOCK_IMPL_DEBUG) 126 std::cout << "stop: stopping thread " << (*p) << std::endl; 127 (*p)->stop(); 128 } 129 143 if (*p) 144 (*p)->stop(); 145 } 130 146 d_running = false; 131 147 }
