Exemplo n.º 1
0
        void log_non_empty_queue(char const* const desc, queue_type& queue)
        {
            mutex_type::scoped_lock l(mtx_);
            while (!queue.empty()) {
                threads::thread_id_type id = queue.front().id_;
                queue.front().id_ = 0;
                queue.pop_front();

                // we know that the id is actually the pointer to the thread
                threads::thread_data* thrd = reinterpret_cast<threads::thread_data*>(id);
                LERR_(info) << "~full_empty_entry: aborting pending thread in "
                        << desc << ": "
                        << get_thread_state_name(thrd->get_state())
                        << "(" << id << "): " << thrd->get_description();

                // forcefully abort thread, do not throw
                error_code ec(lightweight);
                threads::set_thread_state(id, threads::pending,
                    threads::wait_abort, threads::thread_priority_normal, ec);
                if (ec) {
                    LERR_(error) << "~full_empty_entry: could not abort thread"
                        << get_thread_state_name(thrd->get_state())
                        << "(" << id << "): " << thrd->get_description();
                }
            }
        }
Exemplo n.º 2
0
    mutex::~mutex()
    {
        HPX_ITT_SYNC_DESTROY(this);
        if (!queue_.empty()) {
            LERR_(fatal) << "lcos::local::mutex::~mutex: " << description_
                         << ": queue is not empty";

            mutex_type::scoped_lock l(mtx_);
            while (!queue_.empty()) {
                threads::thread_id_type id = queue_.front().id_;
                queue_.front().id_ = 0;
                queue_.pop_front();

                // we know that the id is actually the pointer to the thread
                LERR_(fatal) << "lcos::local::mutex::~mutex: " << description_
                    << ": pending thread: "
                    << threads::get_thread_state_name(threads::get_thread_state(id))
                    << "(" << id << "): " << threads::get_thread_description(id);

                // forcefully abort thread, do not throw
                error_code ec(lightweight);
                threads::set_thread_state(id, threads::pending,
                    threads::wait_abort, threads::thread_priority_default, ec);
                if (ec) {
                    LERR_(fatal) << "lcos::local::mutex::~mutex: could not abort thread"
                        << get_thread_state_name(threads::get_thread_state(id))
                        << "(" << id << "): " << threads::get_thread_state(id);
                }
            }
        }
    }
Exemplo n.º 3
0
    inline thread_state_enum set_active_state(
        thread_id_type const& thrd, thread_state_enum newstate,
        thread_state_ex_enum newstate_ex, thread_priority priority,
        thread_state previous_state)
    {
        if (HPX_UNLIKELY(!thrd)) {
            HPX_THROW_EXCEPTION(null_thread_id,
                "threads::detail::set_active_state",
                "NULL thread id encountered");
            return terminated;
        }

        // make sure that the thread has not been suspended and set active again
        // in the mean time
        thread_state current_state = thrd->get_state();

        if (thread_state_enum(current_state) == thread_state_enum(previous_state) &&
            current_state != previous_state)
        {
            LTM_(warning)
                << "set_active_state: thread is still active, however "
                      "it was non-active since the original set_state "
                      "request was issued, aborting state change, thread("
                << thrd.get() << "), description("
                << thrd->get_description() << "), new state("
                << get_thread_state_name(newstate) << ")";
            return terminated;
        }

        // just retry, set_state will create new thread if target is still active
        error_code ec(lightweight);      // do not throw
        detail::set_thread_state(thrd, newstate, newstate_ex, priority, std::size_t(-1), ec);
        return terminated;
    }
Exemplo n.º 4
0
            ~counting_semaphore()
            {
                typename mutex_type::scoped_lock l(mtx_);

                if (!queue_.empty())
                {
                    LERR_(fatal)
                        << "lcos::counting_semaphore::~counting_semaphore:"
                           " queue is not empty, aborting threads";

                    while (!queue_.empty())
                    {
                        threads::thread_id_type id = queue_.front().id_;
                        queue_.front().id_ = 0;
                        queue_.pop_front();

                        // we know that the id is actually the pointer to the thread
                        LERR_(fatal)
                                << "lcos::counting_semaphore::~counting_semaphore:"
                                << " pending thread: "
                                << get_thread_state_name(threads::get_thread_state(id))
                                << "(" << id << "): " << threads::get_thread_description(id);

                        // forcefully abort thread, do not throw
                        error_code ec(lightweight);
                        threads::set_thread_state(id, threads::pending,
                            threads::wait_abort, threads::thread_priority_default, ec);
                        if (ec)
                        {
                            LERR_(fatal)
                                << "lcos::counting_semaphore::~counting_semaphore:"
                                << " could not abort thread: "
                                << get_thread_state_name(threads::get_thread_state(id))
                                << "(" << id << "): " << threads::get_thread_description(id);
                        }
                    }
                }
            }
Exemplo n.º 5
0
//--------------------------------------------------------------------------
static void display_thrinfo(const td_thrinfo_t &thi)
{
  msg("  tid         : %lx\n", thi.ti_tid);
  msg("  tls         : %lx\n", (size_t)thi.ti_tls);
  msg("  entry       : %lx\n", (size_t)thi.ti_startfunc);
  msg("  stackbase   : %lx\n", (size_t)thi.ti_stkbase);
  msg("  stacksize   : %lx\n", thi.ti_stksize);
  msg("  state       : %s\n", get_thread_state_name(thi.ti_state));
  msg("  suspended   : %d\n", thi.ti_db_suspended);
  msg("  type        : %s\n", get_thread_type_name(thi.ti_type));
  msg("  priority    : %d\n", thi.ti_pri);
  msg("  kernel pid  : %d\n", thi.ti_lid); // lwpid_t
  msg("  signal mask : %lx\n", *(size_t*)&thi.ti_sigmask);
  msg("  traceme     : %d\n", thi.ti_traceme);
  msg("  pending sg  : %s\n", get_sigset_str(thi.ti_pending));
  msg("  enabled ev  : %s\n", get_thr_events_str(thi.ti_events));
}
Exemplo n.º 6
0
inline void create_thread(
    policies::scheduler_base* scheduler, thread_init_data& data,
    threads::thread_id_type& id,
    thread_state_enum initial_state = pending,
    bool run_now = true, error_code& ec = throws)
{
    // verify parameters
    switch (initial_state) {
    case pending:
    case pending_do_not_schedule:
    case suspended:
        break;

    default:
    {
        std::ostringstream strm;
        strm << "invalid initial state: "
             << get_thread_state_name(initial_state);
        HPX_THROWS_IF(ec, bad_parameter,
                      "threads::detail::create_thread",
                      strm.str());
        return;
    }
    }

#ifdef HPX_HAVE_THREAD_DESCRIPTION
    if (!data.description)
    {
        HPX_THROWS_IF(ec, bad_parameter,
                      "threads::detail::create_thread", "description is nullptr");
        return;
    }
#endif

    thread_self* self = get_self_ptr();

#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
    if (nullptr == data.parent_id) {
        if (self)
        {
            data.parent_id = threads::get_self_id().get();
            data.parent_phase = self->get_thread_phase();
        }
    }
    if (0 == data.parent_locality_id)
        data.parent_locality_id = get_locality_id();
#endif

    if (nullptr == data.scheduler_base)
        data.scheduler_base = scheduler;

    // Pass critical priority from parent to child.
    if (self)
    {
        if (thread_priority_critical == threads::get_self_id()->get_priority())
            data.priority = thread_priority_critical;
    }

    // create the new thread
    std::size_t num_thread = data.num_os_thread;
    scheduler->create_thread(data, &id, initial_state, run_now, ec, num_thread);

    LTM_(info) << "register_thread(" << id << "): initial_state("
               << get_thread_state_name(initial_state) << "), "
               << "run_now(" << (run_now ? "true" : "false")
#ifdef HPX_HAVE_THREAD_DESCRIPTION
               << "), description(" << data.description
#endif
               << ")";

    // potentially wake up waiting thread
    scheduler->do_some_work(num_thread);
}
Exemplo n.º 7
0
    bool dump_suspended_threads(std::size_t num_thread,
        Map& tm, boost::int64_t& idle_loop_count, bool running)
    {
#ifndef HPX_THREAD_MINIMAL_DEADLOCK_DETECTION
        HPX_UNUSED(tm);
        HPX_UNUSED(idle_loop_count);
        HPX_UNUSED(running); //-V601
        return false;
#else
        if (!minimal_deadlock_detection)
            return false;
        if (HPX_LIKELY(idle_loop_count++ < HPX_IDLE_LOOP_COUNT_MAX))
            return false;

        // reset idle loop count
        idle_loop_count = 0;

        bool result = false;
        bool collect_suspended = true;

        bool logged_headline = false;
        typename Map::const_iterator end = tm.end();
        for (typename Map::const_iterator it = tm.begin(); it != end; ++it)
        {
            threads::thread_data const* thrd = (*it).get();
            threads::thread_state state = thrd->get_state();
            threads::thread_state marked_state = thrd->get_marked_state();

            if (state != marked_state) {
                // log each thread only once
                if (!logged_headline) {
                    if (running) {
                        LTM_(error) //-V128
                            << "Listing suspended threads while queue ("
                            << num_thread << ") is empty:";
                    }
                    else {
                        LHPX_CONSOLE_(hpx::util::logging::level::error) //-V128
                            << "  [TM] Listing suspended threads while queue ("
                            << num_thread << ") is empty:\n";
                    }
                    logged_headline = true;
                }

                if (running) {
                    LTM_(error) << "queue(" << num_thread << "): " //-V128
                                << get_thread_state_name(state)
                                << "(" << std::hex << std::setw(8)
                                    << std::setfill('0') << (*it).get()
                                << "." << std::hex << std::setw(2)
                                    << std::setfill('0') << thrd->get_thread_phase()
                                << "/" << std::hex << std::setw(8)
                                    << std::setfill('0') << thrd->get_component_id()
                                << ")"
#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
                                << " P" << std::hex << std::setw(8)
                                    << std::setfill('0') << thrd->get_parent_thread_id()
#endif
                                << ": " << thrd->get_description()
                                << ": " << thrd->get_lco_description();
                }
                else {
                    LHPX_CONSOLE_(hpx::util::logging::level::error) << "  [TM] " //-V128
                                << "queue(" << num_thread << "): "
                                << get_thread_state_name(state)
                                << "(" << std::hex << std::setw(8)
                                    << std::setfill('0') << (*it).get()
                                << "." << std::hex << std::setw(2)
                                    << std::setfill('0') << thrd->get_thread_phase()
                                << "/" << std::hex << std::setw(8)
                                    << std::setfill('0') << thrd->get_component_id()
                                << ")"
#ifdef HPX_HAVE_THREAD_PARENT_REFERENCE
                                << " P" << std::hex << std::setw(8)
                                    << std::setfill('0') << thrd->get_parent_thread_id()
#endif
                                << ": " << thrd->get_description()
                                << ": " << thrd->get_lco_description() << "\n";
                }
                thrd->set_marked_state(state);

                // result should be true if we found only suspended threads
                if (collect_suspended) {
                    switch(state.get_state()) {
                    case threads::suspended:
                        result = true;    // at least one is suspended
                        break;

                    case threads::pending:
                    case threads::active:
                        result = false;   // one is active, no deadlock (yet)
                        collect_suspended = false;
                        break;

                    default:
                        // If the thread is terminated we don't care too much
                        // anymore.
                        break;
                    }
                }
            }
        }
        return result;
#endif
    }
Exemplo n.º 8
0
    inline threads::thread_id_type create_thread(
        policies::scheduler_base* scheduler,
        thread_init_data& data, thread_state_enum initial_state = pending,
        bool run_now = true, error_code& ec = throws)
    {
        // verify parameters
        switch (initial_state) {
        case pending:
        case suspended:
            break;

        default:
            {
                hpx::util::osstream strm;
                strm << "invalid initial state: "
                     << get_thread_state_name(initial_state);
                HPX_THROWS_IF(ec, bad_parameter,
                    "threads::detail::create_thread",
                    hpx::util::osstream_get_string(strm));
                return invalid_thread_id;
            }
        }

#if HPX_THREAD_MAINTAIN_DESCRIPTION
        if (0 == data.description)
        {
            HPX_THROWS_IF(ec, bad_parameter,
                "threads::detail::create_thread", "description is NULL");
            return invalid_thread_id;
        }
#endif

#if HPX_THREAD_MAINTAIN_PARENT_REFERENCE
        if (0 == data.parent_id) {
            thread_self* self = get_self_ptr();
            if (self)
            {
                data.parent_id = threads::get_self_id().get();
                data.parent_phase = self->get_thread_phase();
            }
        }
        if (0 == data.parent_locality_id)
            data.parent_locality_id = get_locality_id();
#endif

        if (0 == data.scheduler_base)
            data.scheduler_base = scheduler;

        // create the new thread
        thread_id_type newid = scheduler->create_thread(
            data, initial_state, run_now, ec, data.num_os_thread);

        LTM_(info) << "register_thread(" << newid << "): initial_state("
                   << get_thread_state_name(initial_state) << "), "
                   << "run_now(" << (run_now ? "true" : "false")
#if HPX_THREAD_MAINTAIN_DESCRIPTION
                   << "), description(" << data.description
#endif
                   << ")";

        return newid;
    }
Exemplo n.º 9
0
    inline thread_state set_thread_state(
        thread_id_type const& thrd, thread_state_enum new_state,
        thread_state_ex_enum new_state_ex, thread_priority priority,
        std::size_t thread_num, error_code& ec)
    {
        if (HPX_UNLIKELY(!thrd)) {
            HPX_THROWS_IF(ec, null_thread_id, "threads::detail::set_thread_state",
                "NULL thread id encountered");
            return thread_state(unknown);
        }

        // set_state can't be used to force a thread into active state
        if (new_state == threads::active) {
            std::ostringstream strm;
            strm << "invalid new state: " << get_thread_state_name(new_state);
            HPX_THROWS_IF(ec, bad_parameter, "threads::detail::set_thread_state",
                strm.str());
            return thread_state(unknown);
        }

        // we know that the id is actually the pointer to the thread
        if (!thrd) {
            if (&ec != &throws)
                ec = make_success_code();
            return thread_state(terminated);     // this thread has already been terminated
        }

        thread_state previous_state;
        do {
            // action depends on the current state
            previous_state = thrd->get_state();
            thread_state_enum previous_state_val = previous_state;

            // nothing to do here if the state doesn't change
            if (new_state == previous_state_val) {
                LTM_(warning)
                    << "set_thread_state: old thread state is the same as new "
                       "thread state, aborting state change, thread("
                    << thrd.get() << "), description("
                    << thrd->get_description() << "), new state("
                    << get_thread_state_name(new_state) << ")";

                if (&ec != &throws)
                    ec = make_success_code();

                return thread_state(new_state);
            }

            // the thread to set the state for is currently running, so we
            // schedule another thread to execute the pending set_state
            switch (previous_state_val) {
            case active:
                {
                    // schedule a new thread to set the state
                    LTM_(warning)
                        << "set_thread_state: thread is currently active, scheduling "
                            "new thread, thread(" << thrd.get() << "), description("
                        << thrd->get_description() << "), new state("
                        << get_thread_state_name(new_state) << ")";

                    thread_init_data data(
                        boost::bind(&set_active_state,
                            thrd, new_state, new_state_ex,
                            priority, previous_state),
                        "set state for active thread", 0, priority);

                    create_work(thrd->get_scheduler_base(), data, pending, ec);

                    if (&ec != &throws)
                        ec = make_success_code();

                    return previous_state;     // done
                }
                break;
            case terminated:
                {
                    LTM_(warning)
                        << "set_thread_state: thread is terminated, aborting state "
                            "change, thread(" << thrd.get() << "), description("
                        << thrd->get_description() << "), new state("
                        << get_thread_state_name(new_state) << ")";

                    if (&ec != &throws)
                        ec = make_success_code();

                    // If the thread has been terminated while this set_state was
                    // pending nothing has to be done anymore.
                    return previous_state;
                }
                break;
            case pending:
                if (suspended == new_state) {
                    // we do not allow explicit resetting of a state to suspended
                    // without the thread being executed.
                    std::ostringstream strm;
                    strm << "set_thread_state: invalid new state, can't demote a "
                            "pending thread, "
                         << "thread(" << thrd.get() << "), description("
                         << thrd->get_description() << "), new state("
                         << get_thread_state_name(new_state) << ")";

                    LTM_(fatal) << strm.str();

                    HPX_THROWS_IF(ec, bad_parameter,
                        "threads::detail::set_thread_state",
                        strm.str());
                    return thread_state(unknown);
                }
                break;
            case suspended:
                break;      // fine, just set the new state
            default:
                HPX_ASSERT(false);    // should not happen
                break;
            }

            // If the previous state was pending we are supposed to remove the
            // thread from the queue. But in order to avoid linearly looking
            // through the queue we defer this to the thread function, which
            // at some point will ignore this thread by simply skipping it
            // (if it's not pending anymore).

            LTM_(info) << "set_thread_state: thread(" << thrd.get() << "), "
                          "description(" << thrd->get_description() << "), "
                          "new state(" << get_thread_state_name(new_state) << "), "
                          "old state(" << get_thread_state_name(previous_state_val)
                       << ")";

            // So all what we do here is to set the new state.
            if (thrd->restore_state(new_state, previous_state)) {
                thrd->set_state_ex(new_state_ex);
                break;
            }

            // state has changed since we fetched it from the thread, retry
            LTM_(error)
                << "set_thread_state: state has been changed since it was fetched, "
                   "retrying, thread(" << thrd.get() << "), "
                   "description(" << thrd->get_description() << "), "
                   "new state(" << get_thread_state_name(new_state) << "), "
                   "old state(" << get_thread_state_name(previous_state_val)
                << ")";
        } while (true);

        if (new_state == pending) {
            // REVIEW: Passing a specific target thread may interfere with the
            // round robin queuing.
            thrd->get_scheduler_base()->schedule_thread(thrd.get(), thread_num, priority);
            thrd->get_scheduler_base()->do_some_work(thread_num);
        }

        if (&ec != &throws)
            ec = make_success_code();

        return previous_state;
    }