00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00100 #include <async_sess.h>
00101 #include <fibril_synch.h>
00102 #include <adt/list.h>
00103 #include <adt/hash_table.h>
00104 #include <malloc.h>
00105 #include <errno.h>
00106 #include <assert.h>
00107 #include <async.h>
00108 #include "private/async_sess.h"
00109
00111 typedef struct {
00112 link_t sess_link;
00113 link_t global_link;
00114 int data_phone;
00115 } conn_node_t;
00116
00121 static fibril_mutex_t async_sess_mutex;
00122
00126 static LIST_INITIALIZE(inactive_conn_head);
00127
00131 static LIST_INITIALIZE(session_list_head);
00132
00136 static FIBRIL_CONDVAR_INITIALIZE(avail_phone_cv);
00137
00143 void __async_sess_init(void)
00144 {
00145 fibril_mutex_initialize(&async_sess_mutex);
00146 list_initialize(&inactive_conn_head);
00147 list_initialize(&session_list_head);
00148 }
00149
00165 void async_session_create(async_sess_t *sess, int phone, sysarg_t arg1)
00166 {
00167 sess->sess_phone = phone;
00168 sess->connect_arg1 = arg1;
00169 list_initialize(&sess->conn_head);
00170
00171
00172 fibril_mutex_lock(&async_sess_mutex);
00173 list_append(&sess->sess_link, &session_list_head);
00174 fibril_mutex_unlock(&async_sess_mutex);
00175 }
00176
00184 void async_session_destroy(async_sess_t *sess)
00185 {
00186 conn_node_t *conn;
00187
00188
00189 fibril_mutex_lock(&async_sess_mutex);
00190 list_remove(&sess->sess_link);
00191 fibril_mutex_unlock(&async_sess_mutex);
00192
00193
00194 sess->sess_phone = -1;
00195
00196
00197 while (!list_empty(&sess->conn_head)) {
00198 conn = list_get_instance(sess->conn_head.next, conn_node_t,
00199 sess_link);
00200
00201 list_remove(&conn->sess_link);
00202 list_remove(&conn->global_link);
00203
00204 async_hangup(conn->data_phone);
00205 free(conn);
00206 }
00207
00208 fibril_condvar_broadcast(&avail_phone_cv);
00209 }
00210
00211 static void conn_node_initialize(conn_node_t *conn)
00212 {
00213 link_initialize(&conn->sess_link);
00214 link_initialize(&conn->global_link);
00215 conn->data_phone = -1;
00216 }
00217
00224 int async_exchange_begin(async_sess_t *sess)
00225 {
00226 conn_node_t *conn;
00227 int data_phone;
00228
00229 fibril_mutex_lock(&async_sess_mutex);
00230
00231 if (!list_empty(&sess->conn_head)) {
00232
00233
00234
00235 conn = list_get_instance(sess->conn_head.next, conn_node_t,
00236 sess_link);
00237 list_remove(&conn->sess_link);
00238 list_remove(&conn->global_link);
00239
00240 data_phone = conn->data_phone;
00241 free(conn);
00242 } else {
00243
00244
00245
00246
00247 retry:
00248 data_phone = async_connect_me_to(sess->sess_phone,
00249 sess->connect_arg1, 0, 0);
00250 if (data_phone >= 0) {
00251
00252 } else if (!list_empty(&inactive_conn_head)) {
00253
00254
00255
00256
00257
00258 conn = list_get_instance(inactive_conn_head.next,
00259 conn_node_t, global_link);
00260 list_remove(&conn->global_link);
00261 list_remove(&conn->sess_link);
00262 data_phone = conn->data_phone;
00263 free(conn);
00264 async_hangup(data_phone);
00265 goto retry;
00266 } else {
00267
00268
00269
00270 fibril_condvar_wait(&avail_phone_cv, &async_sess_mutex);
00271 goto retry;
00272 }
00273 }
00274
00275 fibril_mutex_unlock(&async_sess_mutex);
00276 return data_phone;
00277 }
00278
00284 void async_exchange_end(async_sess_t *sess, int data_phone)
00285 {
00286 conn_node_t *conn;
00287
00288 fibril_mutex_lock(&async_sess_mutex);
00289 fibril_condvar_signal(&avail_phone_cv);
00290 conn = (conn_node_t *) malloc(sizeof(conn_node_t));
00291 if (!conn) {
00292
00293
00294
00295
00296 async_hangup(data_phone);
00297 fibril_mutex_unlock(&async_sess_mutex);
00298 return;
00299 }
00300
00301 conn_node_initialize(conn);
00302 conn->data_phone = data_phone;
00303 list_append(&conn->sess_link, &sess->conn_head);
00304 list_append(&conn->global_link, &inactive_conn_head);
00305 fibril_mutex_unlock(&async_sess_mutex);
00306 }
00307