/* -*- c++ -*- */ /* * Copyright 2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #ifdef HAVE_SCHED_H #include #endif #define VERBOSE 0 // define to 0 or 1 static pmt_t s_worker_state_changed = pmt_intern("%worker-state-changed"); mb_worker::mb_worker(mb_runtime_thread_per_block *runtime, mb_mblock_maker_t maker, const std::string &instance_name, pmt_t user_arg) : omni_thread((void *) 0, PRIORITY_NORMAL), d_runtime(runtime), d_maker(maker), d_instance_name(instance_name), d_user_arg(user_arg), d_state_cond(&d_mutex), d_state(TS_UNINITIALIZED), d_why_dead(RIP_NOT_DEAD_YET) { } #if 0 mb_worker::~mb_worker() { } #endif #ifdef HAVE_SCHED_SETAFFINITY static void set_affinity(const std::string &instance_name, const std::string &class_name) { //static int counter = 0; cpu_set_t mask; CPU_ZERO(&mask); if (0){ //CPU_SET(counter & 0x1, &mask); //counter++; CPU_SET(0, &mask); int r = sched_setaffinity(mb_gettid(), sizeof(mask), &mask); if (r == -1) perror("sched_setaffinity"); } } #else static void set_affinity(const std::string &instance_name, const std::string &class_name) { } #endif void mb_worker::set_state(worker_state_t state) { { omni_mutex_lock l2(d_mutex); d_state = state; // update our state d_state_cond.broadcast(); // Notify everybody who cares... } // send msg to runtime, telling it something changed. (*d_runtime->accepter())(s_worker_state_changed, PMT_F, PMT_F, MB_PRI_BEST); } void * mb_worker::run_undetached(void *ignored) { // FIXME add pthread_sigmask stuff //set_affinity(d_instance_name, d_class_name); set_affinity(d_instance_name, ""); try { worker_thread_top_level(); d_why_dead = RIP_EXIT; } catch (mbe_terminate){ d_why_dead = RIP_TERMINATE; } catch (mbe_exit){ d_why_dead = RIP_EXIT; } catch (std::logic_error e){ if (d_why_dead == RIP_NOT_DEAD_YET) d_why_dead = RIP_UNHANDLED_EXCEPTION; std::cerr << "\nmb_worker::run_undetached: unhandled exception:\n"; std::cerr << " " << e.what() << std::endl; } catch (...){ if (d_why_dead == RIP_NOT_DEAD_YET) d_why_dead = RIP_UNHANDLED_EXCEPTION; } if (VERBOSE) std::cerr << "\nrun_undetached: about to return, d_why_dead = " << d_why_dead << std::endl; set_state(TS_DEAD); return 0; } void mb_worker::worker_thread_top_level() { if (VERBOSE) std::cerr << "worker_thread_top_level (enter):" << std::endl << " instance_name: " << d_instance_name << std::endl << " omnithread id: " << id() << std::endl << " gettid: " << mb_gettid() << std::endl << " getpid: " << getpid() << std::endl; cause_of_death_t pending_cause_of_death = RIP_NOT_DEAD_YET; try { pending_cause_of_death = RIP_CTOR_EXCEPTION; d_mblock = d_maker(d_runtime, d_instance_name, d_user_arg); if (VERBOSE) std::cerr << "worker_thread_top_level (post-construction):" << std::endl << " instance_name: " << d_instance_name << std::endl; pending_cause_of_death = RIP_INIT_EXCEPTION; d_mblock->initial_transition(); if (VERBOSE) std::cerr << "worker_thread_top_level (post-initial-transition):" << std::endl << " instance_name: " << d_instance_name << std::endl; set_state(TS_RUNNING); pending_cause_of_death = RIP_UNHANDLED_EXCEPTION; d_mblock->main_loop(); } catch (...){ d_why_dead = pending_cause_of_death; throw; } if (VERBOSE) std::cerr << "worker_thread_top_level (exit):" << std::endl << " instance_name: " << d_instance_name << std::endl; }