Changes in kernel/generic/src/ipc/kbox.c [228e490:2c0e5d2] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/ipc/kbox.c
r228e490 r2c0e5d2 47 47 void ipc_kbox_cleanup(void) 48 48 { 49 /* 49 ipl_t ipl; 50 bool have_kb_thread; 51 52 /* 50 53 * Only hold kb.cleanup_lock while setting kb.finished - 51 54 * this is enough. … … 54 57 TASK->kb.finished = true; 55 58 mutex_unlock(&TASK->kb.cleanup_lock); 56 57 boolhave_kb_thread = (TASK->kb.thread != NULL);58 59 60 have_kb_thread = (TASK->kb.thread != NULL); 61 59 62 /* 60 63 * From now on nobody will try to connect phones or attach 61 64 * kbox threads 62 65 */ 63 66 64 67 /* 65 68 * Disconnect all phones connected to our kbox. Passing true for … … 69 72 */ 70 73 ipc_answerbox_slam_phones(&TASK->kb.box, have_kb_thread); 71 72 /* 74 75 /* 73 76 * If the task was being debugged, clean up debugging session. 74 77 * This is necessarry as slamming the phones won't force 75 78 * kbox thread to clean it up since sender != debugger. 76 79 */ 77 mutex_lock(&TASK->udebug.lock); 80 ipl = interrupts_disable(); 81 spinlock_lock(&TASK->lock); 78 82 udebug_task_cleanup(TASK); 79 mutex_unlock(&TASK->udebug.lock); 83 spinlock_unlock(&TASK->lock); 84 interrupts_restore(ipl); 80 85 81 86 if (have_kb_thread) { … … 86 91 TASK->kb.thread = NULL; 87 92 } 88 93 89 94 /* Answer all messages in 'calls' and 'dispatched_calls' queues. */ 90 irq_spinlock_lock(&TASK->kb.box.lock, true);95 spinlock_lock(&TASK->kb.box.lock); 91 96 ipc_cleanup_call_list(&TASK->kb.box.dispatched_calls); 92 97 ipc_cleanup_call_list(&TASK->kb.box.calls); 93 irq_spinlock_unlock(&TASK->kb.box.lock, true);98 spinlock_unlock(&TASK->kb.box.lock); 94 99 } 95 100 96 101 /** Handle hangup message in kbox. 97 102 * 98 * @param call The IPC_M_PHONE_HUNGUP call structure. 99 * @param last Output, the function stores @c true here if 100 * this was the last phone, @c false otherwise. 101 * 102 */ 103 * @param call The IPC_M_PHONE_HUNGUP call structure. 104 * @param last Output, the function stores @c true here if 105 * this was the last phone, @c false otherwise. 106 **/ 103 107 static void kbox_proc_phone_hungup(call_t *call, bool *last) 104 108 { 109 ipl_t ipl; 110 105 111 /* Was it our debugger, who hung up? */ 106 112 if (call->sender == TASK->udebug.debugger) { 107 113 /* Terminate debugging session (if any). */ 108 114 LOG("Terminate debugging session."); 109 mutex_lock(&TASK->udebug.lock); 115 ipl = interrupts_disable(); 116 spinlock_lock(&TASK->lock); 110 117 udebug_task_cleanup(TASK); 111 mutex_unlock(&TASK->udebug.lock); 118 spinlock_unlock(&TASK->lock); 119 interrupts_restore(ipl); 112 120 } else { 113 121 LOG("Was not debugger."); 114 122 } 115 123 116 124 LOG("Continue with hangup message."); 117 125 IPC_SET_RETVAL(call->data, 0); 118 126 ipc_answer(&TASK->kb.box, call); 119 120 mutex_lock(&TASK->kb.cleanup_lock); 121 122 irq_spinlock_lock(&TASK->lock, true); 123 irq_spinlock_lock(&TASK->kb.box.lock, false); 127 128 ipl = interrupts_disable(); 129 spinlock_lock(&TASK->lock); 130 spinlock_lock(&TASK->kb.box.lock); 124 131 if (list_empty(&TASK->kb.box.connected_phones)) { 125 132 /* … … 127 134 * gets freed and signal to the caller. 128 135 */ 129 136 130 137 /* Only detach kbox thread unless already terminating. */ 131 if (TASK->kb.finished == false) { 138 mutex_lock(&TASK->kb.cleanup_lock); 139 if (&TASK->kb.finished == false) { 132 140 /* Detach kbox thread so it gets freed from memory. */ 133 141 thread_detach(TASK->kb.thread); 134 142 TASK->kb.thread = NULL; 135 143 } 136 144 mutex_unlock(&TASK->kb.cleanup_lock); 145 137 146 LOG("Phone list is empty."); 138 147 *last = true; 139 } else 148 } else { 140 149 *last = false; 141 142 irq_spinlock_unlock(&TASK->kb.box.lock, false); 143 irq_spinlock_unlock(&TASK->lock, true);144 145 mutex_unlock(&TASK->kb.cleanup_lock);150 } 151 152 spinlock_unlock(&TASK->kb.box.lock); 153 spinlock_unlock(&TASK->lock); 154 interrupts_restore(ipl); 146 155 } 147 156 … … 151 160 * when all phones are disconnected from the kbox. 152 161 * 153 * @param arg Ignored. 154 * 162 * @param arg Ignored. 155 163 */ 156 164 static void kbox_thread_proc(void *arg) 157 165 { 158 (void) arg; 166 call_t *call; 167 bool done; 168 169 (void)arg; 159 170 LOG("Starting."); 160 booldone = false;161 171 done = false; 172 162 173 while (!done) { 163 call _t *call= ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT,174 call = ipc_wait_for_call(&TASK->kb.box, SYNCH_NO_TIMEOUT, 164 175 SYNCH_FLAGS_NONE); 165 176 166 177 if (call == NULL) 167 continue; 168 169 switch (IPC_GET_ IMETHOD(call->data)) {170 178 continue; /* Try again. */ 179 180 switch (IPC_GET_METHOD(call->data)) { 181 171 182 case IPC_M_DEBUG_ALL: 172 183 /* Handle debug call. */ 173 184 udebug_call_receive(call); 174 185 break; 175 186 176 187 case IPC_M_PHONE_HUNGUP: 177 188 /* … … 182 193 kbox_proc_phone_hungup(call, &done); 183 194 break; 184 195 185 196 default: 186 197 /* Ignore */ … … 188 199 } 189 200 } 190 201 191 202 LOG("Exiting."); 192 203 } 193 204 194 /** Connect phone to a task kernel-box specified by id. 205 206 /** 207 * Connect phone to a task kernel-box specified by id. 195 208 * 196 209 * Note that this is not completely atomic. For optimisation reasons, the task … … 199 212 * cleanup code. 200 213 * 201 * @return Phone id on success, or negative error code. 202 * 214 * @return Phone id on success, or negative error code. 203 215 */ 204 216 int ipc_connect_kbox(task_id_t taskid) 205 217 { 206 irq_spinlock_lock(&tasks_lock, true); 207 208 task_t *task = task_find_by_id(taskid); 209 if (task == NULL) { 210 irq_spinlock_unlock(&tasks_lock, true); 218 int newphid; 219 task_t *ta; 220 thread_t *kb_thread; 221 ipl_t ipl; 222 223 ipl = interrupts_disable(); 224 spinlock_lock(&tasks_lock); 225 226 ta = task_find_by_id(taskid); 227 if (ta == NULL) { 228 spinlock_unlock(&tasks_lock); 229 interrupts_restore(ipl); 211 230 return ENOENT; 212 231 } 213 214 atomic_inc(&task->refcount); 215 216 irq_spinlock_unlock(&tasks_lock, true); 217 218 mutex_lock(&task->kb.cleanup_lock); 219 220 if (atomic_predec(&task->refcount) == 0) { 221 mutex_unlock(&task->kb.cleanup_lock); 222 task_destroy(task); 232 233 atomic_inc(&ta->refcount); 234 235 spinlock_unlock(&tasks_lock); 236 interrupts_restore(ipl); 237 238 mutex_lock(&ta->kb.cleanup_lock); 239 240 if (atomic_predec(&ta->refcount) == 0) { 241 mutex_unlock(&ta->kb.cleanup_lock); 242 task_destroy(ta); 223 243 return ENOENT; 224 244 } 225 226 if (ta sk->kb.finished != false) {227 mutex_unlock(&ta sk->kb.cleanup_lock);245 246 if (ta->kb.finished != false) { 247 mutex_unlock(&ta->kb.cleanup_lock); 228 248 return EINVAL; 229 249 } 230 231 intnewphid = phone_alloc(TASK);250 251 newphid = phone_alloc(TASK); 232 252 if (newphid < 0) { 233 mutex_unlock(&ta sk->kb.cleanup_lock);253 mutex_unlock(&ta->kb.cleanup_lock); 234 254 return ELIMIT; 235 255 } 236 256 237 257 /* Connect the newly allocated phone to the kbox */ 238 ipc_phone_connect(&TASK->phones[newphid], &ta sk->kb.box);239 240 if (ta sk->kb.thread != NULL) {241 mutex_unlock(&ta sk->kb.cleanup_lock);258 ipc_phone_connect(&TASK->phones[newphid], &ta->kb.box); 259 260 if (ta->kb.thread != NULL) { 261 mutex_unlock(&ta->kb.cleanup_lock); 242 262 return newphid; 243 263 } 244 264 245 265 /* Create a kbox thread */ 246 thread_t *kb_thread = thread_create(kbox_thread_proc, NULL, task, 0,266 kb_thread = thread_create(kbox_thread_proc, NULL, ta, 0, 247 267 "kbox", false); 248 268 if (!kb_thread) { 249 mutex_unlock(&ta sk->kb.cleanup_lock);269 mutex_unlock(&ta->kb.cleanup_lock); 250 270 return ENOMEM; 251 271 } 252 253 ta sk->kb.thread = kb_thread;272 273 ta->kb.thread = kb_thread; 254 274 thread_ready(kb_thread); 255 256 mutex_unlock(&ta sk->kb.cleanup_lock);257 275 276 mutex_unlock(&ta->kb.cleanup_lock); 277 258 278 return newphid; 259 279 }
Note:
See TracChangeset
for help on using the changeset viewer.