failure DOMAIN_ALLOCATE "No more domain descriptors",
failure DOMAIN_NOTFOUND "Domain not found",
failure DOMAIN_RUNNING "Domain is running",
+
+ failure CREATE_DOMAIN_TABLE "Failed to create domain hash table",
+ failure DOMAIN_CAP_HASH "Failed to compute hash code for domain cap",
+ failure DOMAIN_TABLE_FIND "Failed to find requested domain in domain table",
failure FIND_SPAWNDS "Unable to find spawn daemons",
failure MALFORMED_SPAWND_RECORD "Spawn record without ID found?",
struct thread *thread,
dispatcher_handle_t mydisp);
errval_t domain_thread_move_to(struct thread *thread, coreid_t core_id);
+errval_t domain_cap_hash(struct capref domain_cap, uint64_t *ret_hash);
__END_DECLS
struct dispatcher_generic* disp = get_dispatcher_generic(handle);
return &disp->core_state.c.slot_alloc_state;
}
+
+/**
+ * \brief Returns a 64-bit hash code for a given domain cap.
+ */
+errval_t domain_cap_hash(struct capref domain_cap, uint64_t *ret_hash)
+{
+ assert(ret_hash != NULL);
+
+ struct capability ret_cap;
+ errval_t err = debug_cap_identify(domain_cap, &ret_cap);
+ if (err_is_fail(err)) {
+ return err_push(err, PROC_MGMT_ERR_DOMAIN_CAP_HASH);
+ }
+ assert(ret_cap.type == ObjType_Domain);
+
+ static uint64_t base = 1 + (uint64_t) MAX_COREID;
+ *ret_hash = base * ret_cap.u.domain.coreid + ret_cap.u.domain.core_local_id;
+
+ return SYS_ERR_OK;
+}
\ No newline at end of file
#define HASH_INDEX_BUCKETS 6151
static collections_hash_table* domain_table = NULL;
-errval_t domain_cap_hash(struct capref domain_cap, uint64_t *ret_hash)
-{
- assert(ret_hash != NULL);
-
- struct capability ret_cap;
- errval_t err = debug_cap_identify(domain_cap, &ret_cap);
- if (err_is_fail(err)) {
- return err_push(err, PROC_MGMT_ERR_DOMAIN_CAP_HASH);
- }
- assert(ret_cap.type == ObjType_Domain);
-
- static uint64_t base = 1 + (uint64_t) MAX_COREID;
- *ret_hash = base * ret_cap.u.domain.coreid + ret_cap.u.domain.core_local_id;
-
- return SYS_ERR_OK;
-}
-
errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry)
{
assert(ret_entry != NULL);
struct domain_waiter *waiters; // Clients waiting after this domain.
};
-errval_t domain_cap_hash(struct capref domain_cap, uint64_t *ret_hash);
errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry);
errval_t domain_get_by_cap(struct capref domain_cap,
struct domain_entry **ret_entry);
}
errval_t pending_clients_release(struct capref domain_cap,
- struct pending_client *ret_cl)
+ struct pending_client **ret_cl)
{
uint64_t key;
errval_t err = domain_cap_hash(domain_cap, &key);
return PROC_MGMT_ERR_CLIENTS_TABLE_FIND;
}
if (ret_cl != NULL) {
- *ret_cl = *((struct pending_client*) table_entry);
+ *ret_cl = (struct pending_client*) table_entry;
}
collections_hash_delete(pending_clients_table, key);
struct proc_mgmt_binding *b, enum ClientType type,
coreid_t core_id);
errval_t pending_clients_release(struct capref domain_cap,
- struct pending_client *ret_cl);
+ struct pending_client **ret_cl);
#endif // PENDING_CLIENTS_H
\ No newline at end of file
static void spawn_reply_handler(struct spawn_binding *b,
struct capref domain_cap, errval_t spawn_err)
{
- struct pending_client cl;
+ struct pending_client *cl;
errval_t err = pending_clients_release(domain_cap, &cl);
if (err_is_fail(err)) {
// This might be a kill request issued after a successful spawn/span
}
errval_t resp_err;
- switch (cl.type) {
+ switch (cl->type) {
case ClientType_Spawn:
err = spawn_err;
if (err_is_ok(spawn_err)) {
- err = domain_spawn(domain_cap, cl.core_id);
+ err = domain_spawn(domain_cap, cl->core_id);
}
- resp_err = cl.b->tx_vtbl.spawn_response(cl.b, NOP_CONT, err,
+ resp_err = cl->b->tx_vtbl.spawn_response(cl->b, NOP_CONT, err,
domain_cap);
break;
case ClientType_SpawnWithCaps:
err = spawn_err;
if (err_is_ok(spawn_err)) {
- err = domain_spawn(domain_cap, cl.core_id);
+ err = domain_spawn(domain_cap, cl->core_id);
}
- resp_err = cl.b->tx_vtbl.spawn_with_caps_response(cl.b, NOP_CONT,
+ resp_err = cl->b->tx_vtbl.spawn_with_caps_response(cl->b, NOP_CONT,
err, domain_cap);
break;
case ClientType_Span:
err = spawn_err;
if (err_is_ok(spawn_err)) {
- err = domain_span(domain_cap, cl.core_id);
+ err = domain_span(domain_cap, cl->core_id);
}
- resp_err = cl.b->tx_vtbl.span_response(cl.b, NOP_CONT, err);
+ resp_err = cl->b->tx_vtbl.span_response(cl->b, NOP_CONT, err);
break;
default:
// TODO(razvan): Handle the other cases, e.g. kill.
- debug_printf("Unknown client type %u\n", cl.type);
+ debug_printf("Unknown client type %u\n", cl->type);
return;
}
// there's been an error in the process manager's book-keeping
// of domains. Therefore, if the request was a spawn or span one, spawnd
// needs to be asked to stop the dispatcher which it has just enqueued.
- if (cl.type == ClientType_Spawn ||
- cl.type == ClientType_SpawnWithCaps ||
- cl.type == ClientType_Span) {
- struct spawnd_state *state = spawnd_state_get(cl.core_id);
+ if (cl->type == ClientType_Spawn ||
+ cl->type == ClientType_SpawnWithCaps ||
+ cl->type == ClientType_Span) {
+ struct spawnd_state *state = spawnd_state_get(cl->core_id);
assert(state != NULL);
struct spawn_binding *spb = state->b;
assert(spb != NULL);
}
}
+ free(cl);
+
if (err_is_fail(resp_err)) {
DEBUG_ERR(resp_err, "failed to send response to client");
}
#include <string.h>
#include <assert.h>
#include <barrelfish/barrelfish.h>
+#include <collections/hash_table.h>
#include <vfs/vfs.h>
#include "ps.h"
+#define HASH_INDEX_BUCKETS 6151
+static collections_hash_table* domain_table = NULL;
+
static struct ps_entry *entries[MAX_DOMAINS];
errval_t ps_allocate(struct ps_entry *entry, domainid_t *domainid)
if(entries[i] == NULL) {
entries[i] = entry;
*domainid = i;
+ entry->domain_id = i;
return SYS_ERR_OK;
}
}
return entries[domain_id];
}
+
+errval_t ps_hash_domain(struct ps_entry *entry, struct capref domain_cap)
+{
+ entry->domain_cap = domain_cap;
+
+ if (domain_table == NULL) {
+ collections_hash_create_with_buckets(&domain_table, HASH_INDEX_BUCKETS,
+ NULL);
+ if (domain_table == NULL) {
+ return SPAWN_ERR_CREATE_DOMAIN_TABLE;
+ }
+ }
+
+ uint64_t key;
+ errval_t err = domain_cap_hash(entry->domain_cap, &key);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ collections_hash_insert(domain_table, key, entry);
+
+ return SYS_ERR_OK;
+}
+
+errval_t ps_release_domain(struct capref domain_cap,
+ struct ps_entry **ret_entry)
+{
+ assert(ret_entry != NULL);
+
+ uint64_t key;
+ errval_t err = domain_cap_hash(domain_cap, &key);
+ if (err_is_fail(err)) {
+ return err;
+ }
+
+ void *table_entry = collections_hash_find(domain_table, key);
+ if (table_entry == NULL) {
+ return SPAWN_ERR_DOMAIN_TABLE_FIND;
+ }
+ *ret_entry = (struct ps_entry*) table_entry;
+
+ collections_hash_delete(domain_table, key);
+
+ return SYS_ERR_OK;
+}
char *argv[MAX_CMDLINE_ARGS];
char *argbuf;
size_t argbytes;
+
+ domainid_t domain_id;
+
struct capref domain_cap;
+ uint64_t domain_cap_hash;
+
struct capref rootcn_cap;
struct capref dcb;
struct cnoderef rootcn;
bool ps_exists(domainid_t domain_id);
struct ps_entry *ps_get(domainid_t domain_id);
+errval_t ps_hash_domain(struct ps_entry *entry, struct capref domain_cap);
+errval_t ps_release_domain(struct capref domain_cap,
+ struct ps_entry **ret_entry);
+
#endif
err = cap_copy(pe->dcb, si.dcb);
assert(err_is_ok(err));
pe->status = PS_STATUS_RUNNING;
- pe->domain_cap = domain_cap;
+
+ if (!capref_is_null(domain_cap)) {
+ err = ps_hash_domain(pe, domain_cap);
+ if (err_is_fail(err)) {
+ free(pe);
+ spawn_free(&si);
+ return err_push(err, SPAWN_ERR_DOMAIN_CAP_HASH);
+ }
+ }
+
err = ps_allocate(pe, domainid);
if(err_is_fail(err)) {
free(pe);
err = cap_copy(pe->dcb, si.dcb);
assert(err_is_ok(err));
pe->status = PS_STATUS_RUNNING;
- pe->domain_cap = domain_cap;
+
+ err = ps_hash_domain(pe, domain_cap);
+ if (err_is_fail(err)) {
+ free(pe);
+ spawn_free(&si);
+ err = err_push(err, SPAWN_ERR_DOMAIN_CAP_HASH);
+ goto reply;
+ }
+
domainid_t domainid;
err = ps_allocate(pe, &domainid);
if(err_is_fail(err)) {
}
}
+static void cleanup_cap(struct capref cap)
+{
+ errval_t err;
+
+ err = cap_revoke(cap);
+ if (err_is_fail(err)) {
+ DEBUG_ERR(err, "cap_revoke");
+ }
+ err = cap_destroy(cap);
+ if (err_is_fail(err)) {
+ DEBUG_ERR(err, "cap_destroy");
+ }
+}
+
static void kill_request_handler(struct spawn_binding *b,
struct capref domain_cap)
{
- debug_printf("kill_request_handler: NYI\n");
+ errval_t err, reply_err;
+ struct ps_entry *pe;
+ err = ps_release_domain(domain_cap, &pe);
+ if (err_is_fail(err)) {
+ err = err_push(err, SPAWN_ERR_DOMAIN_NOTFOUND);
+ goto reply;
+ }
+
+ // Garbage collect victim's capabilities
+ cleanup_cap(pe->dcb); // Deschedule dispatcher (do this first!)
+ cleanup_cap(pe->rootcn_cap);
+
+ // Cleanup struct ps_entry. Note that waiters will be handled by the process
+ // manager, as opposed to the old protocol of handling them here.
+ free(pe->argbuf);
+ ps_remove(pe->domain_id);
+ free(pe);
+
+reply:
+ reply_err = b->tx_vtbl.spawn_reply(b, NOP_CONT, domain_cap, err);
+ if (err_is_fail(reply_err)) {
+ DEBUG_ERR(err, "failed to send spawn_reply");
+ }
}
/**
ps_remove(domainid);
}
-static void cleanup_cap(struct capref cap)
-{
- errval_t err;
-
- err = cap_revoke(cap);
- if (err_is_fail(err)) {
- DEBUG_ERR(err, "cap_revoke");
- }
- err = cap_destroy(cap);
- if (err_is_fail(err)) {
- DEBUG_ERR(err, "cap_destroy");
- }
-}
-
static errval_t kill_domain(domainid_t domainid, uint8_t exitcode)
{
struct ps_entry *ps = ps_get(domainid);