Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure ASIO thread cannot be stopped prematurely #2612

Merged
merged 1 commit into from
Mar 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/libponyrt/asio/asio.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ bool ponyint_asio_start()

bool ponyint_asio_stop()
{
if(atomic_load_explicit(&running_base.noisy_count, memory_order_relaxed) > 0)
if(!ponyint_asio_stoppable())
return false;

if(running_base.backend != NULL)
Expand All @@ -74,6 +74,12 @@ bool ponyint_asio_stop()
return true;
}

bool ponyint_asio_stoppable()
{
// can only stop if we have no noisy actors
return atomic_load_explicit(&running_base.noisy_count, memory_order_relaxed) == 0;
}

uint64_t ponyint_asio_noisy_add()
{
return atomic_fetch_add_explicit(&running_base.noisy_count, 1, memory_order_relaxed);
Expand Down
7 changes: 7 additions & 0 deletions src/libponyrt/asio/asio.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ uint32_t ponyint_asio_get_cpu();
*/
bool ponyint_asio_stop();

/** Checks if it is safe to stop the asynchronous event mechanism.
*
* Stopping an event mechanism is only possible if there are no pending "noisy"
* subscriptions.
*/
bool ponyint_asio_stoppable();

/** Add a noisy event subscription.
*/
uint64_t ponyint_asio_noisy_add();
Expand Down
23 changes: 8 additions & 15 deletions src/libponyrt/sched/scheduler.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,18 +212,6 @@ static void handle_sched_block(scheduler_t* sched)
// handle SCHED_UNBLOCK message
static void handle_sched_unblock(scheduler_t* sched)
{
// if the ASIO thread has already been stopped
if (sched->asio_stopped)
{
// restart the ASIO thread
ponyint_asio_init(asio_cpu);
sched->asio_stopped = !ponyint_asio_start();
}

// make sure asio hasn't already been stopped or else runtime is in
// an invalid state without the ASIO thread running
pony_assert(!sched->asio_stopped);

// Cancel all acks and increment the ack token, so that any pending
// acks in the queue will be dropped when they are received.
sched->block_count--;
Expand Down Expand Up @@ -328,21 +316,26 @@ static bool quiescent(scheduler_t* sched, uint64_t tsc, uint64_t tsc2)

if(sched->ack_count >= current_active_scheduler_count)
{
if(sched->asio_stopped)
if(sched->asio_stoppable && ponyint_asio_stop())
{
// successfully stopped ASIO thread
// tell all scheduler threads to terminate
send_msg_all(sched->index, SCHED_TERMINATE, 0);

wake_suspended_threads(sched->index);

sched->ack_token++;
sched->ack_count = 0;
} else if(ponyint_asio_stop()) {
sched->asio_stopped = true;
} else if(ponyint_asio_stoppable()) {
sched->asio_stoppable = true;
sched->ack_token++;
sched->ack_count = 0;

// Run another CNF/ACK cycle.
send_msg_all_active(sched->index, SCHED_CNF, sched->ack_token);
} else {
// ASIO is not stoppable
sched->asio_stoppable = false;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/libponyrt/sched/scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ struct scheduler_t
uint32_t cpu;
uint32_t node;
bool terminate;
bool asio_stopped;
bool asio_stoppable;
bool asio_noisy;
pony_signal_event_t sleep_object;

Expand Down