Rev 1086 | Rev 1090 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1086 | Rev 1088 | ||
|---|---|---|---|
| Line 102... | Line 102... | ||
| 102 | void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
102 | void ipc_phone_connect(phone_t *phone, answerbox_t *box) |
| 103 | { |
103 | { |
| 104 | spinlock_lock(&phone->lock); |
104 | spinlock_lock(&phone->lock); |
| 105 | 105 | ||
| 106 | ASSERT(!phone->callee); |
106 | ASSERT(!phone->callee); |
| 107 | phone->busy = 1; |
107 | phone->busy = IPC_BUSY_CONNECTED; |
| 108 | phone->callee = box; |
108 | phone->callee = box; |
| 109 | 109 | ||
| 110 | spinlock_lock(&box->lock); |
110 | spinlock_lock(&box->lock); |
| 111 | list_append(&phone->list, &box->connected_phones); |
111 | list_append(&phone->list, &box->connected_phones); |
| 112 | spinlock_unlock(&box->lock); |
112 | spinlock_unlock(&box->lock); |
| Line 118... | Line 118... | ||
| 118 | */ |
118 | */ |
| 119 | void ipc_phone_init(phone_t *phone) |
119 | void ipc_phone_init(phone_t *phone) |
| 120 | { |
120 | { |
| 121 | spinlock_initialize(&phone->lock, "phone_lock"); |
121 | spinlock_initialize(&phone->lock, "phone_lock"); |
| 122 | phone->callee = NULL; |
122 | phone->callee = NULL; |
| 123 | phone->busy = 0; |
123 | phone->busy = IPC_BUSY_FREE; |
| - | 124 | atomic_set(&phone->active_calls, 0); |
|
| 124 | } |
125 | } |
| 125 | 126 | ||
| 126 | /** Helper function to facilitate synchronous calls */ |
127 | /** Helper function to facilitate synchronous calls */ |
| 127 | void ipc_call_sync(phone_t *phone, call_t *request) |
128 | void ipc_call_sync(phone_t *phone, call_t *request) |
| 128 | { |
129 | { |
| Line 169... | Line 170... | ||
| 169 | } |
170 | } |
| 170 | 171 | ||
| 171 | /* Unsafe unchecking ipc_call */ |
172 | /* Unsafe unchecking ipc_call */ |
| 172 | static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) |
173 | static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) |
| 173 | { |
174 | { |
| - | 175 | if (! (call->flags & IPC_CALL_FORWARDED)) { |
|
| 174 | atomic_inc(&phone->active_calls); |
176 | atomic_inc(&phone->active_calls); |
| 175 | call->data.phone = phone; |
177 | call->data.phone = phone; |
| - | 178 | } |
|
| 176 | 179 | ||
| 177 | spinlock_lock(&box->lock); |
180 | spinlock_lock(&box->lock); |
| 178 | list_append(&call->list, &box->calls); |
181 | list_append(&call->list, &box->calls); |
| 179 | spinlock_unlock(&box->lock); |
182 | spinlock_unlock(&box->lock); |
| 180 | waitq_wakeup(&box->wq, 0); |
183 | waitq_wakeup(&box->wq, 0); |
| Line 183... | Line 186... | ||
| 183 | /** Send a asynchronous request using phone to answerbox |
186 | /** Send a asynchronous request using phone to answerbox |
| 184 | * |
187 | * |
| 185 | * @param phone Phone connected to answerbox |
188 | * @param phone Phone connected to answerbox |
| 186 | * @param request Request to be sent |
189 | * @param request Request to be sent |
| 187 | */ |
190 | */ |
| 188 | void ipc_call(phone_t *phone, call_t *call) |
191 | int ipc_call(phone_t *phone, call_t *call) |
| 189 | { |
192 | { |
| 190 | answerbox_t *box; |
193 | answerbox_t *box; |
| 191 | 194 | ||
| 192 | spinlock_lock(&phone->lock); |
195 | spinlock_lock(&phone->lock); |
| 193 | 196 | ||
| 194 | box = phone->callee; |
197 | box = phone->callee; |
| 195 | if (!box) { |
198 | if (!box) { |
| 196 | /* Trying to send over disconnected phone */ |
199 | /* Trying to send over disconnected phone */ |
| 197 | spinlock_unlock(&phone->lock); |
200 | spinlock_unlock(&phone->lock); |
| - | 201 | if (call->flags & IPC_CALL_FORWARDED) { |
|
| - | 202 | IPC_SET_RETVAL(call->data, EFORWARD); |
|
| - | 203 | } else { /* Simulate sending a message */ |
|
| - | 204 | call->data.phone = phone; |
|
| - | 205 | atomic_inc(&phone->active_calls); |
|
| - | 206 | if (phone->busy == IPC_BUSY_CONNECTED) |
|
| - | 207 | IPC_SET_RETVAL(call->data, EHANGUP); |
|
| - | 208 | else |
|
| - | 209 | IPC_SET_RETVAL(call->data, ENOENT); |
|
| - | 210 | } |
|
| 198 | 211 | ||
| 199 | call->data.phone = phone; |
- | |
| 200 | IPC_SET_RETVAL(call->data, ENOENT); |
- | |
| 201 | _ipc_answer_free_call(call); |
212 | _ipc_answer_free_call(call); |
| 202 | return; |
213 | return ENOENT; |
| 203 | } |
214 | } |
| 204 | _ipc_call(phone, box, call); |
215 | _ipc_call(phone, box, call); |
| 205 | 216 | ||
| 206 | spinlock_unlock(&phone->lock); |
217 | spinlock_unlock(&phone->lock); |
| - | 218 | return 0; |
|
| 207 | } |
219 | } |
| 208 | 220 | ||
| 209 | /** Disconnect phone from answerbox |
221 | /** Disconnect phone from answerbox |
| 210 | * |
222 | * |
| 211 | * It is allowed to call disconnect on already disconnected phone |
223 | * It is allowed to call disconnect on already disconnected phone |
| Line 218... | Line 230... | ||
| 218 | call_t *call; |
230 | call_t *call; |
| 219 | 231 | ||
| 220 | spinlock_lock(&phone->lock); |
232 | spinlock_lock(&phone->lock); |
| 221 | box = phone->callee; |
233 | box = phone->callee; |
| 222 | if (!box) { |
234 | if (!box) { |
| - | 235 | if (phone->busy == IPC_BUSY_CONNECTING) { |
|
| - | 236 | spinlock_unlock(&phone->lock); |
|
| - | 237 | return -1; |
|
| - | 238 | } |
|
| - | 239 | /* Already disconnected phone */ |
|
| - | 240 | phone->busy = IPC_BUSY_FREE; |
|
| 223 | spinlock_unlock(&phone->lock); |
241 | spinlock_unlock(&phone->lock); |
| 224 | return -1; |
242 | return 0; |
| 225 | } |
243 | } |
| 226 | 244 | ||
| 227 | spinlock_lock(&box->lock); |
245 | spinlock_lock(&box->lock); |
| 228 | list_remove(&phone->list); |
246 | list_remove(&phone->list); |
| 229 | phone->callee = NULL; |
247 | phone->callee = NULL; |
| Line 232... | Line 250... | ||
| 232 | call = ipc_call_alloc(); |
250 | call = ipc_call_alloc(); |
| 233 | IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
251 | IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
| 234 | call->flags |= IPC_CALL_DISCARD_ANSWER; |
252 | call->flags |= IPC_CALL_DISCARD_ANSWER; |
| 235 | _ipc_call(phone, box, call); |
253 | _ipc_call(phone, box, call); |
| 236 | 254 | ||
| 237 | phone->busy = 0; |
255 | phone->busy = IPC_BUSY_FREE; |
| 238 | 256 | ||
| 239 | spinlock_unlock(&phone->lock); |
257 | spinlock_unlock(&phone->lock); |
| 240 | 258 | ||
| 241 | return 0; |
259 | return 0; |
| 242 | } |
260 | } |
| Line 244... | Line 262... | ||
| 244 | /** Forwards call from one answerbox to a new one |
262 | /** Forwards call from one answerbox to a new one |
| 245 | * |
263 | * |
| 246 | * @param request Request to be forwarded |
264 | * @param request Request to be forwarded |
| 247 | * @param newbox Target answerbox |
265 | * @param newbox Target answerbox |
| 248 | * @param oldbox Old answerbox |
266 | * @param oldbox Old answerbox |
| - | 267 | * @return 0 on forward ok, error code, if there was error |
|
| - | 268 | * |
|
| - | 269 | * - the return value serves only as an information for the forwarder, |
|
| - | 270 | * the original caller is notified automatically with EFORWARD |
|
| 249 | */ |
271 | */ |
| 250 | void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) |
272 | int ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) |
| 251 | { |
273 | { |
| 252 | spinlock_lock(&oldbox->lock); |
274 | spinlock_lock(&oldbox->lock); |
| 253 | atomic_dec(&call->data.phone->active_calls); |
- | |
| 254 | list_remove(&call->list); |
275 | list_remove(&call->list); |
| 255 | spinlock_unlock(&oldbox->lock); |
276 | spinlock_unlock(&oldbox->lock); |
| 256 | 277 | ||
| 257 | ipc_call(newphone, call); |
278 | return ipc_call(newphone, call); |
| 258 | } |
279 | } |
| 259 | 280 | ||
| 260 | 281 | ||
| 261 | /** Wait for phone call |
282 | /** Wait for phone call |
| 262 | * |
283 | * |
| Line 277... | Line 298... | ||
| 277 | spinlock_lock(&box->lock); |
298 | spinlock_lock(&box->lock); |
| 278 | if (!list_empty(&box->answers)) { |
299 | if (!list_empty(&box->answers)) { |
| 279 | /* Handle asynchronous answers */ |
300 | /* Handle asynchronous answers */ |
| 280 | request = list_get_instance(box->answers.next, call_t, list); |
301 | request = list_get_instance(box->answers.next, call_t, list); |
| 281 | list_remove(&request->list); |
302 | list_remove(&request->list); |
| 282 | printf("%d %P\n", IPC_GET_METHOD(request->data), |
- | |
| 283 | request->data.phone); |
- | |
| 284 | atomic_dec(&request->data.phone->active_calls); |
303 | atomic_dec(&request->data.phone->active_calls); |
| 285 | } else if (!list_empty(&box->calls)) { |
304 | } else if (!list_empty(&box->calls)) { |
| 286 | /* Handle requests */ |
305 | /* Handle requests */ |
| 287 | request = list_get_instance(box->calls.next, call_t, list); |
306 | request = list_get_instance(box->calls.next, call_t, list); |
| 288 | list_remove(&request->list); |
307 | list_remove(&request->list); |
| Line 311... | Line 330... | ||
| 311 | * |
330 | * |
| 312 | * |
331 | * |
| 313 | */ |
332 | */ |
| 314 | void ipc_cleanup(task_t *task) |
333 | void ipc_cleanup(task_t *task) |
| 315 | { |
334 | { |
| - | 335 | int i; |
|
| - | 336 | ||
| - | 337 | /* Disconnect all our phones ('ipc_phone_hangup') */ |
|
| - | 338 | for (i=0;i < IPC_MAX_PHONES; i++) |
|
| - | 339 | ipc_phone_hangup(&task->phones[i]); |
|
| - | 340 | ||
| - | 341 | /* Disconnect all phones connected to answerbox */ |
|
| - | 342 | ||
| 316 | /* Cancel all calls in my dispatch queue */ |
343 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
| 317 | 344 | ||
| - | 345 | /* Wait for all async answers to arrive */ |
|
| 318 | } |
346 | } |