Subversion Repositories HelenOS

Rev

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
}