Rev 1084 | Rev 1088 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 1084 | Rev 1086 | ||
|---|---|---|---|
| Line 121... | Line 121... | ||
| 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 = 0; |
| 124 | } |
124 | } |
| 125 | 125 | ||
| 126 | /** Disconnect phone from answerbox |
- | |
| 127 | * |
- | |
| 128 | * It is allowed to call disconnect on already disconnected phone\ |
- | |
| 129 | */ |
- | |
| 130 | void ipc_phone_destroy(phone_t *phone) |
- | |
| 131 | { |
- | |
| 132 | answerbox_t *box = phone->callee; |
- | |
| 133 | - | ||
| 134 | ASSERT(box); |
- | |
| 135 | - | ||
| 136 | spinlock_lock(&phone->lock); |
- | |
| 137 | spinlock_lock(&box->lock); |
- | |
| 138 | - | ||
| 139 | if (phone->callee) { |
- | |
| 140 | list_remove(&phone->list); |
- | |
| 141 | phone->callee = NULL; |
- | |
| 142 | } |
- | |
| 143 | - | ||
| 144 | spinlock_unlock(&box->lock); |
- | |
| 145 | spinlock_unlock(&phone->lock); |
- | |
| 146 | } |
- | |
| 147 | - | ||
| 148 | /** Helper function to facilitate synchronous calls */ |
126 | /** Helper function to facilitate synchronous calls */ |
| 149 | void ipc_call_sync(phone_t *phone, call_t *request) |
127 | void ipc_call_sync(phone_t *phone, call_t *request) |
| 150 | { |
128 | { |
| 151 | answerbox_t sync_box; |
129 | answerbox_t sync_box; |
| 152 | 130 | ||
| Line 188... | Line 166... | ||
| 188 | spinlock_unlock(&box->lock); |
166 | spinlock_unlock(&box->lock); |
| 189 | /* Send back answer */ |
167 | /* Send back answer */ |
| 190 | _ipc_answer_free_call(call); |
168 | _ipc_answer_free_call(call); |
| 191 | } |
169 | } |
| 192 | 170 | ||
| - | 171 | /* Unsafe unchecking ipc_call */ |
|
| - | 172 | static void _ipc_call(phone_t *phone, answerbox_t *box, call_t *call) |
|
| - | 173 | { |
|
| - | 174 | atomic_inc(&phone->active_calls); |
|
| - | 175 | call->data.phone = phone; |
|
| - | 176 | ||
| - | 177 | spinlock_lock(&box->lock); |
|
| - | 178 | list_append(&call->list, &box->calls); |
|
| - | 179 | spinlock_unlock(&box->lock); |
|
| - | 180 | waitq_wakeup(&box->wq, 0); |
|
| - | 181 | } |
|
| - | 182 | ||
| 193 | /** Send a asynchronous request using phone to answerbox |
183 | /** Send a asynchronous request using phone to answerbox |
| 194 | * |
184 | * |
| 195 | * @param phone Phone connected to answerbox |
185 | * @param phone Phone connected to answerbox |
| 196 | * @param request Request to be sent |
186 | * @param request Request to be sent |
| 197 | */ |
187 | */ |
| 198 | void ipc_call(phone_t *phone, call_t *call) |
188 | void ipc_call(phone_t *phone, call_t *call) |
| 199 | { |
189 | { |
| 200 | answerbox_t *box; |
190 | answerbox_t *box; |
| 201 | 191 | ||
| 202 | spinlock_lock(&phone->lock); |
192 | spinlock_lock(&phone->lock); |
| - | 193 | ||
| 203 | box = phone->callee; |
194 | box = phone->callee; |
| 204 | if (!box) { |
195 | if (!box) { |
| 205 | /* Trying to send over disconnected phone */ |
196 | /* Trying to send over disconnected phone */ |
| - | 197 | spinlock_unlock(&phone->lock); |
|
| - | 198 | ||
| - | 199 | call->data.phone = phone; |
|
| 206 | IPC_SET_RETVAL(call->data, ENOENT); |
200 | IPC_SET_RETVAL(call->data, ENOENT); |
| 207 | _ipc_answer_free_call(call); |
201 | _ipc_answer_free_call(call); |
| 208 | return; |
202 | return; |
| 209 | } |
203 | } |
| - | 204 | _ipc_call(phone, box, call); |
|
| - | 205 | ||
| - | 206 | spinlock_unlock(&phone->lock); |
|
| - | 207 | } |
|
| - | 208 | ||
| - | 209 | /** Disconnect phone from answerbox |
|
| - | 210 | * |
|
| - | 211 | * It is allowed to call disconnect on already disconnected phone |
|
| - | 212 | * |
|
| - | 213 | * @return 0 - phone disconnected, -1 - the phone was already disconnected |
|
| - | 214 | */ |
|
| - | 215 | int ipc_phone_hangup(phone_t *phone) |
|
| - | 216 | { |
|
| - | 217 | answerbox_t *box; |
|
| - | 218 | call_t *call; |
|
| - | 219 | ||
| - | 220 | spinlock_lock(&phone->lock); |
|
| - | 221 | box = phone->callee; |
|
| - | 222 | if (!box) { |
|
| - | 223 | spinlock_unlock(&phone->lock); |
|
| - | 224 | return -1; |
|
| - | 225 | } |
|
| 210 | 226 | ||
| 211 | spinlock_lock(&box->lock); |
227 | spinlock_lock(&box->lock); |
| 212 | list_append(&call->list, &box->calls); |
228 | list_remove(&phone->list); |
| - | 229 | phone->callee = NULL; |
|
| 213 | spinlock_unlock(&box->lock); |
230 | spinlock_unlock(&box->lock); |
| - | 231 | ||
| - | 232 | call = ipc_call_alloc(); |
|
| - | 233 | IPC_SET_METHOD(call->data, IPC_M_PHONE_HUNGUP); |
|
| - | 234 | call->flags |= IPC_CALL_DISCARD_ANSWER; |
|
| 214 | waitq_wakeup(&box->wq, 0); |
235 | _ipc_call(phone, box, call); |
| - | 236 | ||
| - | 237 | phone->busy = 0; |
|
| 215 | 238 | ||
| 216 | spinlock_unlock(&phone->lock); |
239 | spinlock_unlock(&phone->lock); |
| - | 240 | ||
| - | 241 | return 0; |
|
| 217 | } |
242 | } |
| 218 | 243 | ||
| 219 | /** Forwards call from one answerbox to a new one |
244 | /** Forwards call from one answerbox to a new one |
| 220 | * |
245 | * |
| 221 | * @param request Request to be forwarded |
246 | * @param request Request to be forwarded |
| Line 223... | Line 248... | ||
| 223 | * @param oldbox Old answerbox |
248 | * @param oldbox Old answerbox |
| 224 | */ |
249 | */ |
| 225 | void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) |
250 | void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox) |
| 226 | { |
251 | { |
| 227 | spinlock_lock(&oldbox->lock); |
252 | spinlock_lock(&oldbox->lock); |
| - | 253 | atomic_dec(&call->data.phone->active_calls); |
|
| 228 | list_remove(&call->list); |
254 | list_remove(&call->list); |
| 229 | spinlock_unlock(&oldbox->lock); |
255 | spinlock_unlock(&oldbox->lock); |
| 230 | 256 | ||
| 231 | ipc_call(newphone, call); |
257 | ipc_call(newphone, call); |
| 232 | } |
258 | } |
| Line 239... | Line 265... | ||
| 239 | */ |
265 | */ |
| 240 | call_t * ipc_wait_for_call(answerbox_t *box, int flags) |
266 | call_t * ipc_wait_for_call(answerbox_t *box, int flags) |
| 241 | { |
267 | { |
| 242 | call_t *request; |
268 | call_t *request; |
| 243 | 269 | ||
| - | 270 | restart: |
|
| - | 271 | if (flags & IPC_WAIT_NONBLOCKING) { |
|
| - | 272 | if (waitq_sleep_timeout(&box->wq,0,1) == ESYNCH_WOULD_BLOCK) |
|
| - | 273 | return NULL; |
|
| - | 274 | } else |
|
| - | 275 | waitq_sleep(&box->wq); |
|
| - | 276 | ||
| 244 | spinlock_lock(&box->lock); |
277 | spinlock_lock(&box->lock); |
| 245 | while (1) { |
- | |
| 246 | if (!list_empty(&box->answers)) { |
278 | if (!list_empty(&box->answers)) { |
| 247 | /* Handle asynchronous answers */ |
279 | /* Handle asynchronous answers */ |
| 248 | request = list_get_instance(box->answers.next, call_t, list); |
280 | request = list_get_instance(box->answers.next, call_t, list); |
| 249 | list_remove(&request->list); |
281 | 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); |
|
| 250 | } else if (!list_empty(&box->calls)) { |
285 | } else if (!list_empty(&box->calls)) { |
| 251 | /* Handle requests */ |
286 | /* Handle requests */ |
| 252 | request = list_get_instance(box->calls.next, call_t, list); |
287 | request = list_get_instance(box->calls.next, call_t, list); |
| 253 | list_remove(&request->list); |
288 | list_remove(&request->list); |
| 254 | /* Append request to dispatch queue */ |
289 | /* Append request to dispatch queue */ |
| 255 | list_append(&request->list, &box->dispatched_calls); |
290 | list_append(&request->list, &box->dispatched_calls); |
| 256 | request->flags |= IPC_CALL_DISPATCHED; |
291 | request->flags |= IPC_CALL_DISPATCHED; |
| 257 | } else { |
292 | } else { |
| 258 | if (!(flags & IPC_WAIT_NONBLOCKING)) { |
293 | printf("WARNING: Spurious IPC wakeup.\n"); |
| 259 | /* Wait for event to appear */ |
- | |
| 260 | spinlock_unlock(&box->lock); |
294 | spinlock_unlock(&box->lock); |
| 261 | waitq_sleep(&box->wq); |
- | |
| 262 | spinlock_lock(&box->lock); |
- | |
| 263 | continue; |
- | |
| 264 | } |
- | |
| 265 | request = NULL; |
- | |
| 266 | } |
- | |
| 267 | break; |
295 | goto restart; |
| 268 | } |
296 | } |
| 269 | spinlock_unlock(&box->lock); |
297 | spinlock_unlock(&box->lock); |
| 270 | return request; |
298 | return request; |
| 271 | } |
299 | } |
| 272 | 300 | ||