Ejemplo n.º 1
0
static void*
wait_for_wakeup(Parrot_Interp interpreter, void *next)
{
    QUEUE_ENTRY *entry;
    parrot_event* event;
    QUEUE * tq = interpreter->task_queue;
    interpreter->sleeping = 1;
    /*
     * event handler likes callbacks or timers are run as normal code
     * so inside such an even handler function another event might get
     * handled, which is good (higher priority events can interrupt
     * other event handler) OTOH we must ensure that all state changes
     * are done in do_event and we should probably suspend nested
     * event handlers sometimes
     *
     * FIXME: the same is true for the *next param:
     *        get rid of that, instead mangle the resume flags
     *        and offset to stop the runloop
     *
     */

    while (interpreter->sleeping) {
        entry = wait_for_entry(tq);
        event = (parrot_event* )entry->data;
        mem_sys_free(entry);
        edebug((stderr, "got ev %s head : %p\n", et(event), tq->head));
        next = do_event(interpreter, event, next);
    }
    edebug((stderr, "woke up\n"));
    return next;
}
Ejemplo n.º 2
0
static void*
do_event(Parrot_Interp interpreter, parrot_event* event, void *next)
{
    edebug((stderr, "do_event %s\n", et(event)));
    switch (event->type) {
        case EVENT_TYPE_TERMINATE:
            next = NULL;        /* this will terminate the run loop */
            break;
        case EVENT_TYPE_SIGNAL:
            interpreter->sleeping = 0;
            /* generate exception */
            event_to_exception(interpreter, event);
            /* not reached - will longjmp */
            break;
        case EVENT_TYPE_TIMER:
            /* run ops, save registers */
            Parrot_runops_fromc_save(interpreter,
                    event->u.timer_event.sub);
            break;
        case EVENT_TYPE_CALL_BACK:
            edebug((stderr, "starting user cb\n"));
            Parrot_run_callback(interpreter, event->u.call_back.cbi,
                    event->u.call_back.external_data);
            break;
        case EVENT_TYPE_SLEEP:
            interpreter->sleeping = 0;
            break;
        default:
            fprintf(stderr, "Unhandled event type %d\n", event->type);
            break;
    }
    mem_sys_free(event);
    return next;
}
Ejemplo n.º 3
0
void
Parrot_schedule_broadcast_qentry(QUEUE_ENTRY* entry)
{
    Parrot_Interp interp;
    parrot_event* event;
    size_t i;

    event = entry->data;
    switch (event->type) {
        case EVENT_TYPE_SIGNAL:
            edebug((stderr, "broadcast signal\n"));
            /*
             * we don't have special signal handlers in usercode yet
             * e.g.:
             * install handler like exception handler *and*
             * set a interpreter flag, that a handler exists
             * we then could examine that flag (after LOCKing it)
             * and dispatch the exception to all interpreters that
             * handle it
             * Finally, we send the first (main) interpreter that signal
             *
             * For now just send to all.
             *
             */
            switch(event->u.signal) {
                case SIGINT:
                    if (n_interpreters) {
                        LOCK(interpreter_array_mutex);
                        for (i = 1; i < n_interpreters; ++i) {
                            edebug((stderr, "deliver SIGINT to %d\n", i));
                            interp = interpreter_array[i];
                            if (interp)
                                Parrot_schedule_interp_qentry(interp,
                                        dup_entry(entry));
                        }
                        UNLOCK(interpreter_array_mutex);
                    }
                    interp = interpreter_array[0];
                    Parrot_schedule_interp_qentry(interp, entry);
                    edebug((stderr, "deliver SIGINT to 0\n"));
                    break;
                default:
                    mem_sys_free(entry);
                    mem_sys_free(event);
            }
            break;
        default:
            mem_sys_free(entry);
            mem_sys_free(event);
            internal_exception(1, "Unknown event to broadcast");
            break;
    }
}
Ejemplo n.º 4
0
void
Parrot_schedule_interp_qentry(Parrot_Interp interpreter, QUEUE_ENTRY* entry)
{
    parrot_event* event;
    event = entry->data;
    /*
     * sleep checks events when it awakes
     */
    edebug((stderr, "got entry - schedule_inter_qentry %s\n", et(event)));
    if (event->type != EVENT_TYPE_SLEEP)
        enable_event_checking(interpreter);
    /*
     * do push_entry last - this signales the queue condition so the
     * interpreter might starting process that event immediately
     *
     * we should better use a priority for placing the event
     * in front or at the end of the queue
     */
    switch (event->type) {
        case EVENT_TYPE_CALL_BACK:
        case EVENT_TYPE_SIGNAL:
            unshift_entry(interpreter->task_queue, entry);
            break;
        default:
            push_entry(interpreter->task_queue, entry);
            break;
    }
}
Ejemplo n.º 5
0
void TH__setup_threads(const TH_thread_funptr *thfptrs){
  debug((uint16_t) thfptrs[0].fptr);
  int16_t i, n;
  debug(F("Tset:"));
  assert(thfptrs);
  TH__thread_funptrs = (TH_thread_funptr *)thfptrs;
  i = get_len_fptrs();
  sdebug(F("len:")); edebug(i);
  assert(i <= MAX_THREADS);
  TH__threads = (pthread *)malloc(sizeof(pthread) * i);
  debug((uint16_t) TH__threads);
  memcheck(TH__threads);
  for(n = 0; n < i; n++){
    //PT_INIT(&TH__threads[n]);
    //set_thread_innactive(&TH__threads[n]);
    TH__threads[n].lc = PT_INNACTIVE;
    TH__threads[n].data = NULL;
  }
  TH__threads_len = i;
  debug(F("TsetD"));
  return;
error:
  memclr(TH__threads);
  return;
}
Ejemplo n.º 6
0
static void*
event_thread(void *data)
{
    QUEUE* event_q = (QUEUE*) data;
    parrot_event* event;
    QUEUE_ENTRY *entry;
    int running = 1;

    LOCK(event_q->queue_mutex);
    /*
     * we might already have an event in the queue
     */
    if (peek_entry(event_q))
        running = process_events(event_q);
    while (running) {
        entry = peek_entry(event_q);
        if (!entry) {
            /* wait infinite until entry arrives */
            queue_wait(event_q);
        }
        else if (entry->type == QUEUE_ENTRY_TYPE_TIMED_EVENT) {
            /* do a_timedwait for entry */
            struct timespec abs_time;
            FLOATVAL when;
            event = (parrot_event* )entry->data;
            when = event->u.timer_event.abs_time;
            abs_time.tv_sec = (time_t) when;
            abs_time.tv_nsec = (when - abs_time.tv_sec) *
                (1000L*1000L*1000L);
            queue_timedwait(event_q, &abs_time);
        }
        else {
            /* we shouldn't get here probably
             */
            internal_exception(1, "Spurious event");

        }
        /*
         * one or more entries arrived - we hold the mutex again
         * so we have to use the nonsync_pop_entry to pop off event entries
         */
        running = process_events(event_q);
    } /* event loop */
    /*
     * the main interpreter is dying
     * TODO empty the queue
     */
    UNLOCK(event_q->queue_mutex);
    queue_destroy(event_q);
    stop_io_thread();
    edebug((stderr, "event thread stopped\n"));
    return NULL;
}
Ejemplo n.º 7
0
uint8_t schedule_thread(pthread *th){
  uint8_t out = false;
  TH_funptr tfun;
  sdebug(F("schT:")); edebug(get_index(th));
  assert(thread_exists(th));
  assert_raise(not is_active(th), ERR_VALUE, th->lc);
  debug("Init");
  PT_INIT(th);
  tfun = get_thread_function(get_index(th));
  assert(tfun);
  out = tfun(th);
  if(out >= PT_EXITED){
    set_thread_innactive(th);
    out = true;
    sdebug("Ts:"); edebug(get_index(th));
  }
  else{
    sdebug("Ts:"); edebug(get_index(th));
    out = true;
  }
error:
  return out;
}
Ejemplo n.º 8
0
static void*
io_thread(void *data)
{
    QUEUE* event_q = (QUEUE*) data;
    fd_set rfds, wfds;
    int n_highest;
    int running = 1;

    FD_ZERO(&rfds);
    FD_ZERO(&wfds);
    UNUSED(event_q);
    /*
     * Watch the reader end of the pipe for messages
     */
    FD_SET(PIPE_READ_FD, &rfds);
    n_highest = PIPE_READ_FD + 1;
    /*
     * all signals that we shall handle here have to be unblocked
     * in this and only in this thread
     */
    Parrot_unblock_signal(SIGINT);
    while (running) {
        int retval = select(n_highest, &rfds, &wfds, NULL, NULL);
        switch (retval) {
            case -1:
                if (errno == EINTR) {
                    edebug((stderr, "select EINTR\n"));
                    if (sig_int) {
                        edebug((stderr, "int arrived\n"));
                        sig_int = 0;
                        /*
                         * signal the event thread
                         */
                        schedule_signal_event(SIGINT);
                    }

                }
                break;
            default:
                if (retval > 0) {
                    edebug((stderr, "IO ready\n"));
                    if (FD_ISSET(PIPE_READ_FD, &rfds)) {
                        int buf[3];
                        /*
                         * a command arrived
                         */
                        edebug((stderr, "msg arrived\n"));
                        if (read(PIPE_READ_FD, buf, MSG_SIZE) != MSG_SIZE)
                            internal_exception(1,
                                    "read error from msg pipe");
                        switch (buf[0]) {
                            case 'e':
                                running = 0;
                                break;
                            /* TODO */
                            case 'r':
                                /* insert fd in buf[1] into rfds */
                            case 'w':
                                /* insert fd in buf[1] into wfds */
                            case 'R':
                                /* delete fd in buf[1] from rfds */
                            case 'W':
                                /* delete fd in buf[1] from wfds */
                                break;
                            default:
                                internal_exception(1,
                                        "unhandled msg in pipe");
                                break;
                        }

                    }
                    /* TODO check fds */
                    break;
                }
        }
    }
    edebug((stderr, "IO thread terminated\n"));
    close(PIPE_READ_FD);
    close(PIPE_WRITE_FD);
    return NULL;
}