Skip to content

Commit

Permalink
Switch from timer to scheduler thread for triggering cycle detector
Browse files Browse the repository at this point in the history
  • Loading branch information
dipinhora committed May 26, 2018
1 parent 5e5ad13 commit b9333aa
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 104 deletions.
20 changes: 0 additions & 20 deletions src/libponyrt/asio/epoll.c
Expand Up @@ -5,7 +5,6 @@
#ifdef ASIO_USE_EPOLL

#include "../actor/messageq.h"
#include "../gc/cycle.h"
#include "../mem/pool.h"
#include "../sched/cpu.h"
#include "../sched/scheduler.h"
Expand Down Expand Up @@ -217,8 +216,6 @@ DECLARE_THREAD_FN(ponyint_asio_backend_dispatch)
pthread_sigmask(SIG_BLOCK, &set, NULL);
#endif

asio_event_t* cd_timer_event = ponyint_cycle_create_timer();

while(!atomic_load_explicit(&b->terminate, memory_order_relaxed))
{
int event_cnt = epoll_wait(b->epfd, b->events, MAX_EVENTS, -1);
Expand Down Expand Up @@ -288,23 +285,6 @@ DECLARE_THREAD_FN(ponyint_asio_backend_dispatch)
handle_queue(b);
}

// destory cycle detector timer event
if(cd_timer_event)
{
if(cd_timer_event->fd != -1)
{
close(cd_timer_event->fd);
cd_timer_event->fd = -1;
}

// can't use pony_asio_event_destroy because it tries to
// trace the event for GC purposes and that is not a
// good idea when the actor is the cycle detector
POOL_FREE(asio_event_t, cd_timer_event);

cd_timer_event = NULL;
}

close(b->epfd);
close(b->wakeup);
ponyint_messageq_destroy(&b->q);
Expand Down
17 changes: 0 additions & 17 deletions src/libponyrt/asio/iocp.c
Expand Up @@ -6,7 +6,6 @@
#ifdef ASIO_USE_IOCP

#include "../actor/messageq.h"
#include "../gc/cycle.h"
#include "../mem/pool.h"
#include "../sched/cpu.h"
#include "../sched/scheduler.h"
Expand Down Expand Up @@ -121,8 +120,6 @@ DECLARE_THREAD_FN(ponyint_asio_backend_dispatch)
handles[0] = b->wakeup;
handles[1] = GetStdHandle(STD_INPUT_HANDLE);

asio_event_t* cd_timer_event = ponyint_cycle_create_timer();

// handleCount indicates:
// 1 => only listen on queue wake event
// 2 => listen on queue wake event and stdin
Expand Down Expand Up @@ -246,20 +243,6 @@ DECLARE_THREAD_FN(ponyint_asio_backend_dispatch)
}
}

// destory cycle detector timer event
if(cd_timer_event)
{
CancelWaitableTimer(cd_timer_event->timer);
CloseHandle(cd_timer_event->timer);

// can't use pony_asio_event_destroy because it tries to
// trace the event for GC purposes and that is not a
// good idea when the actor is the cycle detector
POOL_FREE(asio_event_t, cd_timer_event);

cd_timer_event = NULL;
}

CloseHandle(b->wakeup);
ponyint_messageq_destroy(&b->q);
POOL_FREE(asio_backend_t, b);
Expand Down
24 changes: 0 additions & 24 deletions src/libponyrt/asio/kqueue.c
Expand Up @@ -4,7 +4,6 @@

#include "../actor/messageq.h"
#include "../mem/pool.h"
#include "../gc/cycle.h"
#include "../sched/cpu.h"
#include "../sched/scheduler.h"
#include "ponyassert.h"
Expand Down Expand Up @@ -178,8 +177,6 @@ DECLARE_THREAD_FN(ponyint_asio_backend_dispatch)
pthread_sigmask(SIG_BLOCK, &set, NULL);
#endif

asio_event_t* cd_timer_event = ponyint_cycle_create_timer();

struct kevent fired[MAX_EVENTS];

while(b->kq != -1)
Expand Down Expand Up @@ -258,27 +255,6 @@ DECLARE_THREAD_FN(ponyint_asio_backend_dispatch)
handle_queue(b);
}

// destory cycle detector timer event
if(cd_timer_event)
{
struct kevent event[1];

if(cd_timer_event->flags & ASIO_TIMER)
{
EV_SET(&event[0], (uintptr_t)cd_timer_event, EVFILT_TIMER, EV_DELETE,
0, 0, cd_timer_event);
}

kevent(b->kq, event, 1, NULL, 0, NULL);

// can't use pony_asio_event_destroy because it tries to
// trace the event for GC purposes and that is not a
// good idea when the actor is the cycle detector
POOL_FREE(asio_event_t, cd_timer_event);

cd_timer_event = NULL;
}

ponyint_messageq_destroy(&b->q);
POOL_FREE(asio_backend_t, b);
pony_unregister_thread();
Expand Down
58 changes: 18 additions & 40 deletions src/libponyrt/gc/cycle.c
@@ -1,6 +1,5 @@
#define __STDC_FORMAT_MACROS
#include "cycle.h"
#include "../asio/asio.h"
#include "../actor/actor.h"
#include "../sched/scheduler.h"
#include "../ds/stack.h"
Expand Down Expand Up @@ -822,10 +821,6 @@ static void cycle_dispatch(pony_ctx_t* ctx, pony_actor_t* self,
{
// check for blocked actors/cycles
check_blocked(ctx, d);

// re-arm timer for next check
asio_msg_t* m = (asio_msg_t*)msg;
pony_asio_event_setnsec(m->event, d->detect_interval);
break;
}

Expand Down Expand Up @@ -890,7 +885,7 @@ static pony_type_t cycle_type =
NULL,
cycle_dispatch,
NULL,
ACTORMSG_CHECKBLOCKED, // event_notify
0,
NULL,
NULL,
NULL
Expand All @@ -912,8 +907,23 @@ void ponyint_cycle_create(pony_ctx_t* ctx, uint32_t detect_interval)

detector_t* d = (detector_t*)cycle_detector;

//convert to nanos
d->detect_interval = detect_interval * 1000000;
// convert to cycles for use with ponyint_cpu_tick()
// 1 second = 2000000000 cycles (approx.)
// based on same scale as ponyint_cpu_core_pause() uses
d->detect_interval = detect_interval * 2000000;
}

bool ponyint_cycle_check_blocked(pony_ctx_t* ctx, uint64_t tsc, uint64_t tsc2)
{
detector_t* d = (detector_t*)cycle_detector;

if(tsc2 - tsc > d->detect_interval)
{
pony_send(ctx, cycle_detector, ACTORMSG_CHECKBLOCKED);
return true;
}

return false;
}

void ponyint_cycle_actor_created(pony_ctx_t* ctx, pony_actor_t* actor)
Expand Down Expand Up @@ -971,35 +981,3 @@ bool ponyint_is_cycle(pony_actor_t* actor)
{
return actor == cycle_detector;
}

asio_event_t* ponyint_cycle_create_timer()
{
// if block messages are disabled don't create the timer
if(ponyint_actor_getnoblock())
return NULL;

detector_t* d = (detector_t*)cycle_detector;

// create non-noisy timer for cycle detector
// asio backend will dispose of it on shutdown
// can't use pony_asio_event_create because it tries to
// trace the event for GC purposes and that is not a
// good idea when the actor is the cycle detector
pony_type_t* type = *(pony_type_t**)cycle_detector;
uint32_t msg_id = type->event_notify;

asio_event_t* ev = POOL_ALLOC(asio_event_t);

ev->magic = ev;
ev->owner = cycle_detector;
ev->msg_id = msg_id;
ev->fd = 0;
ev->flags = ASIO_TIMER;
ev->noisy = false;
ev->nsec = d->detect_interval;
ev->writeable = false;
ev->readable = false;

pony_asio_event_subscribe(ev);
return ev;
}
5 changes: 2 additions & 3 deletions src/libponyrt/gc/cycle.h
Expand Up @@ -3,7 +3,6 @@

#include "gc.h"
#include "../pony.h"
#include "../asio/event.h"
#include <platform.h>
#include <stdint.h>
#include <stdbool.h>
Expand All @@ -12,6 +11,8 @@ PONY_EXTERN_C_BEGIN

void ponyint_cycle_create(pony_ctx_t* ctx, uint32_t detect_interval);

bool ponyint_cycle_check_blocked(pony_ctx_t* ctx, uint64_t tsc, uint64_t tsc2);

void ponyint_cycle_actor_created(pony_ctx_t* ctx, pony_actor_t* actor);

void ponyint_cycle_actor_destroyed(pony_ctx_t* ctx, pony_actor_t* actor);
Expand All @@ -26,8 +27,6 @@ void ponyint_cycle_terminate(pony_ctx_t* ctx);

bool ponyint_is_cycle(pony_actor_t* actor);

asio_event_t* ponyint_cycle_create_timer();

PONY_EXTERN_C_END

#endif
13 changes: 13 additions & 0 deletions src/libponyrt/sched/scheduler.c
Expand Up @@ -30,6 +30,7 @@ typedef enum
} sched_msg_t;

// Scheduler global data.
static uint64_t last_cd_tsc;
static uint32_t scheduler_count;
static uint32_t min_scheduler_count;
static PONY_ATOMIC(uint32_t) active_scheduler_count;
Expand Down Expand Up @@ -748,13 +749,25 @@ static pony_actor_t* steal(scheduler_t* sched)
*/
static void run(scheduler_t* sched)
{
last_cd_tsc = 0;
pony_actor_t* actor = pop_global(sched);
if (DTRACE_ENABLED(ACTOR_SCHEDULED) && actor != NULL) {
DTRACE2(ACTOR_SCHEDULED, (uintptr_t)sched, (uintptr_t)actor);
}

while(true)
{
// if we're scheduler 0 and cycle detection is enabled
// and we're not terminating
if((sched->index == 0) && !ponyint_actor_getnoblock()
&& !sched->terminate)
{
// trigger cycle detector by sending it a message if it is time
uint64_t current_tsc = ponyint_cpu_tick();
if(ponyint_cycle_check_blocked(&sched->ctx, last_cd_tsc, current_tsc))
last_cd_tsc = current_tsc;
}

// In response to reading a message, we might have unmuted an actor and
// added it back to our queue. if we don't have an actor to run, we want
// to pop from our queue to check for a recently unmuted actor
Expand Down

0 comments on commit b9333aa

Please sign in to comment.