Changeset 48bcf49 in mainline
- Timestamp:
- 2017-09-28T22:08:15Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6636fb19
- Parents:
- dd20cbb
- Location:
- kernel/generic
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/cap/cap.h
rdd20cbb r48bcf49 37 37 38 38 #include <typedefs.h> 39 #include <ipc/ipc.h>40 39 #include <adt/list.h> 41 40 #include <synch/mutex.h> 41 #include <atomic.h> 42 42 43 43 #define MAX_CAPS 64 44 44 45 typedef int cap_handle_t; 46 45 47 typedef enum { 46 CAP_TYPE_INVALID, 47 CAP_TYPE_ALLOCATED, 48 CAP_TYPE_PHONE, 49 CAP_TYPE_IRQ, 50 CAP_TYPE_MAX 51 } cap_type_t; 48 CAP_STATE_FREE, 49 CAP_STATE_ALLOCATED, 50 CAP_STATE_PUBLISHED 51 } cap_state_t; 52 53 typedef enum { 54 KOBJECT_TYPE_PHONE, 55 KOBJECT_TYPE_IRQ, 56 KOBJECT_TYPE_MAX 57 } kobject_type_t; 58 59 struct task; 60 struct phone; 61 struct irq; 62 63 struct kobject; 64 typedef struct kobject_ops { 65 bool (*reclaim)(struct kobject *); 66 void (*destroy)(void *); 67 } kobject_ops_t; 68 69 typedef struct kobject { 70 kobject_type_t type; 71 atomic_t refcnt; 72 73 kobject_ops_t *ops; 74 75 union { 76 void *raw; 77 struct phone *phone; 78 struct irq *irq; 79 }; 80 } kobject_t; 52 81 53 82 typedef struct cap { 54 cap_type_t type; 55 int handle; 83 cap_state_t state; 56 84 57 bool (* can_reclaim)(struct cap *);85 cap_handle_t handle; 58 86 59 /* Link to the task's capabilities of the same type. */87 /* Link to the task's capabilities of the same kobject type. */ 60 88 link_t link; 61 89 62 90 /* The underlying kernel object. */ 63 void*kobject;91 kobject_t *kobject; 64 92 } cap_t; 65 93 … … 67 95 mutex_t lock; 68 96 69 list_t type_list[ CAP_TYPE_MAX];97 list_t type_list[KOBJECT_TYPE_MAX]; 70 98 71 99 cap_t *caps; 72 100 } cap_info_t; 73 101 74 struct task;75 76 102 extern void caps_task_alloc(struct task *); 77 103 extern void caps_task_free(struct task *); 78 104 extern void caps_task_init(struct task *); 79 extern bool caps_apply_to_ type(struct task *, cap_type_t,105 extern bool caps_apply_to_kobject_type(struct task *, kobject_type_t, 80 106 bool (*)(cap_t *, void *), void *); 81 extern void caps_lock(struct task *);82 extern void caps_unlock(struct task *);83 107 84 extern void cap_initialize(cap_t *, int); 85 extern cap_t *cap_get(struct task *, int, cap_type_t); 86 extern int cap_alloc(struct task *); 87 extern void cap_publish(struct task *, int, cap_type_t, void *); 88 extern cap_t *cap_unpublish(struct task *, int, cap_type_t); 89 extern void cap_free(struct task *, int); 108 extern void cap_initialize(cap_t *, cap_handle_t); 109 extern cap_handle_t cap_alloc(struct task *); 110 extern void cap_publish(struct task *, cap_handle_t, kobject_t *); 111 extern kobject_t *cap_unpublish(struct task *, cap_handle_t, kobject_type_t); 112 extern void cap_free(struct task *, cap_handle_t); 113 114 extern void kobject_initialize(kobject_t *, kobject_type_t, void *, 115 kobject_ops_t *); 116 extern kobject_t *kobject_get(struct task *, cap_handle_t, kobject_type_t); 117 extern void kobject_put(kobject_t *); 90 118 91 119 #endif -
kernel/generic/include/ddi/irq.h
rdd20cbb r48bcf49 81 81 /** When false, notifications are not sent. */ 82 82 bool notify; 83 /** True if the structure is in irq_uspace_hash_table_table */ 84 bool hashed_in; 83 85 /** Answerbox for notifications. */ 84 86 answerbox_t *answerbox; -
kernel/generic/include/ipc/ipc.h
rdd20cbb r48bcf49 43 43 #include <typedefs.h> 44 44 #include <mm/slab.h> 45 #include <cap/cap.h> 45 46 46 47 struct answerbox; … … 61 62 62 63 /** Structure identifying phone (in TASK structure) */ 63 typedef struct {64 typedef struct phone { 64 65 mutex_t lock; 65 66 link_t link; … … 68 69 ipc_phone_state_t state; 69 70 atomic_t active_calls; 71 kobject_t *kobject; 70 72 } phone_t; 71 73 -
kernel/generic/include/ipc/ipcrsc.h
rdd20cbb r48bcf49 38 38 #include <proc/task.h> 39 39 #include <ipc/ipc.h> 40 #include <cap/cap.h> 40 41 41 42 extern call_t *get_call(sysarg_t); 42 extern phone_t *phone_get_current(int); 43 extern phone_t *phone_get(task_t *, int); 44 extern int phone_alloc(task_t *); 45 extern bool phone_connect(int, answerbox_t *); 46 extern void phone_dealloc(int); 43 extern cap_handle_t phone_alloc(task_t *); 44 extern bool phone_connect(cap_handle_t, answerbox_t *); 45 extern void phone_dealloc(cap_handle_t); 47 46 48 47 #endif -
kernel/generic/src/cap/cap.c
rdd20cbb r48bcf49 40 40 #include <adt/list.h> 41 41 42 void cap_initialize(cap_t *cap, int handle) 43 { 44 cap->type = CAP_TYPE_INVALID; 42 static kobject_t *cap_unpublish_locked(task_t *, cap_handle_t, kobject_type_t); 43 44 void cap_initialize(cap_t *cap, cap_handle_t handle) 45 { 46 cap->state = CAP_STATE_FREE; 45 47 cap->handle = handle; 46 cap->can_reclaim = NULL;47 48 link_initialize(&cap->link); 48 49 } … … 58 59 mutex_initialize(&task->cap_info->lock, MUTEX_PASSIVE); 59 60 60 for ( int i = 0; i < CAP_TYPE_MAX; i++)61 list_initialize(&task->cap_info->type_list[ i]);62 63 for ( int i = 0; i < MAX_CAPS; i++)64 cap_initialize(&task->cap_info->caps[ i], i);61 for (kobject_type_t t = 0; t < KOBJECT_TYPE_MAX; t++) 62 list_initialize(&task->cap_info->type_list[t]); 63 64 for (cap_handle_t h = 0; h < MAX_CAPS; h++) 65 cap_initialize(&task->cap_info->caps[h], h); 65 66 } 66 67 … … 71 72 } 72 73 73 bool caps_apply_to_ type(task_t *task, cap_type_t type,74 bool caps_apply_to_kobject_type(task_t *task, kobject_type_t type, 74 75 bool (*cb)(cap_t *, void *), void *arg) 75 76 { … … 88 89 } 89 90 90 void caps_lock(task_t *task) 91 { 92 mutex_lock(&task->cap_info->lock); 93 } 94 95 void caps_unlock(task_t *task) 96 { 97 mutex_unlock(&task->cap_info->lock); 98 } 99 100 cap_t *cap_get(task_t *task, int handle, cap_type_t type) 91 static cap_t *cap_get(task_t *task, cap_handle_t handle, cap_state_t state) 101 92 { 102 93 assert(mutex_locked(&task->cap_info->lock)); … … 104 95 if ((handle < 0) || (handle >= MAX_CAPS)) 105 96 return NULL; 106 if (task->cap_info->caps[handle]. type != type)97 if (task->cap_info->caps[handle].state != state) 107 98 return NULL; 108 99 return &task->cap_info->caps[handle]; 109 100 } 110 101 111 int cap_alloc(task_t *task) 112 { 113 int handle; 114 115 mutex_lock(&task->cap_info->lock); 116 for (handle = 0; handle < MAX_CAPS; handle++) { 102 cap_handle_t cap_alloc(task_t *task) 103 { 104 mutex_lock(&task->cap_info->lock); 105 for (cap_handle_t handle = 0; handle < MAX_CAPS; handle++) { 117 106 cap_t *cap = &task->cap_info->caps[handle]; 118 if (cap->type > CAP_TYPE_ALLOCATED) { 119 if (cap->can_reclaim && cap->can_reclaim(cap)) { 120 list_remove(&cap->link); 121 cap_initialize(cap, handle); 122 } 123 } 124 if (cap->type == CAP_TYPE_INVALID) { 125 cap->type = CAP_TYPE_ALLOCATED; 107 /* See if the capability should be garbage-collected */ 108 if (cap->state == CAP_STATE_PUBLISHED && 109 cap->kobject->ops->reclaim && 110 cap->kobject->ops->reclaim(cap->kobject)) { 111 kobject_t *kobj = cap_unpublish_locked(task, handle, 112 cap->kobject->type); 113 kobject_put(kobj); 114 cap_initialize(&task->cap_info->caps[handle], handle); 115 } 116 if (cap->state == CAP_STATE_FREE) { 117 cap->state = CAP_STATE_ALLOCATED; 126 118 mutex_unlock(&task->cap_info->lock); 127 119 return handle; … … 133 125 } 134 126 135 void cap_publish(task_t *task, int handle, cap_type_t type, void *kobject) 136 { 137 mutex_lock(&task->cap_info->lock); 138 cap_t *cap = cap_get(task, handle, CAP_TYPE_ALLOCATED); 127 void 128 cap_publish(task_t *task, cap_handle_t handle, kobject_t *kobj) 129 { 130 mutex_lock(&task->cap_info->lock); 131 cap_t *cap = cap_get(task, handle, CAP_STATE_ALLOCATED); 139 132 assert(cap); 140 cap->type = type; 141 cap->kobject = kobject; 142 list_append(&cap->link, &task->cap_info->type_list[type]); 143 mutex_unlock(&task->cap_info->lock); 144 } 145 146 cap_t *cap_unpublish(task_t *task, int handle, cap_type_t type) 147 { 148 cap_t *cap; 149 150 mutex_lock(&task->cap_info->lock); 151 cap = cap_get(task, handle, type); 133 cap->state = CAP_STATE_PUBLISHED; 134 /* Hand over kobj's reference to cap */ 135 cap->kobject = kobj; 136 list_append(&cap->link, &task->cap_info->type_list[kobj->type]); 137 mutex_unlock(&task->cap_info->lock); 138 } 139 140 static kobject_t * 141 cap_unpublish_locked(task_t *task, cap_handle_t handle, kobject_type_t type) 142 { 143 kobject_t *kobj = NULL; 144 145 cap_t *cap = cap_get(task, handle, CAP_STATE_PUBLISHED); 152 146 if (cap) { 153 list_remove(&cap->link); 154 cap->type = CAP_TYPE_ALLOCATED; 155 } 156 mutex_unlock(&task->cap_info->lock); 157 158 return cap; 159 } 160 161 void cap_free(task_t *task, int handle) 147 if (cap->kobject->type == type) { 148 /* Hand over cap's reference to kobj */ 149 kobj = cap->kobject; 150 cap->kobject = NULL; 151 list_remove(&cap->link); 152 cap->state = CAP_STATE_ALLOCATED; 153 } 154 } 155 156 return kobj; 157 } 158 kobject_t *cap_unpublish(task_t *task, cap_handle_t handle, kobject_type_t type) 159 { 160 161 mutex_lock(&task->cap_info->lock); 162 kobject_t *kobj = cap_unpublish_locked(task, handle, type); 163 mutex_unlock(&task->cap_info->lock); 164 165 return kobj; 166 } 167 168 void cap_free(task_t *task, cap_handle_t handle) 162 169 { 163 170 assert(handle >= 0); 164 171 assert(handle < MAX_CAPS); 165 assert(task->cap_info->caps[handle]. type == CAP_TYPE_ALLOCATED);172 assert(task->cap_info->caps[handle].state == CAP_STATE_ALLOCATED); 166 173 167 174 mutex_lock(&task->cap_info->lock); … … 170 177 } 171 178 179 void kobject_initialize(kobject_t *kobj, kobject_type_t type, void *raw, 180 kobject_ops_t *ops) 181 { 182 atomic_set(&kobj->refcnt, 1); 183 kobj->type = type; 184 kobj->raw = raw; 185 kobj->ops = ops; 186 } 187 188 kobject_t * 189 kobject_get(struct task *task, cap_handle_t handle, kobject_type_t type) 190 { 191 kobject_t *kobj = NULL; 192 193 mutex_lock(&task->cap_info->lock); 194 cap_t *cap = cap_get(task, handle, CAP_STATE_PUBLISHED); 195 if (cap) { 196 if (cap->kobject->type == type) { 197 kobj = cap->kobject; 198 atomic_inc(&kobj->refcnt); 199 } 200 } 201 mutex_unlock(&task->cap_info->lock); 202 203 return kobj; 204 } 205 206 void kobject_put(kobject_t *kobj) 207 { 208 if (atomic_postdec(&kobj->refcnt) == 1) { 209 kobj->ops->destroy(kobj->raw); 210 free(kobj); 211 } 212 } 213 172 214 /** @} 173 215 */ -
kernel/generic/src/ipc/ipc.c
rdd20cbb r48bcf49 154 154 /** Connect a phone to an answerbox. 155 155 * 156 * @param phone Initialized phone structure. 157 * @param box Initialized answerbox structure. 158 * @return True if the phone was connected, false otherwise. 156 * This function must be passed a reference to phone->kobject. 157 * 158 * @param phone Initialized phone structure. 159 * @param box Initialized answerbox structure. 160 * @return True if the phone was connected, false otherwise. 159 161 */ 160 162 bool ipc_phone_connect(phone_t *phone, answerbox_t *box) … … 169 171 phone->state = IPC_PHONE_CONNECTED; 170 172 phone->callee = box; 173 /* Pass phone->kobject reference to box->connected_phones */ 171 174 list_append(&phone->link, &box->connected_phones); 172 175 } … … 174 177 irq_spinlock_unlock(&box->lock, true); 175 178 mutex_unlock(&phone->lock); 179 180 if (!active) { 181 /* We still have phone->kobject's reference; drop it */ 182 kobject_put(phone->kobject); 183 } 176 184 177 185 return active; … … 191 199 phone->state = IPC_PHONE_FREE; 192 200 atomic_set(&phone->active_calls, 0); 201 phone->kobject = NULL; 193 202 } 194 203 … … 456 465 list_remove(&phone->link); 457 466 irq_spinlock_unlock(&box->lock, true); 467 468 /* Drop the answerbox reference */ 469 kobject_put(phone->kobject); 458 470 459 471 call_t *call = ipc_call_alloc(0); … … 658 670 659 671 task_release(phone->caller); 672 673 kobject_put(phone->kobject); 660 674 661 675 /* Must start again */ … … 664 678 665 679 mutex_unlock(&phone->lock); 680 kobject_put(phone->kobject); 666 681 } 667 682 … … 734 749 static bool phone_cap_wait_cb(cap_t *cap, void *arg) 735 750 { 736 phone_t *phone = (phone_t *) cap->kobject;751 phone_t *phone = cap->kobject->phone; 737 752 bool *restart = (bool *) arg; 738 753 … … 790 805 */ 791 806 restart = false; 792 if (caps_apply_to_ type(TASK, CAP_TYPE_PHONE, phone_cap_wait_cb,793 &restart)) {807 if (caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE, 808 phone_cap_wait_cb, &restart)) { 794 809 /* Got into cleanup */ 795 810 return; … … 810 825 static bool phone_cap_cleanup_cb(cap_t *cap, void *arg) 811 826 { 812 phone_t *phone = (phone_t *) cap->kobject; 813 ipc_phone_hangup(phone); 827 ipc_phone_hangup(cap->kobject->phone); 814 828 return true; 815 829 } … … 840 854 841 855 /* Disconnect all our phones ('ipc_phone_hangup') */ 842 caps_apply_to_type(TASK, CAP_TYPE_PHONE, phone_cap_cleanup_cb, NULL); 856 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_PHONE, 857 phone_cap_cleanup_cb, NULL); 843 858 844 859 /* Unsubscribe from any event notifications. */ … … 846 861 847 862 /* Disconnect all connected IRQs */ 848 caps_apply_to_type(TASK, CAP_TYPE_IRQ, irq_cap_cleanup_cb, NULL); 863 caps_apply_to_kobject_type(TASK, KOBJECT_TYPE_IRQ, irq_cap_cleanup_cb, 864 NULL); 849 865 850 866 /* Disconnect all phones connected to our regular answerbox */ … … 912 928 static bool print_task_phone_cb(cap_t *cap, void *arg) 913 929 { 914 phone_t *phone = (phone_t *) cap->kobject;930 phone_t *phone = cap->kobject->phone; 915 931 916 932 mutex_lock(&phone->lock); … … 963 979 printf("[phone cap] [calls] [state\n"); 964 980 965 caps_apply_to_type(task, CAP_TYPE_PHONE, print_task_phone_cb, NULL); 981 caps_apply_to_kobject_type(task, KOBJECT_TYPE_PHONE, 982 print_task_phone_cb, NULL); 966 983 967 984 irq_spinlock_lock(&task->lock, true); -
kernel/generic/src/ipc/ipcrsc.c
rdd20cbb r48bcf49 164 164 } 165 165 166 /** Get phone from the current task by capability handle. 167 * 168 * @param handle Phone capability handle. 169 * @param phone Place to store pointer to phone. 170 * 171 * @return Address of the phone kernel object. 172 * @return NULL if the capability is invalid. 173 * 174 */ 175 phone_t *phone_get(task_t *task, int handle) 176 { 177 phone_t *phone; 178 179 caps_lock(task); 180 cap_t *cap = cap_get(task, handle, CAP_TYPE_PHONE); 181 phone = (phone_t *) cap->kobject; 182 caps_unlock(task); 183 if (!cap) 184 return NULL; 185 186 return phone; 187 } 188 189 phone_t *phone_get_current(int handle) 190 { 191 return phone_get(TASK, handle); 192 } 193 194 static bool phone_can_reclaim(cap_t *cap) 195 { 196 assert(cap->type == CAP_TYPE_PHONE); 197 198 phone_t *phone = (phone_t *) cap->kobject; 199 200 return (phone->state == IPC_PHONE_HUNGUP) && 201 (atomic_get(&phone->active_calls) == 0); 202 } 166 static bool phone_reclaim(kobject_t *kobj) 167 { 168 bool gc = false; 169 170 mutex_lock(&kobj->phone->lock); 171 if (kobj->phone->state == IPC_PHONE_HUNGUP && 172 atomic_get(&kobj->phone->active_calls) == 0) 173 gc = true; 174 mutex_unlock(&kobj->phone->lock); 175 176 return gc; 177 } 178 179 static void phone_destroy(void *arg) 180 { 181 phone_t *phone = (phone_t *) arg; 182 slab_free(phone_slab, phone); 183 } 184 185 static kobject_ops_t phone_kobject_ops = { 186 .reclaim = phone_reclaim, 187 .destroy = phone_destroy 188 }; 189 203 190 204 191 /** Allocate new phone in the specified task. … … 209 196 * @return Negative error code if a new capability cannot be allocated. 210 197 */ 211 int phone_alloc(task_t *task)212 { 213 int handle = cap_alloc(task);198 cap_handle_t phone_alloc(task_t *task) 199 { 200 cap_handle_t handle = cap_alloc(task); 214 201 if (handle >= 0) { 215 202 phone_t *phone = slab_alloc(phone_slab, FRAME_ATOMIC); … … 218 205 return ENOMEM; 219 206 } 220 207 kobject_t *kobject = malloc(sizeof(kobject_t), FRAME_ATOMIC); 208 if (!kobject) { 209 cap_free(TASK, handle); 210 slab_free(phone_slab, phone); 211 return ENOMEM; 212 } 213 221 214 ipc_phone_init(phone, task); 222 215 phone->state = IPC_PHONE_CONNECTING; 216 217 kobject_initialize(kobject, KOBJECT_TYPE_PHONE, phone, 218 &phone_kobject_ops); 219 phone->kobject = kobject; 223 220 224 // FIXME: phase this out eventually 225 mutex_lock(&task->cap_info->lock); 226 cap_t *cap = cap_get(task, handle, CAP_TYPE_ALLOCATED); 227 cap->can_reclaim = phone_can_reclaim; 228 mutex_unlock(&task->cap_info->lock); 229 230 cap_publish(task, handle, CAP_TYPE_PHONE, phone); 221 cap_publish(task, handle, kobject); 231 222 } 232 223 … … 241 232 * 242 233 */ 243 void phone_dealloc(int handle) 244 { 245 cap_t *cap = cap_unpublish(TASK, handle, CAP_TYPE_PHONE); 246 assert(cap); 247 248 phone_t *phone = (phone_t *) cap->kobject; 249 250 assert(phone); 251 assert(phone->state == IPC_PHONE_CONNECTING); 252 253 slab_free(phone_slab, phone); 234 void phone_dealloc(cap_handle_t handle) 235 { 236 kobject_t *kobj = cap_unpublish(TASK, handle, KOBJECT_TYPE_PHONE); 237 if (!kobj) 238 return; 239 240 assert(kobj->phone); 241 assert(kobj->phone->state == IPC_PHONE_CONNECTING); 242 243 kobject_put(kobj); 254 244 cap_free(TASK, handle); 255 245 } … … 260 250 * @param box Answerbox to which to connect the phone. 261 251 * @return True if the phone was connected, false otherwise. 262 * 263 * The procedure _enforces_ that the user first marks the phone busy (e.g. via 264 * phone_alloc) and then connects the phone, otherwise race condition may 265 * appear. 266 * 267 */ 268 bool phone_connect(int handle, answerbox_t *box) 269 { 270 phone_t *phone = phone_get_current(handle); 271 272 assert(phone); 273 assert(phone->state == IPC_PHONE_CONNECTING); 274 275 return ipc_phone_connect(phone, box); 252 */ 253 bool phone_connect(cap_handle_t handle, answerbox_t *box) 254 { 255 kobject_t *phone_obj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); 256 if (!phone_obj) 257 return false; 258 259 assert(phone_obj->phone->state == IPC_PHONE_CONNECTING); 260 261 /* Hand over phone_obj reference to the answerbox */ 262 return ipc_phone_connect(phone_obj->phone, box); 276 263 } 277 264 -
kernel/generic/src/ipc/irq.c
rdd20cbb r48bcf49 271 271 } 272 272 273 static void irq_destroy(void *arg) 274 { 275 irq_t *irq = (irq_t *) arg; 276 277 /* Free up the IRQ code and associated structures. */ 278 code_free(irq->notif_cfg.code); 279 slab_free(irq_slab, irq); 280 } 281 282 static kobject_ops_t irq_kobject_ops = { 283 .destroy = irq_destroy 284 }; 285 273 286 /** Subscribe an answerbox as a receiving end for IRQ notifications. 274 287 * … … 304 317 * Allocate and populate the IRQ kernel object. 305 318 */ 306 int handle = cap_alloc(TASK);319 cap_handle_t handle = cap_alloc(TASK); 307 320 if (handle < 0) 308 321 return handle; … … 311 324 if (!irq) { 312 325 cap_free(TASK, handle); 326 return ENOMEM; 327 } 328 329 kobject_t *kobject = malloc(sizeof(kobject_t), FRAME_ATOMIC); 330 if (!kobject) { 331 cap_free(TASK, handle); 332 slab_free(irq_slab, irq); 313 333 return ENOMEM; 314 334 } … … 330 350 irq_spinlock_lock(&irq->lock, false); 331 351 352 irq->notif_cfg.hashed_in = true; 332 353 hash_table_insert(&irq_uspace_hash_table, key, &irq->link); 333 354 … … 335 356 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 336 357 337 cap_publish(TASK, handle, CAP_TYPE_IRQ, irq); 358 kobject_initialize(kobject, KOBJECT_TYPE_IRQ, irq, &irq_kobject_ops); 359 cap_publish(TASK, handle, kobject); 338 360 339 361 return handle; … … 350 372 int ipc_irq_unsubscribe(answerbox_t *box, int handle) 351 373 { 352 cap_t *cap = cap_unpublish(TASK, handle, CAP_TYPE_IRQ);353 if (! cap)374 kobject_t *kobj = cap_unpublish(TASK, handle, KOBJECT_TYPE_IRQ); 375 if (!kobj) 354 376 return ENOENT; 355 377 356 irq_t *irq = (irq_t *) cap->kobject;357 378 assert(kobj->irq->notif_cfg.answerbox == box); 379 358 380 irq_spinlock_lock(&irq_uspace_hash_table_lock, true); 359 irq_spinlock_lock(&irq->lock, false); 360 361 assert(irq->notif_cfg.answerbox == box); 362 363 /* Remove the IRQ from the uspace IRQ hash table. */ 364 hash_table_remove_item(&irq_uspace_hash_table, &irq->link); 365 366 /* irq->lock unlocked by the hash table remove_callback */ 381 irq_spinlock_lock(&kobj->irq->lock, false); 382 383 if (kobj->irq->notif_cfg.hashed_in) { 384 /* Remove the IRQ from the uspace IRQ hash table. */ 385 hash_table_remove_item(&irq_uspace_hash_table, 386 &kobj->irq->link); 387 kobj->irq->notif_cfg.hashed_in = false; 388 } 389 390 /* kobj->irq->lock unlocked by the hash table remove_callback */ 367 391 irq_spinlock_unlock(&irq_uspace_hash_table_lock, true); 368 369 /* Free up the IRQ code and associated structures. */ 370 code_free(irq->notif_cfg.code); 371 372 /* Free up the IRQ capability and the underlying kernel object. */ 373 slab_free(irq_slab, cap->kobject); 392 393 kobject_put(kobj); 374 394 cap_free(TASK, handle); 375 395 -
kernel/generic/src/ipc/kbox.c
rdd20cbb r48bcf49 206 206 * cleanup code. 207 207 * 208 * @return Phone capability on success, or negative error code.208 * @return Phone capability handle on success, or negative error code. 209 209 * 210 210 */ … … 236 236 } 237 237 238 int cap = phone_alloc(TASK); 239 if (cap < 0) { 240 mutex_unlock(&task->kb.cleanup_lock); 241 return ELIMIT; 242 } 243 238 cap_handle_t phone_handle = phone_alloc(TASK); 239 if (phone_handle < 0) { 240 mutex_unlock(&task->kb.cleanup_lock); 241 return phone_handle; 242 } 243 244 kobject_t *phone_obj = kobject_get(TASK, phone_handle, 245 KOBJECT_TYPE_PHONE); 244 246 /* Connect the newly allocated phone to the kbox */ 245 (void) ipc_phone_connect(phone_get_current(cap), &task->kb.box); 247 /* Hand over phone_obj's reference to ipc_phone_connect() */ 248 (void) ipc_phone_connect(phone_obj->phone, &task->kb.box); 246 249 247 250 if (task->kb.thread != NULL) { 248 251 mutex_unlock(&task->kb.cleanup_lock); 249 return cap;252 return phone_handle; 250 253 } 251 254 … … 263 266 mutex_unlock(&task->kb.cleanup_lock); 264 267 265 return cap;268 return phone_handle; 266 269 } 267 270 -
kernel/generic/src/ipc/ops/conctmeto.c
rdd20cbb r48bcf49 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2012 Jakub Jermar 3 * Copyright (c) 2012 Jakub Jermar 4 4 * All rights reserved. 5 5 * … … 42 42 static int request_preprocess(call_t *call, phone_t *phone) 43 43 { 44 int cap= phone_alloc(TASK);44 cap_handle_t phone_handle = phone_alloc(TASK); 45 45 46 46 /* Remember the phone capability or the error. */ 47 call->priv = cap;48 if ( cap< 0)49 return ELIMIT;50 47 call->priv = phone_handle; 48 if (phone_handle < 0) 49 return phone_handle; 50 51 51 /* Set arg5 for server */ 52 IPC_SET_ARG5(call->data, (sysarg_t) phone_get_current(cap)); 52 kobject_t *phone_obj = kobject_get(TASK, phone_handle, 53 KOBJECT_TYPE_PHONE); 54 /* Hand over phone_obj's reference to ARG5 */ 55 IPC_SET_ARG5(call->data, (sysarg_t) phone_obj->phone); 53 56 54 57 return EOK; … … 57 60 static int request_forget(call_t *call) 58 61 { 59 phone_dealloc(call->priv); 62 cap_handle_t phone_handle = (cap_handle_t) call->priv; 63 phone_dealloc(phone_handle); 64 /* Hand over reference from ARG5 to phone->kobject */ 65 phone_t *phone = (phone_t *) IPC_GET_ARG5(call->data); 66 /* Drop phone_obj's reference */ 67 kobject_put(phone->kobject); 60 68 return EOK; 61 69 } … … 63 71 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 64 72 { 73 /* Hand over reference from ARG5 to phone */ 65 74 phone_t *phone = (phone_t *) IPC_GET_ARG5(*olddata); 66 75 67 76 /* If the user accepted call, connect */ 68 if (IPC_GET_RETVAL(answer->data) == EOK) 77 if (IPC_GET_RETVAL(answer->data) == EOK) { 78 /* Hand over reference from phone to the answerbox */ 69 79 (void) ipc_phone_connect(phone, &TASK->answerbox); 80 } else { 81 kobject_put(phone->kobject); 82 } 70 83 71 84 return EOK; … … 74 87 static int answer_process(call_t *answer) 75 88 { 76 int cap = (int) answer->priv;89 cap_handle_t phone_handle = (cap_handle_t) answer->priv; 77 90 78 91 if (IPC_GET_RETVAL(answer->data)) { 79 if ( cap>= 0) {92 if (phone_handle >= 0) { 80 93 /* 81 94 * The phone was indeed allocated and now needs 82 95 * to be deallocated. 83 96 */ 84 phone_dealloc( cap);97 phone_dealloc(phone_handle); 85 98 } 86 99 } else { 87 IPC_SET_ARG5(answer->data, cap);100 IPC_SET_ARG5(answer->data, phone_handle); 88 101 } 89 102 -
kernel/generic/src/ipc/ops/concttome.c
rdd20cbb r48bcf49 1 1 /* 2 2 * Copyright (c) 2006 Ondrej Palkovsky 3 * Copyright (c) 2012 Jakub Jermar 3 * Copyright (c) 2012 Jakub Jermar 4 4 * All rights reserved. 5 5 * … … 42 42 static int request_process(call_t *call, answerbox_t *box) 43 43 { 44 int cap= phone_alloc(TASK);44 cap_handle_t phone_handle = phone_alloc(TASK); 45 45 46 IPC_SET_ARG5(call->data, cap);46 IPC_SET_ARG5(call->data, phone_handle); 47 47 48 48 return EOK; … … 51 51 static int answer_cleanup(call_t *answer, ipc_data_t *olddata) 52 52 { 53 int cap = (int) IPC_GET_ARG5(*olddata);53 cap_handle_t phone_handle = (cap_handle_t) IPC_GET_ARG5(*olddata); 54 54 55 if ( cap>= 0)56 phone_dealloc( cap);55 if (phone_handle >= 0) 56 phone_dealloc(phone_handle); 57 57 58 58 return EOK; … … 61 61 static int answer_preprocess(call_t *answer, ipc_data_t *olddata) 62 62 { 63 int cap = (int) IPC_GET_ARG5(*olddata);63 cap_handle_t phone_handle = (cap_handle_t) IPC_GET_ARG5(*olddata); 64 64 65 65 if (IPC_GET_RETVAL(answer->data) != EOK) { 66 66 /* The connection was not accepted */ 67 67 answer_cleanup(answer, olddata); 68 } else if ( cap>= 0) {68 } else if (phone_handle >= 0) { 69 69 /* The connection was accepted */ 70 if (phone_connect(cap, &answer->sender->answerbox)) { 71 /* Set 'phone hash' as arg5 of response */ 70 if (phone_connect(phone_handle, &answer->sender->answerbox)) { 71 /* Set 'phone hash' as ARG5 of response */ 72 kobject_t *phone_obj = kobject_get(TASK, phone_handle, 73 KOBJECT_TYPE_PHONE); 72 74 IPC_SET_ARG5(answer->data, 73 (sysarg_t) phone_get_current(cap)); 75 (sysarg_t) phone_obj->phone); 76 kobject_put(phone_obj); 74 77 } else { 75 78 /* The answerbox is shutting down. */ -
kernel/generic/src/ipc/ops/stchngath.c
rdd20cbb r48bcf49 45 45 task_t *other_task_s; 46 46 47 phone_t *sender_phone = phone_get_current(IPC_GET_ARG5(call->data)); 48 if (!sender_phone) 47 kobject_t *sender_obj = kobject_get(TASK, IPC_GET_ARG5(call->data), 48 KOBJECT_TYPE_PHONE); 49 if (!sender_obj) 49 50 return ENOENT; 50 51 51 mutex_lock(&sender_phone->lock); 52 if (sender_phone->state != IPC_PHONE_CONNECTED) { 53 mutex_unlock(&sender_phone->lock); 52 mutex_lock(&sender_obj->phone->lock); 53 if (sender_obj->phone->state != IPC_PHONE_CONNECTED) { 54 mutex_unlock(&sender_obj->phone->lock); 55 kobject_put(sender_obj); 54 56 return EINVAL; 55 57 } 56 58 57 other_task_s = sender_ phone->callee->task;59 other_task_s = sender_obj->phone->callee->task; 58 60 59 mutex_unlock(&sender_ phone->lock);61 mutex_unlock(&sender_obj->phone->lock); 60 62 61 63 /* Remember the third party task hash. */ 62 64 IPC_SET_ARG5(call->data, (sysarg_t) other_task_s); 63 65 66 kobject_put(sender_obj); 64 67 return EOK; 65 68 } … … 71 74 if (!IPC_GET_RETVAL(answer->data)) { 72 75 /* The recipient authorized the change of state. */ 73 phone_t *recipient_phone;74 76 task_t *other_task_s; 75 77 task_t *other_task_r; 76 78 77 recipient_phone = phone_get_current(IPC_GET_ARG1(answer->data)); 78 if (!recipient_phone) { 79 kobject_t *recipient_obj = kobject_get(TASK, 80 IPC_GET_ARG1(answer->data), KOBJECT_TYPE_PHONE); 81 if (!recipient_obj) { 79 82 IPC_SET_RETVAL(answer->data, ENOENT); 80 83 return ENOENT; 81 84 } 82 85 83 mutex_lock(&recipient_ phone->lock);84 if (recipient_ phone->state != IPC_PHONE_CONNECTED) {85 mutex_unlock(&recipient_ phone->lock);86 mutex_lock(&recipient_obj->phone->lock); 87 if (recipient_obj->phone->state != IPC_PHONE_CONNECTED) { 88 mutex_unlock(&recipient_obj->phone->lock); 86 89 IPC_SET_RETVAL(answer->data, EINVAL); 90 kobject_put(recipient_obj); 87 91 return EINVAL; 88 92 } 89 93 90 other_task_r = recipient_ phone->callee->task;94 other_task_r = recipient_obj->phone->callee->task; 91 95 other_task_s = (task_t *) IPC_GET_ARG5(*olddata); 92 96 … … 109 113 } 110 114 111 mutex_unlock(&recipient_phone->lock); 115 mutex_unlock(&recipient_obj->phone->lock); 116 kobject_put(recipient_obj); 112 117 } 113 118 -
kernel/generic/src/ipc/sysipc.c
rdd20cbb r48bcf49 260 260 /** Make a call over IPC and wait for reply. 261 261 * 262 * @param phone_cap Phone capabilityfor the call.262 * @param handle Phone capability handle for the call. 263 263 * @param data[inout] Structure with request/reply data. 264 264 * @param priv Value to be stored in call->priv. … … 268 268 * 269 269 */ 270 int ipc_req_internal( int phone_cap, ipc_data_t *data, sysarg_t priv)271 { 272 phone_t *phone = phone_get_current(phone_cap);273 if (! phone)270 int ipc_req_internal(cap_handle_t handle, ipc_data_t *data, sysarg_t priv) 271 { 272 kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); 273 if (!kobj->phone) 274 274 return ENOENT; 275 275 … … 278 278 memcpy(call->data.args, data->args, sizeof(data->args)); 279 279 280 int rc = request_preprocess(call, phone);280 int rc = request_preprocess(call, kobj->phone); 281 281 if (!rc) { 282 282 #ifdef CONFIG_UDEBUG … … 285 285 286 286 ipc_call_hold(call); 287 rc = ipc_call_sync( phone, call);287 rc = ipc_call_sync(kobj->phone, call); 288 288 spinlock_lock(&call->forget_lock); 289 289 bool forgotten = call->forget; … … 312 312 assert(rc == EINTR); 313 313 } 314 return rc; 314 kobject_put(kobj); 315 return rc; 315 316 } 316 317 … … 321 322 memcpy(data->args, call->data.args, sizeof(data->args)); 322 323 ipc_call_free(call); 324 kobject_put(kobj); 323 325 324 326 return EOK; … … 346 348 * the generic function sys_ipc_call_async_slow(). 347 349 * 348 * @param phone_cap Phone capabilityfor the call.349 * @param imethod 350 * @param arg1 351 * @param arg2 352 * @param arg3 353 * @param arg4 350 * @param handle Phone capability handle for the call. 351 * @param imethod Interface and method of the call. 352 * @param arg1 Service-defined payload argument. 353 * @param arg2 Service-defined payload argument. 354 * @param arg3 Service-defined payload argument. 355 * @param arg4 Service-defined payload argument. 354 356 * 355 357 * @return Call hash on success. … … 359 361 * 360 362 */ 361 sysarg_t sys_ipc_call_async_fast(sysarg_t phone_cap, sysarg_t imethod,363 sysarg_t sys_ipc_call_async_fast(sysarg_t handle, sysarg_t imethod, 362 364 sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, sysarg_t arg4) 363 365 { 364 phone_t *phone = phone_get_current(phone_cap);365 if (! phone)366 kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); 367 if (!kobj) 366 368 return IPC_CALLRET_FATAL; 367 369 368 if (check_call_limit(phone)) 370 if (check_call_limit(kobj->phone)) { 371 kobject_put(kobj); 369 372 return IPC_CALLRET_TEMPORARY; 373 } 370 374 371 375 call_t *call = ipc_call_alloc(0); … … 382 386 IPC_SET_ARG5(call->data, 0); 383 387 384 int res = request_preprocess(call, phone);388 int res = request_preprocess(call, kobj->phone); 385 389 386 390 if (!res) 387 ipc_call( phone, call);391 ipc_call(kobj->phone, call); 388 392 else 389 ipc_backsend_err(phone, call, res); 390 393 ipc_backsend_err(kobj->phone, call, res); 394 395 kobject_put(kobj); 391 396 return (sysarg_t) call; 392 397 } … … 394 399 /** Make an asynchronous IPC call allowing to transmit the entire payload. 395 400 * 396 * @param phone_capPhone capability for the call.397 * @param data 401 * @param handle Phone capability for the call. 402 * @param data Userspace address of call data with the request. 398 403 * 399 404 * @return See sys_ipc_call_async_fast(). 400 405 * 401 406 */ 402 sysarg_t sys_ipc_call_async_slow(sysarg_t phone_cap, ipc_data_t *data)403 { 404 phone_t *phone = phone_get_current(phone_cap);405 if (! phone)407 sysarg_t sys_ipc_call_async_slow(sysarg_t handle, ipc_data_t *data) 408 { 409 kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); 410 if (!kobj) 406 411 return IPC_CALLRET_FATAL; 407 412 408 if (check_call_limit(phone)) 413 if (check_call_limit(kobj->phone)) { 414 kobject_put(kobj); 409 415 return IPC_CALLRET_TEMPORARY; 416 } 410 417 411 418 call_t *call = ipc_call_alloc(0); … … 414 421 if (rc != 0) { 415 422 ipc_call_free(call); 423 kobject_put(kobj); 416 424 return (sysarg_t) rc; 417 425 } 418 426 419 int res = request_preprocess(call, phone);427 int res = request_preprocess(call, kobj->phone); 420 428 421 429 if (!res) 422 ipc_call( phone, call);430 ipc_call(kobj->phone, call); 423 431 else 424 ipc_backsend_err(phone, call, res); 425 432 ipc_backsend_err(kobj->phone, call, res); 433 434 kobject_put(kobj); 426 435 return (sysarg_t) call; 427 436 } … … 431 440 * Common code for both the fast and the slow version. 432 441 * 433 * @param callid 434 * @param phone_capPhone capability to use for forwarding.435 * @param imethod 436 * @param arg1 437 * @param arg2 438 * @param arg3 439 * @param arg4 440 * @param arg5 441 * @param mode 442 * @param slow 443 * 444 * 442 * @param callid Hash of the call to forward. 443 * @param handle Phone capability to use for forwarding. 444 * @param imethod New interface and method to use for the forwarded call. 445 * @param arg1 New value of the first argument for the forwarded call. 446 * @param arg2 New value of the second argument for the forwarded call. 447 * @param arg3 New value of the third argument for the forwarded call. 448 * @param arg4 New value of the fourth argument for the forwarded call. 449 * @param arg5 New value of the fifth argument for the forwarded call. 450 * @param mode Flags that specify mode of the forward operation. 451 * @param slow If true, arg3, arg4 and arg5 are considered. Otherwise 452 * the function considers only the fast version arguments: 453 * i.e. arg1 and arg2. 445 454 * 446 455 * @return 0 on succes, otherwise an error code. … … 449 458 * 450 459 */ 451 static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t phone_cap,460 static sysarg_t sys_ipc_forward_common(sysarg_t callid, sysarg_t handle, 452 461 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, sysarg_t arg3, 453 462 sysarg_t arg4, sysarg_t arg5, unsigned int mode, bool slow) … … 465 474 int rc; 466 475 467 phone_t *phone = phone_get_current(phone_cap);468 if (! phone) {476 kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); 477 if (!kobj) { 469 478 rc = ENOENT; 470 479 goto error; … … 512 521 } 513 522 514 rc = ipc_forward(call, phone, &TASK->answerbox, mode);523 rc = ipc_forward(call, kobj->phone, &TASK->answerbox, mode); 515 524 if (rc != EOK) { 516 525 after_forward = true; … … 518 527 } 519 528 529 kobject_put(kobj); 520 530 return EOK; 521 531 … … 528 538 ipc_answer(&TASK->answerbox, call); 529 539 540 if (kobj) 541 kobject_put(kobj); 530 542 return rc; 531 543 } … … 540 552 * arguments are not set and these values are ignored. 541 553 * 542 * @param callid Hash of the call to forward.543 * @param phoneidPhone handle to use for forwarding.544 * @param imethod New interface and method to use for the forwarded call.545 * @param arg1 New value of the first argument for the forwarded call.546 * @param arg2 New value of the second argument for the forwarded call.547 * @param mode Flags that specify mode of the forward operation.554 * @param callid Hash of the call to forward. 555 * @param handle Phone handle to use for forwarding. 556 * @param imethod New interface and method to use for the forwarded call. 557 * @param arg1 New value of the first argument for the forwarded call. 558 * @param arg2 New value of the second argument for the forwarded call. 559 * @param mode Flags that specify mode of the forward operation. 548 560 * 549 561 * @return 0 on succes, otherwise an error code. 550 562 * 551 563 */ 552 sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t phoneid,564 sysarg_t sys_ipc_forward_fast(sysarg_t callid, sysarg_t handle, 553 565 sysarg_t imethod, sysarg_t arg1, sysarg_t arg2, unsigned int mode) 554 566 { 555 return sys_ipc_forward_common(callid, phoneid, imethod, arg1, arg2, 0, 0,567 return sys_ipc_forward_common(callid, handle, imethod, arg1, arg2, 0, 0, 556 568 0, mode, false); 557 569 } … … 567 579 * 568 580 * @param callid Hash of the call to forward. 569 * @param phoneidPhone handle to use for forwarding.581 * @param handle Phone handle to use for forwarding. 570 582 * @param data Userspace address of the new IPC data. 571 583 * @param mode Flags that specify mode of the forward operation. … … 574 586 * 575 587 */ 576 sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t phoneid,588 sysarg_t sys_ipc_forward_slow(sysarg_t callid, sysarg_t handle, 577 589 ipc_data_t *data, unsigned int mode) 578 590 { … … 583 595 return (sysarg_t) rc; 584 596 585 return sys_ipc_forward_common(callid, phoneid,597 return sys_ipc_forward_common(callid, handle, 586 598 IPC_GET_IMETHOD(newdata), IPC_GET_ARG1(newdata), 587 599 IPC_GET_ARG2(newdata), IPC_GET_ARG3(newdata), … … 681 693 /** Hang up a phone. 682 694 * 683 * @param phone_cap Phone capabilityof the phone to be hung up.695 * @param handle Phone capability handle of the phone to be hung up. 684 696 * 685 697 * @return 0 on success or an error code. 686 698 * 687 699 */ 688 sysarg_t sys_ipc_hangup(sysarg_t phone_cap)689 { 690 phone_t *phone = phone_get_current(phone_cap);691 if (! phone)700 sysarg_t sys_ipc_hangup(sysarg_t handle) 701 { 702 kobject_t *kobj = kobject_get(TASK, handle, KOBJECT_TYPE_PHONE); 703 if (!kobj) 692 704 return ENOENT; 693 705 694 if (ipc_phone_hangup(phone)) 706 if (ipc_phone_hangup(kobj->phone)) { 707 kobject_put(kobj); 695 708 return -1; 696 709 } 710 711 kobject_put(kobj); 697 712 return 0; 698 713 } -
kernel/generic/src/proc/task.c
rdd20cbb r48bcf49 239 239 if ((ipc_phone_0) && 240 240 (container_check(ipc_phone_0->task->container, task->container))) { 241 int cap = phone_alloc(task); 242 assert(cap == 0); 243 (void) ipc_phone_connect(phone_get(task, 0), ipc_phone_0); 241 cap_handle_t phone_handle = phone_alloc(task); 242 kobject_t *phone_obj = kobject_get(task, phone_handle, 243 KOBJECT_TYPE_PHONE); 244 (void) ipc_phone_connect(phone_obj->phone, ipc_phone_0); 244 245 } 245 246
Note:
See TracChangeset
for help on using the changeset viewer.