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