Implement kill_request_handler in spawnd, using domain caps.
[barrelfish] / usr / proc_mgmt / domain.c
1 /*
2  * \brief Domain internals for the process manager.
3  *
4  * Copyright (c) 2017, ETH Zurich.
5  * All rights reserved.
6  *
7  * This file is distributed under the terms in the attached LICENSE file.
8  * If you do not find this file, copies can be found by writing to:
9  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
10  */
11
12 #include <barrelfish/barrelfish.h>
13 #include <collections/hash_table.h>
14
15 #include "domain.h"
16
17 #define HASH_INDEX_BUCKETS 6151
18 static collections_hash_table* domain_table = NULL;
19
20 errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry)
21 {
22     assert(ret_entry != NULL);
23
24     struct domain_entry *entry = (struct domain_entry*) malloc(
25             sizeof(struct domain_entry));
26     if (entry == NULL) {
27         return LIB_ERR_MALLOC_FAIL;
28     }
29
30     entry->domain_cap = domain_cap;
31     entry->status = DOMAIN_STATUS_NIL;
32     entry->spawnds = NULL;
33     entry->waiters = NULL;
34
35     if (domain_table == NULL) {
36         collections_hash_create_with_buckets(&domain_table, HASH_INDEX_BUCKETS,
37                                              NULL);
38         if (domain_table == NULL) {
39             return PROC_MGMT_ERR_CREATE_DOMAIN_TABLE;
40         }
41     }
42
43     uint64_t key;
44     errval_t err = domain_cap_hash(entry->domain_cap, &key);
45     if (err_is_fail(err)) {
46         return err;
47     }
48
49     collections_hash_insert(domain_table, key, entry);
50
51     *ret_entry = entry;
52
53     return SYS_ERR_OK;
54 }
55
56 errval_t domain_get_by_cap(struct capref domain_cap,
57                            struct domain_entry **ret_entry)
58 {
59     assert(ret_entry != NULL);
60
61     uint64_t key;
62     errval_t err = domain_cap_hash(domain_cap, &key);
63     if (err_is_fail(err)) {
64         return err;
65     }
66
67     void *table_entry = collections_hash_find(domain_table, key);
68     if (table_entry == NULL) {
69         return PROC_MGMT_ERR_DOMAIN_TABLE_FIND;
70     }
71     *ret_entry = (struct domain_entry*) table_entry;
72
73     return SYS_ERR_OK;
74 }
75
76 void domain_run_on_spawnd(struct domain_entry *entry,
77                           struct spawnd_state *spawnd)
78 {
79     assert(entry != NULL);
80     assert(spawnd != NULL);
81     assert(entry->status == DOMAIN_STATUS_NIL ||
82            entry->status == DOMAIN_STATUS_RUNNING);
83
84     entry->status = DOMAIN_STATUS_RUNNING;
85
86     struct domain_spawnd_state *st = (struct domain_spawnd_state*) malloc(
87             sizeof(struct domain_spawnd_state));
88     st->spawnd_state = spawnd;
89     st->next = entry->spawnds;
90     entry->spawnds = st;
91 }
92
93 errval_t domain_spawn(struct capref domain_cap, coreid_t core_id)
94 {
95     struct domain_entry *entry = NULL;
96     errval_t err = domain_new(domain_cap, &entry);
97     if (err_is_fail(err)) {
98         if (entry != NULL) {
99             free(entry);
100         }
101         return err;
102     }
103
104     domain_run_on_spawnd(entry, spawnd_state_get(core_id));
105
106     return SYS_ERR_OK;
107 }
108
109 errval_t domain_can_span(struct capref domain_cap, coreid_t core_id)
110 {
111     struct domain_entry *entry = NULL;
112     errval_t err = domain_get_by_cap(domain_cap, &entry);
113     if (err_is_fail(err)) {
114         return err;
115     }
116
117     assert(entry != NULL);
118     if (entry->status != DOMAIN_STATUS_RUNNING) {
119         return PROC_MGMT_ERR_DOMAIN_NOT_RUNNING;
120     }
121
122     struct domain_spawnd_state *st = entry->spawnds;
123     while (st != NULL) {
124         if (st->spawnd_state->core_id == core_id) {
125             // TODO(razvan): Maybe we want to allow the same domain to span
126             // multiple dispatcher onto the same core?
127             return PROC_MGMT_ERR_ALREADY_SPANNED;
128         }
129         st = st->next;
130     }
131
132     return SYS_ERR_OK;
133 }
134
135 errval_t domain_span(struct capref domain_cap, coreid_t core_id)
136 {
137     struct domain_entry *entry = NULL;
138     errval_t err = domain_get_by_cap(domain_cap, &entry);
139     if (err_is_fail(err)) {
140         return err;
141     }
142     assert(entry != NULL);
143
144     domain_run_on_spawnd(entry, spawnd_state_get(core_id));
145
146     return SYS_ERR_OK;
147 }
148
149 void domain_send_stop(struct domain_entry *entry)
150 {
151     assert(entry != NULL);
152
153     struct domain_spawnd_state *st = entry->spawnds;
154     while (st != NULL) {
155         debug_printf("Simulating STOP message to spawnd at binding %p\n",
156                      st->spawnd_state->b);
157         st = st->next;
158     }
159 }