summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core/src/lib/runtime')
-rw-r--r--gnuradio-core/src/lib/runtime/gr_runtime.cc24
-rw-r--r--gnuradio-core/src/lib/runtime/gr_runtime_impl.cc47
-rw-r--r--gnuradio-core/src/lib/runtime/gr_runtime_impl.h13
-rw-r--r--gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc38
-rw-r--r--gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h1
5 files changed, 59 insertions, 64 deletions
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.cc b/gnuradio-core/src/lib/runtime/gr_runtime.cc
index 926e87857..93f78fea8 100644
--- a/gnuradio-core/src/lib/runtime/gr_runtime.cc
+++ b/gnuradio-core/src/lib/runtime/gr_runtime.cc
@@ -26,8 +26,11 @@
#include <gr_runtime.h>
#include <gr_runtime_impl.h>
+#include <gr_local_sighandler.h>
#include <iostream>
+static gr_runtime *s_runtime = 0;
+
gr_runtime_sptr
gr_make_runtime(gr_hier_block2_sptr top_block)
{
@@ -37,16 +40,29 @@ gr_make_runtime(gr_hier_block2_sptr top_block)
gr_runtime::gr_runtime(gr_hier_block2_sptr top_block)
{
d_impl = new gr_runtime_impl(top_block);
+ s_runtime = this;
}
gr_runtime::~gr_runtime()
{
+ s_runtime = 0; // we don't own this
delete d_impl;
}
+// HACK: This prevents using more than one gr_runtime instance
+static void
+runtime_sigint_handler(int signum)
+{
+
+ if (s_runtime)
+ s_runtime->stop();
+}
+
void
gr_runtime::start()
{
+ gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+
d_impl->start();
}
@@ -59,12 +75,16 @@ gr_runtime::stop()
void
gr_runtime::wait()
{
+ gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+
d_impl->wait();
}
void
gr_runtime::run()
{
- start();
- wait();
+ gr_local_sighandler sigint(SIGINT, runtime_sigint_handler);
+
+ d_impl->start();
+ d_impl->wait();
}
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
index ffc897b8b..dcd904a01 100644
--- a/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
+++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.cc
@@ -30,14 +30,14 @@
#include <gr_simple_flowgraph.h>
#include <gr_hier_block2.h>
#include <gr_hier_block2_detail.h>
+#include <signal.h>
#include <stdexcept>
#include <iostream>
-gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block) :
-d_running(false),
-d_top_block(top_block),
-d_sfg(gr_make_simple_flowgraph()),
-d_graphs()
+gr_runtime_impl::gr_runtime_impl(gr_hier_block2_sptr top_block)
+ : d_running(false),
+ d_top_block(top_block),
+ d_sfg(gr_make_simple_flowgraph())
{
}
@@ -66,7 +66,7 @@ gr_runtime_impl::start()
d_threads.clear();
for (std::vector<gr_block_vector_t>::iterator p = d_graphs.begin();
p != d_graphs.end(); p++) {
- gr_scheduler_thread_sptr thread = gr_make_scheduler_thread(*p);
+ gr_scheduler_thread *thread = new gr_scheduler_thread(*p);
thread->start();
d_threads.push_back(thread);
}
@@ -78,9 +78,8 @@ gr_runtime_impl::stop()
if (!d_running)
throw std::runtime_error("not running");
- for (gr_scheduler_thread_viter_t p = d_threads.begin();
- p != d_threads.end(); p++)
- (*p)->stop();
+ for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++)
+ (*p)->stop();
d_running = false;
}
@@ -88,19 +87,12 @@ gr_runtime_impl::stop()
void
gr_runtime_impl::wait()
{
- for (gr_scheduler_thread_viter_t p = d_threads.begin();
- p != d_threads.end(); p++) {
- while(1) {
- (*p)->join(NULL);
- if (!(*p)->state() == omni_thread::STATE_TERMINATED)
- break;
- }
- }
-}
+ void *dummy_status; // don't ever dereference this
-gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph)
-{
- return gr_scheduler_thread_sptr(new gr_scheduler_thread(graph));
+ for (gr_scheduler_thread_viter_t p = d_threads.begin(); p != d_threads.end(); p++) {
+ (*p)->join(&dummy_status); // pthreads will self-delete, so pointer is now dead
+ (*p) = 0; // FIXME: switch to stl::list and actually remove from container
+ }
}
gr_scheduler_thread::gr_scheduler_thread(gr_block_vector_t graph) :
@@ -118,8 +110,19 @@ void gr_scheduler_thread::start()
start_undetached();
}
-void *gr_scheduler_thread::run_undetached(void *arg)
+void *
+gr_scheduler_thread::run_undetached(void *arg)
{
+ // First code to run in new thread context
+
+ // Mask off SIGINT in this thread to gaurantee mainline thread gets signal
+ sigset_t old_set;
+ sigset_t new_set;
+ sigfillset(&new_set);
+ sigdelset(&new_set, SIGINT);
+ sigprocmask(SIG_BLOCK, &new_set, &old_set);
+
+ // Run the single-threaded scheduler
d_sts->run();
return 0;
}
diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_impl.h b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
index 54977ef97..e69446719 100644
--- a/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
+++ b/gnuradio-core/src/lib/runtime/gr_runtime_impl.h
@@ -28,23 +28,20 @@
#include <omnithread.h>
#include <gr_single_threaded_scheduler.h>
+// omnithread calls delete on itself after thread exits, so can't use shared ptr
class gr_scheduler_thread;
-typedef boost::shared_ptr<gr_scheduler_thread> gr_scheduler_thread_sptr;
-typedef std::vector<gr_scheduler_thread_sptr> gr_scheduler_thread_vector_t;
-typedef std::vector<gr_scheduler_thread_sptr>::iterator gr_scheduler_thread_viter_t;
-
-gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph);
+typedef std::vector<gr_scheduler_thread *> gr_scheduler_thread_vector_t;
+typedef gr_scheduler_thread_vector_t::iterator gr_scheduler_thread_viter_t;
class gr_scheduler_thread : public omni_thread
{
private:
- gr_scheduler_thread(gr_block_vector_t graph);
- friend gr_scheduler_thread_sptr gr_make_scheduler_thread(gr_block_vector_t graph);
-
gr_single_threaded_scheduler_sptr d_sts;
public:
+ gr_scheduler_thread(gr_block_vector_t graph);
~gr_scheduler_thread();
+
virtual void *run_undetached(void *arg);
void start();
void stop();
diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
index 36dc0bc40..0c9c9b707 100644
--- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.cc
@@ -110,8 +110,8 @@ gr_simple_flowgraph_detail::connect(const std::string &src_name, int src_port,
gr_block_sptr dst_block = lookup_block(dst_name);
if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- std::cout << "Connecting " << src_name << ":" << src_port << "->"
- << dst_name << ":" << dst_port << std::endl;
+ std::cout << "Connecting " << src_name << ":" << src_port << "->"
+ << dst_name << ":" << dst_port << std::endl;
if (!src_block)
throw std::invalid_argument("unknown src name");
@@ -291,8 +291,8 @@ gr_simple_flowgraph_detail::setup_connections()
gr_edge_vector_t in_edges = calc_upstream_edges(p->first);
if (GR_SIMPLE_FLOWGRAPH_DETAIL_DEBUG)
- if (in_edges.size() > 0)
- std::cout << "Connecting inputs to " << p->first << "..." << std::endl;
+ if (in_edges.size() > 0)
+ std::cout << "Connecting inputs to " << p->first << "..." << std::endl;
// For each edge that feeds into it
for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) {
@@ -485,28 +485,12 @@ gr_simple_flowgraph_detail::calc_adjacent_blocks(gr_block_sptr block, gr_block_v
return result;
}
-void
-gr_simple_flowgraph_detail::dump_block_vector(gr_block_vector_t blocks)
-{
- for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
- std::cout << (*p) << std::endl;
- }
-}
-
gr_block_vector_t
gr_simple_flowgraph_detail::topological_sort(gr_block_vector_t &blocks)
{
gr_block_vector_t result, tmp;
- std::cout << "Before source sort: " << std::endl;
- dump_block_vector(blocks);
- std::cout << std::endl;
-
tmp = sort_sources_first(blocks);
- std::cout << "After source sort: " << std::endl;
- dump_block_vector(tmp);
- std::cout << std::endl;
-
// Start 'em all white
for (gr_block_viter_t p = tmp.begin(); p != tmp.end(); p++)
(*p)->detail()->set_color(gr_block_detail::WHITE);
@@ -518,10 +502,6 @@ gr_simple_flowgraph_detail::topological_sort(gr_block_vector_t &blocks)
reverse(result.begin(), result.end());
- std::cout << "After dfs: " << std::endl;
- dump_block_vector(result);
- std::cout << std::endl;
-
return result;
}
@@ -557,18 +537,15 @@ gr_simple_flowgraph_detail::topological_dfs_visit(gr_block_sptr block, gr_block_
{
block->detail()->set_color(gr_block_detail::GREY);
- gr_block_vector_t ds_blocks = calc_downstream_blocks(lookup_name(block));
- std::cout << "Downstream blocks of " << block << ":" << std::endl;
- dump_block_vector(ds_blocks);
+ gr_block_vector_t blocks(calc_downstream_blocks(lookup_name(block)));
- gr_block_vector_t blocks(ds_blocks);
for (gr_block_viter_t p = blocks.begin(); p != blocks.end(); p++) {
switch ((*p)->detail()->color()) {
- case gr_block_detail::WHITE: // (u, v) is a tree edge
+ case gr_block_detail::WHITE:
topological_dfs_visit(*p, output);
break;
- case gr_block_detail::GREY: // (u, v) is a back edge - not a DAG
+ case gr_block_detail::GREY:
throw std::runtime_error("flow graph has loops!");
case gr_block_detail::BLACK:
@@ -577,7 +554,6 @@ gr_simple_flowgraph_detail::topological_dfs_visit(gr_block_sptr block, gr_block_
default:
throw std::runtime_error("invalid color on block!");
}
-
}
block->detail()->set_color(gr_block_detail::BLACK);
diff --git a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
index d4812b615..2df1575ad 100644
--- a/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_simple_flowgraph_detail.h
@@ -113,7 +113,6 @@ private:
bool source_p(gr_block_sptr block);
gr_block_vector_t sort_sources_first(gr_block_vector_t &blocks);
void topological_dfs_visit(gr_block_sptr block, gr_block_vector_t &output);
- void dump_block_vector(gr_block_vector_t blocks);
public:
~gr_simple_flowgraph_detail();