Merge branch 'master' of ssh://code.systems.ethz.ch:8006/diffusion/BFI/barrelfish
authorAdam Turowski <adam.turowski@inf.ethz.ch>
Tue, 26 Jul 2016 11:58:57 +0000 (13:58 +0200)
committerAdam Turowski <adam.turowski@inf.ethz.ch>
Tue, 26 Jul 2016 11:58:57 +0000 (13:58 +0200)
Signed-off-by: Adam Turowski <adam.turowski@inf.ethz.ch>

12 files changed:
1  2 
errors/errno.fugu
if/acpi.if
include/barrelfish_kpi/dispatcher_shared.h
lib/barrelfish/debug.c
lib/barrelfish/waitset.c
lib/pci/pci_client.c
usr/acpi/acpi_service.c
usr/drivers/cpuboot/main.c
usr/drivers/cpuboot/x86boot.c
usr/kaluga/start_cpu.c
usr/pci/pci.c
usr/pci/pci_service.c

Simple merge
diff --cc if/acpi.if
@@@ -39,6 -39,9 +39,9 @@@ interface acpi "acpi RPC Interface" 
      rpc reset(out errval err);
      rpc sleep(in uint32 state, out errval err);
  
 -    rpc get_handle(in string devid, out uint64 handle, out errval err);
 -    rpc eval_integer(in uint64 handle, in string path, out uint64 val, out errval err); 
++    rpc get_handle(in String devid[2048], out uint64 handle, out errval err);
++    rpc eval_integer(in uint64 handle, in String path[2048], out uint64 val, out errval err);
      // Kludge: retrieve frame cap to VBE BIOS;
      rpc get_vbe_bios_cap(out errval err, out cap cap, out uint32 size);
  
Simple merge
@@@ -213,162 -183,217 +213,173 @@@ void arranet_polling_loop_proxy(void
      USER_PANIC("Network polling not available without Arranet!\n");
  }
  
+ void poll_ahci(struct waitset_chanstate *) __attribute__((weak));
+ void poll_ahci(struct waitset_chanstate *chan)
+ {
+     errval_t err = waitset_chan_trigger(chan);
+     assert(err_is_ok(err)); // should not be able to fail
+ }
 -/// Helper function that knows how to poll the given channel, based on its type
 -static void poll_channel(struct waitset_chanstate *chan)
 -{
 -    switch (chan->chantype) {
 +/// Check polled channels
 +void poll_channels_disabled(dispatcher_handle_t handle) {
 +    struct dispatcher_generic *dp = get_dispatcher_generic(handle);
 +    struct waitset_chanstate *chan;
 +
 +    if (!dp->polled_channels)
 +        return;
 +    chan = dp->polled_channels;
 +    do {
 +        switch (chan->chantype) {
  #ifdef CONFIG_INTERCONNECT_DRIVER_UMP
 -    case CHANTYPE_UMP_IN:
 -        ump_endpoint_poll(chan);
 -        break;
 +        case CHANTYPE_UMP_IN: {
 +            if (ump_endpoint_poll(chan)) {
 +                errval_t err = waitset_chan_trigger_disabled(chan, handle);
 +                assert(err_is_ok(err)); // should not fail
 +                if (!dp->polled_channels) // restart scan
 +                    return;
 +                chan = dp->polled_channels;
 +                continue;
 +            } else
 +                chan = chan->polled_next;
 +        } break;
  #endif // CONFIG_INTERCONNECT_DRIVER_UMP
 -
 -    case CHANTYPE_LWIP_SOCKET:
 -        arranet_polling_loop_proxy();
 -        break;
 -
 -    case CHANTYPE_AHCI:
 -        poll_ahci(chan);
 -        break;
 -
 -    default:
 -        assert(!"invalid channel type to poll!");
 -    }
 +        case CHANTYPE_LWIP_SOCKET:
 +            arranet_polling_loop_proxy();
 +            break;
++        case CHANTYPE_AHCI:
++            poll_ahci(chan);
++            break;
 +        default:
 +            assert(!"invalid channel type to poll!");
 +        }
 +    } while (chan != dp->polled_channels);
  }
  
 -// pollcycles_*: arch-specific implementation for polling.
 -//               Used by get_next_event().
 -//
 -//   pollcycles_reset()  -- return the number of pollcycles we want to poll for
 -//   pollcycles_update() -- update the pollcycles variable. This is needed for
 -//                          implementations where we don't have a cycle counter
 -//                          and we just count the number of polling operations
 -//                          performed
 -//   pollcycles_expired() -- check if pollcycles have expired
 -//
 -// We might want to move them to architecture-specific files, and/or create a
 -// cleaner interface. For now, I just wanted to keep them out of
 -// get_next_event()
 -
 -#if defined(__ARM_ARCH_7A__) && defined(__GNUC__) \
 -      && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && __GNUC_PATCHLEVEL__ <= 3
 -static __attribute__((noinline, unused))
 -#else
 -static inline
 -#endif
 -cycles_t pollcycles_reset(void)
 +/// Re-register a channel (if persistent)
 +static void reregister_channel(struct waitset *ws, struct waitset_chanstate *chan,
 +                                dispatcher_handle_t handle)
  {
 -    cycles_t pollcycles;
 -#if defined(__arm__) && !defined(__gem5__)
 -    reset_cycle_counter();
 -    pollcycles = waitset_poll_cycles;
 -#elif defined(__arm__) && defined(__gem5__)
 -    pollcycles = 0;
 -#elif defined(__aarch64__) && defined(__gem5__)
 -    pollcycles = 0;
 -#else
 -    pollcycles = cyclecount() + waitset_poll_cycles;
 -#endif
 -    return pollcycles;
 -}
 +    assert(chan->waitset == ws);
 +    if (chan->state == CHAN_PENDING) {
 +        dequeue(&ws->pending, chan);
 +    } else {
 +        assert(chan->state == CHAN_WAITING);
 +        dequeue(&ws->waiting, chan);
 +    }
  
 -#if defined(__ARM_ARCH_7A__) && defined(__GNUC__) \
 -      && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && __GNUC_PATCHLEVEL__ <= 3
 -static __attribute__((noinline, unused))
 -#else
 -static inline
 -#endif
 -cycles_t pollcycles_update(cycles_t pollcycles)
 -{
 -    cycles_t ret = pollcycles;
 -    #if defined(__arm__) && defined(__gem5__)
 -    ret++;
 -      #elif defined(__aarch64__) && defined(__gem5__)
 -      ret++;
 -    #endif
 -    return ret;
 +    chan->token = 0;
-     if (chan->chantype == CHANTYPE_UMP_IN) {
++    if (chan->chantype == CHANTYPE_UMP_IN
++        || chan->chantype == CHANTYPE_LWIP_SOCKET 
++        || chan->chantype == CHANTYPE_AHCI) {
 +        enqueue(&ws->polled, chan);
 +        enqueue_polled(&get_dispatcher_generic(handle)->polled_channels, chan);
 +        chan->state = CHAN_POLLED;
 +    } else {
 +        enqueue(&ws->idle, chan);
 +        chan->state = CHAN_IDLE;
 +    }
  }
  
 -#if defined(__ARM_ARCH_7A__) && defined(__GNUC__) \
 -      && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && __GNUC_PATCHLEVEL__ <= 3
 -static __attribute__((noinline, unused))
 -#else
 -static inline
 -#endif
 -bool pollcycles_expired(cycles_t pollcycles)
 +/// Find a thread that is able to receive an event
 +static struct thread * find_recipient(struct waitset *ws,
 +                        struct waitset_chanstate *channel, struct thread *me)
  {
 -    bool ret;
 -    #if defined(__arm__) && !defined(__gem5__)
 -    ret = (cyclecount() > pollcycles || is_cycle_counter_overflow());
 -    #elif defined(__arm__) && defined(__gem5__)
 -    ret = pollcycles >= POLL_COUNT;
 -    #elif defined(__aarch64__) && defined(__gem5__)
 -    ret = pollcycles >= POLL_COUNT;
 -    #else
 -    ret = cyclecount() > pollcycles;
 -    #endif
 -    return ret;
 +    struct thread *t = ws->waiting_threads;
 +
 +    if (!t)
 +        return NULL;
 +    do {
 +        if (waitset_check_token(channel, t))
 +            return t;
 +        t = t->next;
 +    } while (t != ws->waiting_threads);
 +    return ws->waiting_threads;
  }
  
 -static errval_t get_next_event_debug(struct waitset *ws,
 -        struct event_closure *retclosure, bool debug)
 +/// Wake up other thread if there's more pending events
 +static void wake_up_other_thread(dispatcher_handle_t handle, struct waitset *ws)
  {
 -    struct waitset_chanstate *chan;
 -    bool was_polling = false;
 -    cycles_t pollcycles;
 -
 -    assert(ws != NULL);
 -    assert(retclosure != NULL);
 -
 -    // unconditionally disable ourselves and check for events
 -    // if we decide we have to start polling, we'll jump back up here
 -    goto check_for_events;
 -
 -    /* ------------ POLLING LOOP; RUNS WHILE ENABLED ------------ */
 -polling_loop:
 -    was_polling = true;
 -    assert(ws->polling); // this thread is polling
 -    // get the amount of cycles we want to poll for
 -    pollcycles = pollcycles_reset();
 -
 -    // while there are no pending events, poll channels
 -    while (ws->polled != NULL && ws->pending == NULL) {
 -        struct waitset_chanstate *nextchan = NULL;
 -        // NB: Polling policy is to return as soon as a pending event
 -        // appears, not bother looking at the rest of the polling queue
 -        for (chan = ws->polled;
 -             chan != NULL && chan->waitset == ws && chan->state == CHAN_POLLED
 -                 && ws->pending == NULL;
 -             chan = nextchan) {
 -
 -            nextchan = chan->next;
 -            poll_channel(chan);
 -            // update pollcycles
 -            pollcycles = pollcycles_update(pollcycles);
 -            // yield the thread if we exceed the cycle count limit
 -            if (ws->pending == NULL && pollcycles_expired(pollcycles)) {
 -                if (debug) {
 -                if (strcmp(disp_name(), "netd") != 0) {
 -                    // Print the callback trace so that we know which call is leading
 -                    // the schedule removal and
 -                    printf("%s: callstack: %p %p %p %p\n", disp_name(),
 -                            __builtin_return_address(0),
 -                            __builtin_return_address(1),
 -                            __builtin_return_address(2),
 -                            __builtin_return_address(3));
 -                }
 -
 -                }
 -                thread_yield();
 -                pollcycles = pollcycles_reset();
 -            }
 -        }
 +    if (ws->pending && ws->waiting_threads) {
 +        struct thread *t;
  
 -        // ensure that we restart polling from the place we left off here,
 -        // if the next channel is a valid one
 -        if (nextchan != NULL && nextchan->waitset == ws
 -            && nextchan->state == CHAN_POLLED) {
 -            ws->polled = nextchan;
 -        }
 +        t = thread_unblock_one_disabled(handle, &ws->waiting_threads, NULL);
 +        assert_disabled(t == NULL); // shouldn't see a remote thread
      }
 +}
  
 -    /* ------------ STATE MACHINERY; RUNS WHILE DISABLED ------------ */
 -check_for_events: ;
 -    dispatcher_handle_t handle = disp_disable();
 +/**
 + * \brief Get next pending event
 + *
 + * Check if there is a pending event that matches current thread and return it.
 + * Pending events are in a pending queue and in a waiting queue.
 + * A pending event then will be removed from a pending/waiting queue and become
 + * unregistered or, if it's persistent, will be re-registered to an idle queue
 + * or a polled queue (UMP channels) of a waitset.
 + * If there's no pending event, block this thread.
 + * If there's a pending event but it doesn't match our thread, don't remove it
 + * from a pending queue and wake up a matching thread.
 + * If there's no matching thread, add it to a waiting queue.
 + *
 + * \param ws Waitset with sources of events
 + * \param retchannel Holder of returned event
 + * \param retclosure Holder of returned closure
 + * \param waitfor Specific event that we're waiting for (can be NULL)
 + * \param handle Dispatcher's handle
 + * \param debug Debug mode (not used)
 + */
  
 -    // are there any pending events on the waitset?
 -    chan = get_pending_event_disabled(ws);
 -    if (chan != NULL) {
 -        // if we need to poll, and we have a blocked thread, wake it up to do so
 -        if (was_polling && ws->polled != NULL && ws->waiting_threads != NULL) {
 -            // start a blocked thread polling
 -            struct thread *t;
 -            t = thread_unblock_one_disabled(handle, &ws->waiting_threads, NULL);
 -            assert_disabled(t == NULL); // shouldn't see a remote thread
 -        } else if (was_polling) {
 -            // I'm stopping polling, and there is nobody else
 -            assert_disabled(ws->polling);
 -            ws->polling = false;
 +errval_t get_next_event_disabled(struct waitset *ws,
 +    struct waitset_chanstate **retchannel, struct event_closure *retclosure,
 +    struct waitset_chanstate *waitfor, dispatcher_handle_t handle, bool debug)
 +{
 +    struct waitset_chanstate * chan;
 +
 +    for (;;) {
 +        chan = get_pending_event_disabled(ws, waitfor); // get our event
 +        if (chan) {
 +            *retchannel = chan;
 +            *retclosure = chan->closure;
 +            chan->wait_for = NULL;
 +            chan->token = 0;
 +            if (chan->persistent)
 +                reregister_channel(ws, chan, handle);
 +            else
 +                waitset_chan_deregister_disabled(chan, handle);
 +            wake_up_other_thread(handle, ws);
 +            return SYS_ERR_OK;
          }
 -        disp_enable(handle);
 -
 -        *retclosure = chan->closure;
 -        return SYS_ERR_OK;
 -    }
 -
 -    // If we got here and there are channels to poll but no-one is polling,
 -    // then either we never polled, or we lost a race on the channel we picked.
 -    // Either way, we'd better start polling again.
 -    if (ws->polled != NULL && (was_polling || !ws->polling)) {
 -        if (!was_polling) {
 -            ws->polling = true;
 +        chan = ws->pending; // check a pending queue
 +        if (!chan) { // if nothing then wait
 +            thread_block_disabled(handle, &ws->waiting_threads);
 +            disp_disable();
 +        } else { // something but it's not our event
 +            if (!ws->waiting_threads) { // no other thread interested in
 +                dequeue(&ws->pending, chan);
 +                enqueue(&ws->waiting, chan);
 +                chan->state = CHAN_WAITING;
 +                chan->waitset = ws;
 +            } else {
 +                // find a matching thread
 +                struct thread *t;
 +                for (t = ws->waiting_threads; t; ) {
 +                    if (waitset_check_token(chan, t)) { // match found, wake it
 +                        ws->waiting_threads = t;
 +                        t = thread_unblock_one_disabled(handle,
 +                                                    &ws->waiting_threads, chan);
 +                        assert_disabled(t == NULL); // shouldn't see a remote thread
 +                        break;
 +                    }
 +                    t = t->next;
 +                    if (t == ws->waiting_threads) { // no recipient found
 +                        dequeue(&ws->pending, chan);
 +                        enqueue(&ws->waiting, chan);
 +                        chan->state = CHAN_WAITING;
 +                        chan->waitset = ws;
 +                        break;
 +                    }
 +                }
 +            }
          }
 -        disp_enable(handle);
 -        goto polling_loop;
 -    }
 -
 -    // otherwise block awaiting an event
 -    chan = thread_block_disabled(handle, &ws->waiting_threads);
 -
 -    if (chan == NULL) {
 -        // not a real event, just a wakeup to get us to start polling!
 -        assert(ws->polling);
 -        goto polling_loop;
 -    } else {
 -        *retclosure = chan->closure;
 -        return SYS_ERR_OK;
      }
  }
  
Simple merge
Simple merge
@@@ -165,13 -168,15 +167,13 @@@ static int list_cpu(int argc, char **ar
          err = oct_get(&record, names[i]);
          assert(err_is_ok(err));
  
-         uint64_t barrelfish_id, apic_id, processor_id, enabled;
-         err = oct_read(record, "_ { barrelfish_id: %d, apic_id: %d, processor_id: %d, enabled: %d }",
-                        &barrelfish_id, &apic_id, &processor_id, &enabled);
+         uint64_t barrelfish_id, hw_id, enabled, type;
+         err = oct_read(record, "_ { " HW_PROCESSOR_GENERIC_FIELDS "}",
+                        &enabled, &barrelfish_id, &hw_id, &type);
          assert(err_is_ok(err));
  
-         printf("CPU %"PRIu64": APIC_ID=%"PRIu64" APIC_PROCESSOR_ID=%"PRIu64" ENABLED=%"PRIu64"\n",
-                barrelfish_id, apic_id, processor_id, enabled);
+         printf("CPU %"PRIu64": HW_ID=%"PRIu64" TYPE=%s ENABLED=%"PRIu64"\n",
+                barrelfish_id, hw_id, cpu_type_to_archstr(type), enabled);
 -
 -        free(record);
      }
      if (len == 0) {
          DEBUG("%s:%s:%d: No cpus found?\n",
Simple merge
@@@ -63,13 -67,9 +67,8 @@@ static void cpu_change_event(octopus_mo
  
  out:
      assert(!(mode & OCT_REMOVED));
 -    free(record);
  }
  
- static char* local_apics = "r'hw\\.processor\\.[0-9]+' { processor_id: _, "
-                            "                             enabled: 1, "
-                            "                             apic_id: _, "
-                            "                             barrelfish_id: _ }";
  errval_t watch_for_cores(void)
  {
      octopus_trigger_id_t tid;
diff --cc usr/pci/pci.c
Simple merge
Simple merge