failure MODULE_NOT_FOUND "Boot module not found.",
failure DRIVER_ALREADY_STARTED "Driver for this type of device is already running.",
failure DRIVER_NOT_AUTO "Driver not declared as auto in menu.lst.",
+ failure WAITING_FOR_ACPI "Unable to wait for ACPI",
+ failure QUERY_LOCAL_APIC "Unable to query local APIC.",
+
};
+
// errors generated by THC
errors thc THC_ {
failure CANCELED "Operation canceled",
errval_t oct_set_get(oct_mode_t, char**, const char*, ...);
errval_t oct_del(const char*, ...);
errval_t oct_exists(const char*, ...);
+errval_t oct_wait_for(char**, const char*, ...);
errval_t oct_read(const char*, const char*, ...);
free(buf);
return err;
}
+
+/**
+ * \brief Waits until a given record exists.
+ *
+ * \param record Record that matched the query, callee has to free this.
+ * \param query Format of record to wait for.
+ * \param ... Additional arguments to format query.
+ *
+ * \note This call blocks on the octopus RPC waitset if the record is not there yet.
+ *
+ * \retval SYS_ERR_OK
+ */
+errval_t oct_wait_for(char** record, const char *query, ...)
+{
+ assert(query != NULL);
+ errval_t err = SYS_ERR_OK;
+ va_list args;
+
+ char* buf = NULL;
+ FORMAT_QUERY(query, args, buf);
+
+ struct octopus_thc_client_binding_t* cl = oct_get_thc_client();
+
+ errval_t error_code;
+ err = cl->call_seq.wait_for(cl, buf, record, &error_code);
+ if (err_is_fail(err)) {
+ goto out;
+ }
+ err = error_code;
+
+out:
+ free(buf);
+ return err;
+}
USER_PANIC_ERR(err, "Watching PCI devices.");
}
- // XXX: This is a bit silly, I add this record
- // because it was previously in spawnd so
- // there may be code out there who relies on this
- // It might be better to get rid of this completely
- err = oct_set("all_spawnds_up { iref: 0 }");
- assert(err_is_ok(err));
+ err = wait_for_all_spawnds();
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "Unable to wait for spawnds failed.");
+ }
+
#elif __pandaboard__
printf("Kaluga running on Pandaboard.\n");
#include "kaluga.h"
-//static coreid_t core_counter = 1;
-
static void cpu_change_event(octopus_mode_t mode, char* record, void* state)
{
if (mode & OCT_ON_SET) {
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)
{
- static char* local_apics = "r'hw\\.processor\\.[0-9]+' { processor_id: _, "
- " enabled: 1, "
- " apic_id: _, "
- " barrelfish_id: _ }";
- octopus_trigger_id_t tid;
+ octopus_trigger_id_t tid;
return oct_trigger_existing_and_watch(local_apics, cpu_change_event, NULL, &tid);
}
return err;
}
+
+
+static void spawnd_change_event(octopus_mode_t mode, char* record, void* state)
+{
+ size_t count = (size_t) state;
+ static coreid_t spawnd_counter = 0;
+
+ if (mode & OCT_ON_SET) {
+ KALUGA_DEBUG("spawnd found: %s\n", record);
+ spawnd_counter++;
+
+ if (spawnd_counter == count) {
+ KALUGA_DEBUG("Found enough spawnds, setting all_spawnds_up\n");
+ errval_t err = oct_set("all_spawnds_up { iref: 0 }");
+ assert(err_is_ok(err));
+ }
+ }
+}
+
+errval_t wait_for_all_spawnds(void)
+{
+ // Note: The whole wait for all_spawnds_up thing is a hack.
+ // Our overall design goal is a system where cores
+ // come and go dynamically and we do not want / need
+ // to wait for a stable state.
+ // However, some of our code (for example domain spanning)
+ // still assumes a fixed set of cores and will deadlock
+ // otherwise. Therefore we need to fix those parts first.
+
+
+ KALUGA_DEBUG("Waiting for acpi");
+ char* record = NULL;
+ errval_t err = oct_wait_for(&record, "acpi { iref: _ }");
+ free(record);
+ if (err_is_fail(err)) {
+ return err_push(err, KALUGA_ERR_WAITING_FOR_ACPI);
+ }
+
+ // No we should be able to get core count
+ // of all cores to estimate the amount of
+ // spawnd's we have to expect (one per core)
+ char** names;
+ size_t count;
+ err = oct_get_names(&names, &count, local_apics);
+ if (err_is_fail(err)) {
+ return err_push(err, KALUGA_ERR_QUERY_LOCAL_APIC);
+ }
+ oct_free_names(names, count);
+
+ static char* spawnds = "r'spawn.[0-9]+' { iref: _ }";
+ octopus_trigger_id_t tid;
+ return oct_trigger_existing_and_watch(spawnds, spawnd_change_event, (void*)count, &tid);
+}
\ No newline at end of file
#include <errors/errno.h>
errval_t watch_for_cores(void);
+errval_t wait_for_all_spawnds(void);
errval_t start_boot_driver(coreid_t where,
struct module_info* mi,
char* record);
octopus_BINDING_EVENT, OCT_ON_SET, spawnd_up_event, state);
// Construct service name
- static char* format = "spawn.%hhu { iref: _ }";
+ static char* format = "spawn.%"PRIuCOREID" { iref: _ }";
int length = snprintf(NULL, 0, format, core);
char* query = malloc(length+1);
snprintf(query, length+1, format, core);