9a0d89dcc05ad872e100c12061df7c1174227abf
[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 #include <if/spawn_defs.h>
15
16 #include "domain.h"
17 #include "spawnd_state.h"
18
19 #define HASH_INDEX_BUCKETS 6151
20 static collections_hash_table* domain_table = NULL;
21
22 errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry)
23 {
24     assert(ret_entry != NULL);
25
26     struct domain_entry *entry = (struct domain_entry*) malloc(
27             sizeof(struct domain_entry));
28     if (entry == NULL) {
29         return LIB_ERR_MALLOC_FAIL;
30     }
31
32     entry->domain_cap = domain_cap;
33     entry->status = DOMAIN_STATUS_NIL;
34     memset(entry->spawnds, 0, sizeof(entry->spawnds));
35     entry->num_spawnds_running = 0;
36     entry->waiters = NULL;
37
38     if (domain_table == NULL) {
39         collections_hash_create_with_buckets(&domain_table, HASH_INDEX_BUCKETS,
40                                              NULL);
41         if (domain_table == NULL) {
42             return PROC_MGMT_ERR_CREATE_DOMAIN_TABLE;
43         }
44     }
45
46     uint64_t key;
47     errval_t err = domain_cap_hash(entry->domain_cap, &key);
48     if (err_is_fail(err)) {
49         return err;
50     }
51
52     collections_hash_insert(domain_table, key, entry);
53
54     *ret_entry = entry;
55
56     return SYS_ERR_OK;
57 }
58
59 errval_t domain_get_by_cap(struct capref domain_cap,
60                            struct domain_entry **ret_entry)
61 {
62     assert(ret_entry != NULL);
63
64     uint64_t key;
65     errval_t err = domain_cap_hash(domain_cap, &key);
66     if (err_is_fail(err)) {
67         return err;
68     }
69
70     void *table_entry = collections_hash_find(domain_table, key);
71     if (table_entry == NULL) {
72         return PROC_MGMT_ERR_DOMAIN_TABLE_FIND;
73     }
74     *ret_entry = (struct domain_entry*) table_entry;
75
76     return SYS_ERR_OK;
77 }
78
79 void domain_run_on_core(struct domain_entry *entry, coreid_t core_id)
80 {
81     assert(entry != NULL);
82     assert(core_id < MAX_COREID);
83     assert(entry->status == DOMAIN_STATUS_NIL ||
84            entry->status == DOMAIN_STATUS_RUNNING);
85
86     entry->status = DOMAIN_STATUS_RUNNING;
87
88     entry->spawnds[core_id] = spawnd_state_get(core_id);
89     ++entry->num_spawnds_running;
90 }
91
92 errval_t domain_spawn(struct capref domain_cap, coreid_t core_id)
93 {
94     struct domain_entry *entry = NULL;
95     errval_t err = domain_new(domain_cap, &entry);
96     if (err_is_fail(err)) {
97         if (entry != NULL) {
98             free(entry);
99         }
100         return err;
101     }
102
103     domain_run_on_core(entry, core_id);
104
105     return SYS_ERR_OK;
106 }
107
108 errval_t domain_can_span(struct capref domain_cap, coreid_t core_id)
109 {
110     struct domain_entry *entry = NULL;
111     errval_t err = domain_get_by_cap(domain_cap, &entry);
112     if (err_is_fail(err)) {
113         return err;
114     }
115
116     assert(entry != NULL);
117     if (entry->status != DOMAIN_STATUS_RUNNING) {
118         return PROC_MGMT_ERR_DOMAIN_NOT_RUNNING;
119     }
120
121     if (entry->spawnds[core_id] != NULL) {
122         // TODO(razvan): Maybe we want to allow the same domain to span multiple
123         // dispatchers onto the same core?
124         return PROC_MGMT_ERR_ALREADY_SPANNED;
125     }
126
127     return SYS_ERR_OK;
128 }
129
130 errval_t domain_span(struct capref domain_cap, coreid_t core_id)
131 {
132     struct domain_entry *entry = NULL;
133     errval_t err = domain_get_by_cap(domain_cap, &entry);
134     if (err_is_fail(err)) {
135         return err;
136     }
137     assert(entry != NULL);
138
139     domain_run_on_core(entry, core_id);
140
141     return SYS_ERR_OK;
142 }