Changeset 05913fe7 in mainline
- Timestamp:
- 2017-10-09T22:18:09Z (5 years ago)
- Branches:
- lfn, master, serial
- Children:
- 2bdf92a5
- Parents:
- e02bfb4
- Location:
- kernel/generic
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/cap/cap.h
re02bfb4 r05913fe7 38 38 #include <typedefs.h> 39 39 #include <adt/list.h> 40 #include <adt/hash.h> 41 #include <adt/hash_table.h> 42 #include <lib/ra.h> 40 43 #include <synch/mutex.h> 41 44 #include <atomic.h> 42 43 #define MAX_CAPS 6444 45 45 46 typedef int cap_handle_t; … … 89 90 cap_state_t state; 90 91 92 struct task *task; 91 93 cap_handle_t handle; 92 94 93 95 /* Link to the task's capabilities of the same kobject type. */ 94 link_t link; 96 link_t type_link; 97 98 ht_link_t caps_link; 95 99 96 100 /* The underlying kernel object. */ … … 103 107 list_t type_list[KOBJECT_TYPE_MAX]; 104 108 105 cap_t *caps; 109 hash_table_t caps; 110 ra_arena_t *handles; 106 111 } cap_info_t; 107 112 … … 112 117 bool (*)(cap_t *, void *), void *); 113 118 114 extern void cap_initialize(cap_t *, cap_handle_t);115 119 extern cap_handle_t cap_alloc(struct task *); 116 120 extern void cap_publish(struct task *, cap_handle_t, kobject_t *); -
kernel/generic/src/cap/cap.c
re02bfb4 r05913fe7 79 79 #include <adt/list.h> 80 80 81 #include <stdint.h> 82 83 #define MAX_CAPS INT_MAX 84 81 85 static kobject_t *cap_unpublish_locked(task_t *, cap_handle_t, kobject_type_t); 82 86 83 /** Initialize capability and associate it with its handle 84 * 85 * @param cap Address of the capability. 86 * @param handle Capability handle. 87 */ 88 void cap_initialize(cap_t *cap, cap_handle_t handle) 89 { 90 cap->state = CAP_STATE_FREE; 91 cap->handle = handle; 92 link_initialize(&cap->link); 93 } 87 static size_t caps_hash(const ht_link_t *item) 88 { 89 cap_t *cap = hash_table_get_inst(item, cap_t, caps_link); 90 return hash_mix(cap->handle); 91 } 92 93 static size_t caps_key_hash(void *key) 94 { 95 cap_handle_t *handle = (cap_handle_t *) key; 96 return hash_mix(*handle); 97 } 98 99 static bool caps_key_equal(void *key, const ht_link_t *item) 100 { 101 cap_handle_t *handle = (cap_handle_t *) key; 102 cap_t *cap = hash_table_get_inst(item, cap_t, caps_link); 103 return *handle == cap->handle; 104 } 105 106 static hash_table_ops_t caps_ops = { 107 .hash = caps_hash, 108 .key_hash = caps_key_hash, 109 .key_equal = caps_key_equal 110 }; 94 111 95 112 /** Allocate the capability info structure … … 100 117 { 101 118 task->cap_info = (cap_info_t *) malloc(sizeof(cap_info_t), 0); 102 task->cap_info->caps = malloc(sizeof(cap_t) * MAX_CAPS, 0); 119 task->cap_info->handles = ra_arena_create(); 120 // FIXME: allow caps_task_alloc() to fail 121 assert(task->cap_info->handles); 122 bool success = ra_span_add(task->cap_info->handles, 0, MAX_CAPS); 123 // FIXME: allow caps_task_alloc() to fail 124 assert(success); 125 success = hash_table_create(&task->cap_info->caps, 0, 0, &caps_ops); 126 // FIXME: allow caps_task_alloc() to fail 127 assert(success); 103 128 } 104 129 … … 113 138 for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++) 114 139 list_initialize(&task->cap_info->type_list[t]); 115 116 for (cap_handle_t h = 0; h < MAX_CAPS; h++)117 cap_initialize(&task->cap_info->caps[h], h);118 140 } 119 141 … … 124 146 void caps_task_free(task_t *task) 125 147 { 126 free(task->cap_info->caps); 148 hash_table_destroy(&task->cap_info->caps); 149 ra_arena_destroy(task->cap_info->handles); 127 150 free(task->cap_info); 128 151 } … … 146 169 mutex_lock(&task->cap_info->lock); 147 170 list_foreach_safe(task->cap_info->type_list[type], cur, next) { 148 cap_t *cap = list_get_instance(cur, cap_t, link);171 cap_t *cap = list_get_instance(cur, cap_t, type_link); 149 172 done = cb(cap, arg); 150 173 if (!done) … … 156 179 } 157 180 181 /** Initialize capability and associate it with its handle 182 * 183 * @param cap Address of the capability. 184 * @param task Backling to the owning task. 185 * @param handle Capability handle. 186 */ 187 static void cap_initialize(cap_t *cap, task_t *task, cap_handle_t handle) 188 { 189 cap->state = CAP_STATE_FREE; 190 cap->task = task; 191 cap->handle = handle; 192 link_initialize(&cap->type_link); 193 } 194 158 195 /** Get capability using capability handle 159 196 * … … 171 208 if ((handle < 0) || (handle >= MAX_CAPS)) 172 209 return NULL; 173 if (task->cap_info->caps[handle].state != state) 210 ht_link_t *link = hash_table_find(&task->cap_info->caps, &handle); 211 if (!link) 174 212 return NULL; 175 return &task->cap_info->caps[handle]; 213 cap_t *cap = hash_table_get_inst(link, cap_t, caps_link); 214 if (cap->state != state) 215 return NULL; 216 return cap; 217 } 218 219 static bool cap_reclaimer(ht_link_t *link, void *arg) 220 { 221 cap_t **result = (cap_t **) arg; 222 cap_t *cap = hash_table_get_inst(link, cap_t, caps_link); 223 224 if (cap->state == CAP_STATE_PUBLISHED && cap->kobject->ops->reclaim && 225 cap->kobject->ops->reclaim(cap->kobject)) { 226 kobject_t *kobj = cap_unpublish_locked(cap->task, cap->handle, 227 cap->kobject->type); 228 kobject_put(kobj); 229 cap_initialize(cap, cap->task, cap->handle); 230 *result = cap; 231 return false; 232 } 233 234 return true; 176 235 } 177 236 … … 185 244 cap_handle_t cap_alloc(task_t *task) 186 245 { 187 mutex_lock(&task->cap_info->lock); 188 for (cap_handle_t handle = 0; handle < MAX_CAPS; handle++) { 189 cap_t *cap = &task->cap_info->caps[handle]; 190 /* See if the capability should be garbage-collected */ 191 if (cap->state == CAP_STATE_PUBLISHED && 192 cap->kobject->ops->reclaim && 193 cap->kobject->ops->reclaim(cap->kobject)) { 194 kobject_t *kobj = cap_unpublish_locked(task, handle, 195 cap->kobject->type); 196 kobject_put(kobj); 197 cap_initialize(&task->cap_info->caps[handle], handle); 246 cap_t *cap = NULL; 247 cap_handle_t handle; 248 249 /* 250 * First of all, see if we can reclaim a capability. Note that this 251 * feature is only temporary and capability reclamaition will eventually 252 * be phased out. 253 */ 254 mutex_lock(&task->cap_info->lock); 255 hash_table_apply(&task->cap_info->caps, cap_reclaimer, &cap); 256 257 /* 258 * If we don't have a capability by now, try to allocate a new one. 259 */ 260 if (!cap) { 261 cap = malloc(sizeof(cap_t), 0); 262 if (!cap) { 263 mutex_unlock(&task->cap_info->lock); 264 return ENOMEM; 198 265 } 199 if (cap->state == CAP_STATE_FREE) { 200 cap->state = CAP_STATE_ALLOCATED; 266 uintptr_t hbase; 267 if (!ra_alloc(task->cap_info->handles, 1, 1, &hbase)) { 268 free(cap); 201 269 mutex_unlock(&task->cap_info->lock); 202 return handle;270 return ENOMEM; 203 271 } 204 } 205 mutex_unlock(&task->cap_info->lock); 206 207 return ELIMIT; 272 cap_initialize(cap, task, (cap_handle_t) hbase); 273 hash_table_insert(&task->cap_info->caps, &cap->caps_link); 274 } 275 276 cap->state = CAP_STATE_ALLOCATED; 277 handle = cap->handle; 278 mutex_unlock(&task->cap_info->lock); 279 280 return handle; 208 281 } 209 282 … … 227 300 /* Hand over kobj's reference to cap */ 228 301 cap->kobject = kobj; 229 list_append(&cap-> link, &task->cap_info->type_list[kobj->type]);302 list_append(&cap->type_link, &task->cap_info->type_list[kobj->type]); 230 303 mutex_unlock(&task->cap_info->lock); 231 304 } … … 242 315 kobj = cap->kobject; 243 316 cap->kobject = NULL; 244 list_remove(&cap-> link);317 list_remove(&cap->type_link); 245 318 cap->state = CAP_STATE_ALLOCATED; 246 319 } … … 281 354 assert(handle >= 0); 282 355 assert(handle < MAX_CAPS); 283 assert(task->cap_info->caps[handle].state == CAP_STATE_ALLOCATED); 284 285 mutex_lock(&task->cap_info->lock); 286 cap_initialize(&task->cap_info->caps[handle], handle); 356 357 mutex_lock(&task->cap_info->lock); 358 cap_t *cap = cap_get(task, handle, CAP_STATE_ALLOCATED); 359 360 assert(cap); 361 362 hash_table_remove_item(&task->cap_info->caps, &cap->caps_link); 363 ra_free(task->cap_info->handles, handle, 1); 364 free(cap); 287 365 mutex_unlock(&task->cap_info->lock); 288 366 }
Note: See TracChangeset
for help on using the changeset viewer.