Subversion Repositories HelenOS

Rev

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

Rev 2486 Rev 2488
Line 104... Line 104...
104
 
104
 
105
atomic_t async_futex = FUTEX_INITIALIZER;
105
atomic_t async_futex = FUTEX_INITIALIZER;
106
static hash_table_t conn_hash_table;
106
static hash_table_t conn_hash_table;
107
static LIST_INITIALIZE(timeout_list);
107
static LIST_INITIALIZE(timeout_list);
108
 
108
 
-
 
109
/** Structures of this type represent a waiting fibril. */
109
typedef struct {
110
typedef struct {
110
    /** Expiration time for waiting fibril. */
111
    /** Expiration time. */
111
    struct timeval expires;    
112
    struct timeval expires;    
112
    /** If true, this struct is in the timeout list. */
113
    /** If true, this struct is in the timeout list. */
113
    int inlist;
114
    int inlist;
-
 
115
    /** Timeout list link. */
114
    link_t link;
116
    link_t link;
115
 
117
 
116
    /** Fibril waiting for this message. */
118
    /** Fibril waiting for this message. */
117
    fid_t fid;
119
    fid_t fid;
118
    /** If this fibril is currently active. */
120
    /** If true, this fibril is currently active. */
119
    int active;
121
    int active;
120
    /** If true, we timed out. */
122
    /** If true, we have timed out. */
121
    int timedout;
123
    int timedout;
122
} awaiter_t;
124
} awaiter_t;
123
 
125
 
124
typedef struct {
126
typedef struct {
125
    awaiter_t wdata;
127
    awaiter_t wdata;
-
 
128
   
-
 
129
    /** If reply was received. */
-
 
130
    int done;
-
 
131
    /** Pointer to where the answer data is stored. */
-
 
132
    ipc_call_t *dataptr;
126
 
133
 
127
    int done;                   /**< If reply was received */
-
 
128
    ipc_call_t *dataptr;        /**< Pointer where the answer data
-
 
129
                     *   is stored */
-
 
130
    ipcarg_t retval;
134
    ipcarg_t retval;
131
} amsg_t;
135
} amsg_t;
132
 
136
 
133
typedef struct {
137
typedef struct {
134
    link_t link;
138
    link_t link;
Line 137... Line 141...
137
} msg_t;
141
} msg_t;
138
 
142
 
139
typedef struct {
143
typedef struct {
140
    awaiter_t wdata;
144
    awaiter_t wdata;
141
 
145
 
142
    link_t link;            /**< Hash table link. */
146
    /** Hash table link. */
-
 
147
    link_t link;
-
 
148
 
143
    ipcarg_t in_phone_hash;     /**< Incoming phone hash. */
149
    /** Incoming phone hash. */
-
 
150
    ipcarg_t in_phone_hash;    
-
 
151
 
144
    link_t msg_queue;       /**< Messages that should be delivered
152
    /** Messages that should be delivered to this fibril. */
145
                     *   to this fibril. */
153
    link_t msg_queue;      
-
 
154
                     
146
    /* Structures for connection opening packet */
155
    /** Identification of the opening call. */
147
    ipc_callid_t callid;
156
    ipc_callid_t callid;
-
 
157
    /** Call data of the opening call. */
148
    ipc_call_t call;
158
    ipc_call_t call;
-
 
159
 
149
    ipc_callid_t close_callid;  /* Identification of closing packet. */
160
    /** Identification of the closing call. */
-
 
161
    ipc_callid_t close_callid;
-
 
162
 
-
 
163
    /** Fibril function that will be used to handle the connection. */
150
    void (*cfibril)(ipc_callid_t, ipc_call_t *);
164
    void (*cfibril)(ipc_callid_t, ipc_call_t *);
151
} connection_t;
165
} connection_t;
152
 
166
 
153
/** Identifier of the incoming connection handled by the current fibril. */
167
/** Identifier of the incoming connection handled by the current fibril. */
154
__thread connection_t *FIBRIL_connection;
168
__thread connection_t *FIBRIL_connection;
-
 
169
 
155
/** If true, it is forbidden to use async_req functions and
170
/** If true, it is forbidden to use async_req functions and all preemption is
156
 *  all preemption is disabled */
171
 * disabled. */
157
__thread int in_interrupt_handler;
172
__thread int in_interrupt_handler;
158
 
173
 
159
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
174
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call);
160
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
175
static void default_interrupt_received(ipc_callid_t callid, ipc_call_t *call);
161
static async_client_conn_t client_connection = default_client_connection;
176
static async_client_conn_t client_connection = default_client_connection;
162
static async_client_conn_t interrupt_received = default_interrupt_received;
177
static async_client_conn_t interrupt_received = default_interrupt_received;
163
 
178
 
164
/* Hash table functions */
-
 
165
#define CONN_HASH_TABLE_CHAINS  32
179
#define CONN_HASH_TABLE_CHAINS  32
166
 
180
 
-
 
181
/** Compute hash into the connection hash table based on the source phone hash.
-
 
182
 *
-
 
183
 * @param key       Pointer to source phone hash.
-
 
184
 *
-
 
185
 * @return      Index into the connection hash table.
-
 
186
 */
167
static hash_index_t conn_hash(unsigned long *key)
187
static hash_index_t conn_hash(unsigned long *key)
168
{
188
{
169
    assert(key);
189
    assert(key);
170
    return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS;
190
    return ((*key) >> 4) % CONN_HASH_TABLE_CHAINS;
171
}
191
}
172
 
192
 
-
 
193
/** Compare hash table item with a key.
-
 
194
 *
-
 
195
 * @param key       Array containing the source phone hash as the only item.
-
 
196
 * @param keys      Expected 1 but ignored.
-
 
197
 * @param item      Connection hash table item.
-
 
198
 *
-
 
199
 * @return      True on match, false otherwise.
-
 
200
 */
173
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
201
static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item)
174
{
202
{
175
    connection_t *hs;
203
    connection_t *hs;
176
 
204
 
177
    hs = hash_table_get_instance(item, connection_t, link);
205
    hs = hash_table_get_instance(item, connection_t, link);
178
   
206
   
179
    return key[0] == hs->in_phone_hash;
207
    return key[0] == hs->in_phone_hash;
180
}
208
}
181
 
209
 
-
 
210
/** Connection hash table removal callback function.
-
 
211
 *
-
 
212
 * This function is called whenever a connection is removed from the connection
-
 
213
 * hash table.
-
 
214
 *
-
 
215
 * @param item      Connection hash table item being removed.
-
 
216
 */
182
static void conn_remove(link_t *item)
217
static void conn_remove(link_t *item)
183
{
218
{
184
    free(hash_table_get_instance(item, connection_t, link));
219
    free(hash_table_get_instance(item, connection_t, link));
185
}
220
}
186
 
221
 
187
 
222
 
188
/** Operations for NS hash table. */
223
/** Operations for the connection hash table. */
189
static hash_table_operations_t conn_hash_table_ops = {
224
static hash_table_operations_t conn_hash_table_ops = {
190
    .hash = conn_hash,
225
    .hash = conn_hash,
191
    .compare = conn_compare,
226
    .compare = conn_compare,
192
    .remove_callback = conn_remove
227
    .remove_callback = conn_remove
193
};
228
};
194
 
229
 
195
/** Insert sort timeout msg into timeouts list
230
/** Sort in current fibril's timeout request.
196
 *
231
 *
-
 
232
 * @param wd        Wait data of the current fibril.
197
 */
233
 */
198
static void insert_timeout(awaiter_t *wd)
234
static void insert_timeout(awaiter_t *wd)
199
{
235
{
200
    link_t *tmp;
236
    link_t *tmp;
201
    awaiter_t *cur;
237
    awaiter_t *cur;
Line 211... Line 247...
211
        tmp = tmp->next;
247
        tmp = tmp->next;
212
    }
248
    }
213
    list_append(&wd->link, tmp);
249
    list_append(&wd->link, tmp);
214
}
250
}
215
 
251
 
216
/** Try to route a call to an appropriate connection fibril
252
/** Try to route a call to an appropriate connection fibril.
217
 *
253
 *
218
 */
254
 */
219
static int route_call(ipc_callid_t callid, ipc_call_t *call)
255
static int route_call(ipc_callid_t callid, ipc_call_t *call)
220
{
256
{
221
    connection_t *conn;
257
    connection_t *conn;
Line 255... Line 291...
255
    futex_up(&async_futex);
291
    futex_up(&async_futex);
256
 
292
 
257
    return 1;
293
    return 1;
258
}
294
}
259
 
295
 
260
/** Return new incoming message for the current (fibril-local) connection */
296
/** Return new incoming message for the current (fibril-local) connection.
-
 
297
 *
-
 
298
 * @param call      Storage where the incoming call data will be stored.
-
 
299
 * @param usecs     Timeout in microseconds. Zero denotes no timeout.
-
 
300
 *
-
 
301
 * @return      If no timeout was specified, then a hash of the
-
 
302
 *          incoming call is returned. If a timeout is specified,
-
 
303
 *          then a hash of the incoming call is returned unless
-
 
304
 *          the timeout expires prior to receiving a message. In
-
 
305
 *          that case zero is returned.
-
 
306
 */
261
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
307
ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs)
262
{
308
{
263
    msg_t *msg;
309
    msg_t *msg;
264
    ipc_callid_t callid;
310
    ipc_callid_t callid;
265
    connection_t *conn;
311
    connection_t *conn;
Line 278... Line 324...
278
        gettimeofday(&conn->wdata.expires, NULL);
324
        gettimeofday(&conn->wdata.expires, NULL);
279
        tv_add(&conn->wdata.expires, usecs);
325
        tv_add(&conn->wdata.expires, usecs);
280
    } else {
326
    } else {
281
        conn->wdata.inlist = 0;
327
        conn->wdata.inlist = 0;
282
    }
328
    }
283
    /* If nothing in queue, wait until something appears */
329
    /* If nothing in queue, wait until something arrives */
284
    while (list_empty(&conn->msg_queue)) {
330
    while (list_empty(&conn->msg_queue)) {
285
        if (usecs)
331
        if (usecs)
286
            insert_timeout(&conn->wdata);
332
            insert_timeout(&conn->wdata);
287
 
333
 
288
        conn->wdata.active = 0;
334
        conn->wdata.active = 0;
289
        fibril_schedule_next_adv(FIBRIL_TO_MANAGER);
335
        fibril_schedule_next_adv(FIBRIL_TO_MANAGER);
-
 
336
        /*
290
        /* Futex is up after getting back from async_manager
337
         * Futex is up after getting back from async_manager get it
291
         * get it again */
338
         * again.
-
 
339
        */
292
        futex_down(&async_futex);
340
        futex_down(&async_futex);
293
        if (usecs && conn->wdata.timedout &&
341
        if (usecs && conn->wdata.timedout &&
294
            list_empty(&conn->msg_queue)) {
342
            list_empty(&conn->msg_queue)) {
295
            /* If we timed out-> exit */
343
            /* If we timed out -> exit */
296
            futex_up(&async_futex);
344
            futex_up(&async_futex);
297
            return 0;
345
            return 0;
298
        }
346
        }
299
    }
347
    }
300
   
348
   
Line 308... Line 356...
308
    return callid;
356
    return callid;
309
}
357
}
310
 
358
 
311
/** Fibril function that gets created on new connection
359
/** Fibril function that gets created on new connection
312
 *
360
 *
313
 * This function is defined as a weak symbol - to be redefined in
361
 * This function is defined as a weak symbol - to be redefined in user code.
314
 * user code.
-
 
315
 */
362
 */
316
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
363
static void default_client_connection(ipc_callid_t callid, ipc_call_t *call)
317
{
364
{
318
    ipc_answer_fast(callid, ENOENT, 0, 0);
365
    ipc_answer_fast(callid, ENOENT, 0, 0);
319
}
366
}