Subversion Repositories HelenOS-historic

Rev

Rev 1072 | Rev 1086 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1072 Rev 1084
Line 47... Line 47...
47
/* Open channel that is assigned automatically to new tasks */
47
/* Open channel that is assigned automatically to new tasks */
48
answerbox_t *ipc_phone_0 = NULL;
48
answerbox_t *ipc_phone_0 = NULL;
49
 
49
 
50
static slab_cache_t *ipc_call_slab;
50
static slab_cache_t *ipc_call_slab;
51
 
51
 
-
 
52
/* Initialize new call */
-
 
53
static void _ipc_call_init(call_t *call)
-
 
54
{
-
 
55
    memsetb((__address)call, sizeof(*call), 0);
-
 
56
    call->callerbox = &TASK->answerbox;
-
 
57
    call->sender = TASK;
-
 
58
}
-
 
59
 
52
/** Allocate & initialize call structure
60
/** Allocate & initialize call structure
53
 *
61
 *
54
 * The call is initialized, so that the reply will be directed
62
 * The call is initialized, so that the reply will be directed
55
 * to TASK->answerbox
63
 * to TASK->answerbox
56
 */
64
 */
57
call_t * ipc_call_alloc(void)
65
call_t * ipc_call_alloc(void)
58
{
66
{
59
    call_t *call;
67
    call_t *call;
60
 
68
 
61
    call = slab_alloc(ipc_call_slab, 0);
69
    call = slab_alloc(ipc_call_slab, 0);
62
    memsetb((__address)call, sizeof(*call), 0);
-
 
63
    call->callerbox = &TASK->answerbox;
-
 
64
    call->sender = TASK;
70
    _ipc_call_init(call);
65
 
71
 
66
    return call;
72
    return call;
67
}
73
}
68
 
74
 
69
/** Initialize allocated call */
75
/** Initialize allocated call */
70
void ipc_call_init(call_t *call)
76
void ipc_call_static_init(call_t *call)
71
{
77
{
72
    call->callerbox = &TASK->answerbox;
78
    _ipc_call_init(call);
73
    call->flags = IPC_CALL_STATIC_ALLOC;
79
    call->flags |= IPC_CALL_STATIC_ALLOC;
74
    call->sender = TASK;
-
 
75
}
80
}
76
 
81
 
77
/** Deallocate call stracuture */
82
/** Deallocate call stracuture */
78
void ipc_call_free(call_t *call)
83
void ipc_call_free(call_t *call)
79
{
84
{
Line 94... Line 99...
94
}
99
}
95
 
100
 
96
/** Connect phone to answerbox */
101
/** Connect phone to answerbox */
97
void ipc_phone_connect(phone_t *phone, answerbox_t *box)
102
void ipc_phone_connect(phone_t *phone, answerbox_t *box)
98
{
103
{
-
 
104
    spinlock_lock(&phone->lock);
-
 
105
 
99
    ASSERT(!phone->callee);
106
    ASSERT(!phone->callee);
100
    phone->busy = 1;
107
    phone->busy = 1;
101
    phone->callee = box;
108
    phone->callee = box;
102
 
109
 
103
    spinlock_lock(&box->lock);
110
    spinlock_lock(&box->lock);
104
    list_append(&phone->list, &box->connected_phones);
111
    list_append(&phone->list, &box->connected_phones);
105
    spinlock_unlock(&box->lock);
112
    spinlock_unlock(&box->lock);
-
 
113
 
-
 
114
    spinlock_unlock(&phone->lock);
106
}
115
}
107
 
116
 
108
/** Initialize phone structure and connect phone to naswerbox
117
/** Initialize phone structure and connect phone to naswerbox
109
 */
118
 */
110
void ipc_phone_init(phone_t *phone)
119
void ipc_phone_init(phone_t *phone)
Line 112... Line 121...
112
    spinlock_initialize(&phone->lock, "phone_lock");
121
    spinlock_initialize(&phone->lock, "phone_lock");
113
    phone->callee = NULL;
122
    phone->callee = NULL;
114
    phone->busy = 0;
123
    phone->busy = 0;
115
}
124
}
116
 
125
 
117
/** Disconnect phone from answerbox */
126
/** Disconnect phone from answerbox
-
 
127
 *
-
 
128
 * It is allowed to call disconnect on already disconnected phone\
-
 
129
 */
118
void ipc_phone_destroy(phone_t *phone)
130
void ipc_phone_destroy(phone_t *phone)
119
{
131
{
120
    answerbox_t *box = phone->callee;
132
    answerbox_t *box = phone->callee;
121
   
133
   
122
    ASSERT(box);
134
    ASSERT(box);
123
 
135
 
-
 
136
    spinlock_lock(&phone->lock);
124
    spinlock_lock(&box->lock);
137
    spinlock_lock(&box->lock);
-
 
138
 
-
 
139
    if (phone->callee) {
125
    list_remove(&phone->list);
140
        list_remove(&phone->list);
-
 
141
        phone->callee = NULL;
-
 
142
    }
-
 
143
 
126
    spinlock_unlock(&box->lock);
144
    spinlock_unlock(&box->lock);
-
 
145
    spinlock_unlock(&phone->lock);
127
}
146
}
128
 
147
 
129
/** Helper function to facilitate synchronous calls */
148
/** Helper function to facilitate synchronous calls */
130
void ipc_call_sync(phone_t *phone, call_t *request)
149
void ipc_call_sync(phone_t *phone, call_t *request)
131
{
150
{
Line 138... Line 157...
138
 
157
 
139
    ipc_call(phone, request);
158
    ipc_call(phone, request);
140
    ipc_wait_for_call(&sync_box, 0);
159
    ipc_wait_for_call(&sync_box, 0);
141
}
160
}
142
 
161
 
-
 
162
/** Answer message that was not dispatched and is not entered in
-
 
163
 * any queue
-
 
164
 */
-
 
165
static void _ipc_answer_free_call(call_t *call)
-
 
166
{
-
 
167
    answerbox_t *callerbox = call->callerbox;
-
 
168
 
-
 
169
    call->flags &= ~IPC_CALL_DISPATCHED;
-
 
170
    call->flags |= IPC_CALL_ANSWERED;
-
 
171
 
-
 
172
    spinlock_lock(&callerbox->lock);
-
 
173
    list_append(&call->list, &callerbox->answers);
-
 
174
    spinlock_unlock(&callerbox->lock);
-
 
175
    waitq_wakeup(&callerbox->wq, 0);
-
 
176
}
-
 
177
 
-
 
178
/** Answer message, that is in callee queue
-
 
179
 *
-
 
180
 * @param box Answerbox that is answering the message
-
 
181
 * @param call Modified request that is being sent back
-
 
182
 */
-
 
183
void ipc_answer(answerbox_t *box, call_t *call)
-
 
184
{
-
 
185
    /* Remove from active box */
-
 
186
    spinlock_lock(&box->lock);
-
 
187
    list_remove(&call->list);
-
 
188
    spinlock_unlock(&box->lock);
-
 
189
    /* Send back answer */
-
 
190
    _ipc_answer_free_call(call);
-
 
191
}
-
 
192
 
143
/** Send a asynchronous request using phone to answerbox
193
/** Send a asynchronous request using phone to answerbox
144
 *
194
 *
145
 * @param phone Phone connected to answerbox
195
 * @param phone Phone connected to answerbox
146
 * @param request Request to be sent
196
 * @param request Request to be sent
147
 */
197
 */
148
void ipc_call(phone_t *phone, call_t *call)
198
void ipc_call(phone_t *phone, call_t *call)
149
{
199
{
150
    answerbox_t *box = phone->callee;
200
    answerbox_t *box;
151
 
201
 
-
 
202
    spinlock_lock(&phone->lock);
-
 
203
    box = phone->callee;
152
    ASSERT(box);
204
    if (!box) {
-
 
205
        /* Trying to send over disconnected phone */
-
 
206
        IPC_SET_RETVAL(call->data, ENOENT);
-
 
207
        _ipc_answer_free_call(call);
-
 
208
        return;
-
 
209
    }
153
 
210
 
154
    spinlock_lock(&box->lock);
211
    spinlock_lock(&box->lock);
155
    list_append(&call->list, &box->calls);
212
    list_append(&call->list, &box->calls);
156
    spinlock_unlock(&box->lock);
213
    spinlock_unlock(&box->lock);
157
    waitq_wakeup(&box->wq, 0);
214
    waitq_wakeup(&box->wq, 0);
-
 
215
   
-
 
216
    spinlock_unlock(&phone->lock);
158
}
217
}
159
 
218
 
160
/** Forwards call from one answerbox to a new one
219
/** Forwards call from one answerbox to a new one
161
 *
220
 *
162
 * @param request Request to be forwarded
221
 * @param request Request to be forwarded
163
 * @param newbox Target answerbox
222
 * @param newbox Target answerbox
164
 * @param oldbox Old answerbox
223
 * @param oldbox Old answerbox
165
 */
224
 */
166
void ipc_forward(call_t *call, answerbox_t *newbox, answerbox_t *oldbox)
225
void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox)
167
{
226
{
168
    spinlock_lock(&oldbox->lock);
227
    spinlock_lock(&oldbox->lock);
169
    list_remove(&call->list);
228
    list_remove(&call->list);
170
    spinlock_unlock(&oldbox->lock);
229
    spinlock_unlock(&oldbox->lock);
171
 
230
 
172
    spinlock_lock(&newbox->lock);
-
 
173
    list_append(&call->list, &newbox->calls);
-
 
174
    spinlock_lock(&newbox->lock);
-
 
175
    waitq_wakeup(&newbox->wq, 0);
231
    ipc_call(newphone, call);
176
}
232
}
177
 
233
 
178
/** Answer message back to phone
-
 
179
 *
-
 
180
 * @param box Answerbox that is answering the message
-
 
181
 * @param request Modified request that is being sent back
-
 
182
 */
-
 
183
void ipc_answer(answerbox_t *box, call_t *request)
-
 
184
{
-
 
185
    answerbox_t *callerbox = request->callerbox;
-
 
186
 
-
 
187
    request->flags &= ~IPC_CALL_DISPATCHED;
-
 
188
    request->flags |= IPC_CALL_ANSWERED;
-
 
189
 
-
 
190
    spinlock_lock(&box->lock);
-
 
191
    list_remove(&request->list);
-
 
192
    spinlock_unlock(&box->lock);
-
 
193
 
-
 
194
    spinlock_lock(&callerbox->lock);
-
 
195
    list_append(&request->list, &callerbox->answers);
-
 
196
    spinlock_unlock(&callerbox->lock);
-
 
197
    waitq_wakeup(&callerbox->wq, 0);
-
 
198
}
-
 
199
 
234
 
200
/** Wait for phone call
235
/** Wait for phone call
201
 *
236
 *
202
 * @return Recived message address
237
 * @return Recived message address
203
 * - to distinguish between call and answer, look at call->flags
238
 * - to distinguish between call and answer, look at call->flags