Changeset 6769005 in mainline for uspace/lib/c/generic/async/server.c
- Timestamp:
- 2018-10-31T06:03:38Z (5 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 53ee7a0
- Parents:
- 94ab1fe
- git-author:
- Jakub Jermar <jakub@…> (2018-10-28 12:42:35)
- git-committer:
- Jakub Jermar <jakub@…> (2018-10-31 06:03:38)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/c/generic/async/server.c
r94ab1fe r6769005 144 144 task_id_t in_task_id; 145 145 146 /** Incoming phone hash. */147 sysarg_t in_phone_hash;148 149 146 /** Link to the client tracking structure. */ 150 147 client_t *client; … … 234 231 static sysarg_t notification_avail = 0; 235 232 236 static FIBRIL_RMUTEX_INITIALIZE(conn_mutex);237 static hash_table_t conn_hash_table;238 239 233 static size_t client_key_hash(void *key) 240 234 { … … 261 255 .key_hash = client_key_hash, 262 256 .key_equal = client_key_equal, 263 .equal = NULL,264 .remove_callback = NULL265 };266 267 typedef struct {268 task_id_t task_id;269 sysarg_t phone_hash;270 } conn_key_t;271 272 /** Compute hash into the connection hash table273 *274 * The hash is based on the source task ID and the source phone hash. The task275 * ID is included in the hash because a phone hash alone might not be unique276 * while we still track connections for killed tasks due to kernel's recycling277 * of phone structures.278 *279 * @param key Pointer to the connection key structure.280 *281 * @return Index into the connection hash table.282 *283 */284 static size_t conn_key_hash(void *key)285 {286 conn_key_t *ck = (conn_key_t *) key;287 288 size_t hash = 0;289 hash = hash_combine(hash, LOWER32(ck->task_id));290 hash = hash_combine(hash, UPPER32(ck->task_id));291 hash = hash_combine(hash, ck->phone_hash);292 return hash;293 }294 295 static size_t conn_hash(const ht_link_t *item)296 {297 connection_t *conn = hash_table_get_inst(item, connection_t, link);298 return conn_key_hash(&(conn_key_t){299 .task_id = conn->in_task_id,300 .phone_hash = conn->in_phone_hash301 });302 }303 304 static bool conn_key_equal(void *key, const ht_link_t *item)305 {306 conn_key_t *ck = (conn_key_t *) key;307 connection_t *conn = hash_table_get_inst(item, connection_t, link);308 return ((ck->task_id == conn->in_task_id) &&309 (ck->phone_hash == conn->in_phone_hash));310 }311 312 /** Operations for the connection hash table. */313 static hash_table_ops_t conn_hash_table_ops = {314 .hash = conn_hash,315 .key_hash = conn_key_hash,316 .key_equal = conn_key_equal,317 257 .equal = NULL, 318 258 .remove_callback = NULL … … 386 326 fibril_connection = (connection_t *) arg; 387 327 328 mpsc_t *c = fibril_connection->msg_channel; 329 388 330 /* 389 331 * Add our reference for the current connection in the client task … … 395 337 if (!client) { 396 338 ipc_answer_0(fibril_connection->call.cap_handle, ENOMEM); 397 return 0;339 goto out; 398 340 } 399 341 … … 411 353 async_client_put(client); 412 354 413 fibril_rmutex_lock(&conn_mutex);414 415 /*416 * Remove myself from the connection hash table.417 */418 hash_table_remove(&conn_hash_table, &(conn_key_t){419 .task_id = fibril_connection->in_task_id,420 .phone_hash = fibril_connection->in_phone_hash421 });422 423 355 /* 424 356 * Close the channel, if it isn't closed already. 425 357 */ 426 mpsc_t *c = fibril_connection->msg_channel;427 358 mpsc_close(c); 428 429 fibril_rmutex_unlock(&conn_mutex);430 359 431 360 /* … … 439 368 * Clean up memory. 440 369 */ 370 out: 441 371 mpsc_destroy(c); 442 372 free(fibril_connection); … … 444 374 } 445 375 376 /** Return label usable during replies to IPC_M_CONNECT_ME_TO. */ 377 sysarg_t async_get_label(void) 378 { 379 return (sysarg_t) fibril_connection; 380 } 381 446 382 /** Create a new fibril for a new connection. 447 383 * … … 450 386 * particular fibrils. 451 387 * 452 * @param in_task_id Identification of the incoming connection. 453 * @param in_phone_hash Identification of the incoming connection. 454 * @param call Call data of the opening call. If call is NULL, 455 * the connection was opened by accepting the 456 * IPC_M_CONNECT_TO_ME call and this function is 457 * called directly by the server. 458 * @param handler Connection handler. 459 * @param data Client argument to pass to the connection handler. 388 * @param conn Pointer to the connection structure. Will be used as the 389 * label of the connected phone and request_label of incoming 390 * calls routed through that phone. 391 * @param in_task_id Identification of the incoming connection. 392 * @param call Call data of the opening call. If call is NULL, the 393 * connection was opened by accepting the 394 * IPC_M_CONNECT_TO_ME call and this function is called 395 * directly by the server. 396 * @param handler Connection handler. 397 * @param data Client argument to pass to the connection handler. 460 398 * 461 399 * @return New fibril id or NULL on failure. 462 400 * 463 401 */ 464 static fid_t async_new_connection( task_id_t in_task_id, sysarg_t in_phone_hash,402 static fid_t async_new_connection(connection_t *conn, task_id_t in_task_id, 465 403 ipc_call_t *call, async_port_handler_t handler, void *data) 466 404 { 467 connection_t *conn = malloc(sizeof(*conn));468 if (!conn) {469 if (call)470 ipc_answer_0(call->cap_handle, ENOMEM);471 472 return (fid_t) NULL;473 }474 475 405 conn->in_task_id = in_task_id; 476 conn->in_phone_hash = in_phone_hash;477 406 conn->msg_channel = mpsc_create(sizeof(ipc_call_t)); 478 407 conn->handler = handler; 479 408 conn->data = data; 409 410 if (!conn->msg_channel) 411 goto error; 480 412 481 413 if (call) … … 487 419 conn->fid = fibril_create(connection_fibril, conn); 488 420 489 if (conn->fid == 0) { 421 if (conn->fid == 0) 422 goto error; 423 424 fibril_start(conn->fid); 425 426 return conn->fid; 427 428 error: 429 if (conn->msg_channel) 490 430 mpsc_destroy(conn->msg_channel); 491 free(conn); 492 493 if (call) 494 ipc_answer_0(call->cap_handle, ENOMEM); 495 496 return (fid_t) NULL; 497 } 498 499 /* Add connection to the connection hash table */ 500 501 fibril_rmutex_lock(&conn_mutex); 502 hash_table_insert(&conn_hash_table, &conn->link); 503 fibril_rmutex_unlock(&conn_mutex); 504 505 fibril_start(conn->fid); 506 507 return conn->fid; 431 free(conn); 432 433 if (call) 434 ipc_answer_0(call->cap_handle, ENOMEM); 435 436 return (fid_t) NULL; 508 437 } 509 438 … … 532 461 return ENOENT; 533 462 463 connection_t *conn = calloc(1, sizeof(*conn)); 464 if (!conn) 465 return ENOMEM; 466 534 467 ipc_call_t answer; 535 aid_t req = async_send_ 3(exch, IPC_M_CONNECT_TO_ME, iface, arg1, arg2,536 &answer);468 aid_t req = async_send_5(exch, IPC_M_CONNECT_TO_ME, iface, arg1, arg2, 469 0, (sysarg_t) conn, &answer); 537 470 538 471 errno_t rc; 539 472 async_wait_for(req, &rc); 540 if (rc != EOK) 473 if (rc != EOK) { 474 free(conn); 541 475 return rc; 476 } 542 477 543 478 rc = async_create_port_internal(iface, handler, data, port_id); 544 if (rc != EOK) 479 if (rc != EOK) { 480 free(conn); 545 481 return rc; 546 547 sysarg_t phone_hash = IPC_GET_ARG5(answer); 548 fid_t fid = async_new_connection( answer.in_task_id, phone_hash,549 NULL, handler,data);482 } 483 484 fid_t fid = async_new_connection(conn, answer.task_id, NULL, handler, 485 data); 550 486 if (fid == (fid_t) NULL) 551 487 return ENOMEM; … … 601 537 assert(call); 602 538 603 fibril_rmutex_lock(&conn_mutex); 604 605 ht_link_t *link = hash_table_find(&conn_hash_table, &(conn_key_t){ 606 .task_id = call->in_task_id, 607 .phone_hash = call->in_phone_hash 608 }); 609 if (!link) { 610 fibril_rmutex_unlock(&conn_mutex); 539 connection_t *conn = (connection_t *) call->request_label; 540 541 if (!conn) 611 542 return ENOENT; 612 } 613 614 connection_t *conn = hash_table_get_inst(link, connection_t, link); 543 544 assert(conn->msg_channel); 615 545 616 546 errno_t rc = mpsc_send(conn->msg_channel, call); … … 625 555 } 626 556 627 fibril_rmutex_unlock(&conn_mutex);628 557 return rc; 629 558 } … … 1009 938 /* New connection */ 1010 939 if (IPC_GET_IMETHOD(*call) == IPC_M_CONNECT_ME_TO) { 940 connection_t *conn = calloc(1, sizeof(*conn)); 941 if (!conn) { 942 ipc_answer_0(call->cap_handle, ENOMEM); 943 return; 944 } 945 1011 946 iface_t iface = (iface_t) IPC_GET_ARG1(*call); 1012 sysarg_t in_phone_hash = IPC_GET_ARG5(*call);1013 947 1014 948 // TODO: Currently ignores all ports but the first one. … … 1017 951 async_get_port_handler(iface, 0, &data); 1018 952 1019 async_new_connection(call->in_task_id, in_phone_hash, call, 1020 handler, data); 953 async_new_connection(conn, call->task_id, call, handler, data); 1021 954 return; 1022 955 } 1023 956 1024 /* Try to route the call through the connection hash table*/957 /* Route the call according to its request label */ 1025 958 errno_t rc = route_call(call); 1026 959 if (rc == EOK) … … 1083 1016 abort(); 1084 1017 1085 if (!hash_table_create(&conn_hash_table, 0, 0, &conn_hash_table_ops))1086 abort();1087 1088 1018 if (!hash_table_create(¬ification_hash_table, 0, 0, 1089 1019 ¬ification_hash_table_ops)) … … 1171 1101 return ENOENT; 1172 1102 1173 ipc_call_t answer; 1174 aid_t req = async_send_3(exch, IPC_M_CONNECT_TO_ME, iface, arg2, arg3, 1175 &answer); 1176 1177 errno_t rc; 1178 async_wait_for(req, &rc); 1179 if (rc != EOK) 1180 return (errno_t) rc; 1181 1182 return EOK; 1103 sysarg_t label = 0; 1104 errno_t rc = async_req_5_0(exch, IPC_M_CONNECT_TO_ME, iface, arg2, arg3, 1105 0, label); 1106 1107 return rc; 1183 1108 } 1184 1109
Note:
See TracChangeset
for help on using the changeset viewer.