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