The open source OpenXR runtime
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipc: Add a stable ID for clients

Co-authored-by: Lubosz Sarnecki <lubosz.sarnecki@collabora.com>

authored by

Jakob Bornecrantz
Lubosz Sarnecki
and committed by
Lubosz Sarnecki
7dae8d1d 1920a9f0

+192 -66
+21 -2
src/xrt/ipc/server/ipc_server.h
··· 342 342 343 343 volatile uint32_t current_slot_index; 344 344 345 + //! Generator for IDs. 346 + uint32_t id_generator; 347 + 345 348 struct 346 349 { 347 350 int active_client_index; ··· 378 381 #endif 379 382 380 383 /*! 384 + * Get the current state of a client. 385 + * 386 + * @ingroup ipc_server 387 + */ 388 + xrt_result_t 389 + ipc_server_get_client_app_state(struct ipc_server *s, uint32_t client_id, struct ipc_app_state *out_ias); 390 + 391 + /*! 381 392 * Set the new active client. 382 393 * 383 394 * @ingroup ipc_server 384 395 */ 385 - void 386 - ipc_server_set_active_client(struct ipc_server *s, int client_id); 396 + xrt_result_t 397 + ipc_server_set_active_client(struct ipc_server *s, uint32_t client_id); 398 + 399 + /*! 400 + * Toggle the io for this client. 401 + * 402 + * @ingroup ipc_server 403 + */ 404 + xrt_result_t 405 + ipc_server_toggle_io_client(struct ipc_server *s, uint32_t client_id); 387 406 388 407 /*! 389 408 * Called by client threads to set a session to active.
+32 -38
src/xrt/ipc/server/ipc_server_handler.c
··· 938 938 } 939 939 940 940 xrt_result_t 941 - ipc_handle_system_get_client_info(volatile struct ipc_client_state *_ics, 942 - uint32_t id, 943 - struct ipc_app_state *out_client_desc) 941 + ipc_handle_system_get_clients(volatile struct ipc_client_state *_ics, struct ipc_client_list *list) 944 942 { 945 - if (id >= IPC_MAX_CLIENTS) { 946 - return XRT_ERROR_IPC_FAILURE; 947 - } 948 - volatile struct ipc_client_state *ics = &_ics->server->threads[id].ics; 943 + struct ipc_server *s = _ics->server; 944 + 945 + // Look client list. 946 + os_mutex_lock(&s->global_state.lock); 947 + 948 + uint32_t count = 0; 949 + for (uint32_t i = 0; i < IPC_MAX_CLIENTS; i++) { 950 + 951 + volatile struct ipc_client_state *ics = &s->threads[i].ics; 952 + 953 + // Is this thread running? 954 + if (ics->server_thread_index < 0) { 955 + continue; 956 + } 949 957 950 - if (!xrt_ipc_handle_is_valid(ics->imc.ipc_handle)) { 951 - return XRT_ERROR_IPC_FAILURE; 958 + list->ids[count++] = ics->client_state.id; 952 959 } 953 960 954 - *out_client_desc = ics->client_state; 955 - out_client_desc->io_active = ics->io_active; 961 + list->id_count = count; 956 962 957 - //@todo: track this data in the ipc_client_state struct 958 - out_client_desc->primary_application = false; 959 - if (ics->server->global_state.active_client_index == (int)id) { 960 - out_client_desc->primary_application = true; 961 - } 963 + // Unlock now. 964 + os_mutex_unlock(&s->global_state.lock); 962 965 963 966 return XRT_SUCCESS; 964 967 } 965 968 966 969 xrt_result_t 967 - ipc_handle_system_get_clients(volatile struct ipc_client_state *_ics, struct ipc_client_list *list) 970 + ipc_handle_system_get_client_info(volatile struct ipc_client_state *_ics, 971 + uint32_t client_id, 972 + struct ipc_app_state *out_ias) 968 973 { 969 - for (uint32_t i = 0; i < IPC_MAX_CLIENTS; i++) { 970 - list->ids[i] = _ics->server->threads[i].ics.server_thread_index; 971 - } 972 - return XRT_SUCCESS; 974 + struct ipc_server *s = _ics->server; 975 + 976 + return ipc_server_get_client_app_state(s, client_id, out_ias); 973 977 } 974 978 975 979 xrt_result_t 976 - ipc_handle_system_set_primary_client(volatile struct ipc_client_state *ics, uint32_t client_id) 980 + ipc_handle_system_set_primary_client(volatile struct ipc_client_state *_ics, uint32_t client_id) 977 981 { 978 - IPC_INFO(ics->server, "System setting active client to %d.", client_id); 982 + struct ipc_server *s = _ics->server; 979 983 980 - ipc_server_set_active_client(ics->server, client_id); 984 + IPC_INFO(s, "System setting active client to %d.", client_id); 981 985 982 - return XRT_SUCCESS; 986 + return ipc_server_set_active_client(s, client_id); 983 987 } 984 988 985 989 xrt_result_t ··· 993 997 xrt_result_t 994 998 ipc_handle_system_toggle_io_client(volatile struct ipc_client_state *_ics, uint32_t client_id) 995 999 { 996 - volatile struct ipc_client_state *ics = NULL; 1000 + struct ipc_server *s = _ics->server; 997 1001 998 - if (client_id >= IPC_MAX_CLIENTS) { 999 - return XRT_ERROR_IPC_FAILURE; 1000 - } 1002 + IPC_INFO(s, "System toggling io for client %u.", client_id); 1001 1003 1002 - ics = &_ics->server->threads[client_id].ics; 1003 - 1004 - if (!xrt_ipc_handle_is_valid(ics->imc.ipc_handle)) { 1005 - return XRT_ERROR_IPC_FAILURE; 1006 - } 1007 - 1008 - ics->io_active = !ics->io_active; 1009 - 1010 - return XRT_SUCCESS; 1004 + return ipc_server_toggle_io_client(s, client_id); 1011 1005 } 1012 1006 1013 1007 xrt_result_t
+1 -1
src/xrt/ipc/server/ipc_server_per_client_thread.c
··· 70 70 { 71 71 U_TRACE_SET_THREAD_NAME("IPC Client"); 72 72 73 - IPC_INFO(ics->server, "Client connected"); 73 + IPC_INFO(ics->server, "Client %u connected", ics->client_state.id); 74 74 75 75 // Claim the client fd. 76 76 int epoll_fd = setup_epoll(ics);
+125 -8
src/xrt/ipc/server/ipc_server_process.c
··· 40 40 #include <stdio.h> 41 41 #include <string.h> 42 42 #include <assert.h> 43 + #include <limits.h> 43 44 44 45 /* 45 46 * ··· 431 432 } 432 433 433 434 it->state = IPC_THREAD_STARTING; 435 + 436 + // Allocate a new ID, avoid zero. 437 + //! @todo validate ID. 438 + uint32_t id = ++vs->id_generator; 439 + 440 + // Reset everything. 441 + U_ZERO((struct ipc_client_state *)ics); 442 + 443 + // Set state. 444 + ics->client_state.id = id; 434 445 ics->imc.ipc_handle = ipc_handle; 435 446 ics->server = vs; 436 447 ics->server_thread_index = cs_index; 437 448 ics->io_active = true; 449 + 438 450 os_thread_start(&it->thread, ipc_server_client_thread, (void *)ics); 439 451 440 452 // Unlock when we are done. ··· 695 707 s->global_state.last_active_client_index = s->global_state.active_client_index; 696 708 } 697 709 698 - static void 699 - set_active_client_locked(struct ipc_server *s, int client_id) 710 + static volatile struct ipc_client_state * 711 + find_client_locked(struct ipc_server *s, uint32_t client_id) 712 + { 713 + // Check for invalid IDs. 714 + if (client_id == 0 || client_id > INT_MAX) { 715 + IPC_WARN(s, "Invalid ID '%u', failing operation.", client_id); 716 + return NULL; 717 + } 718 + 719 + for (uint32_t i = 0; i < IPC_MAX_CLIENTS; i++) { 720 + volatile struct ipc_client_state *ics = &s->threads[i].ics; 721 + 722 + // Is this the client we are looking for? 723 + if (ics->client_state.id != client_id) { 724 + continue; 725 + } 726 + 727 + // Just in case of state data. 728 + if (!xrt_ipc_handle_is_valid(ics->imc.ipc_handle)) { 729 + IPC_WARN(s, "Encountered invalid state while searching for client with ID '%d'", client_id); 730 + return NULL; 731 + } 732 + 733 + return ics; 734 + } 735 + 736 + IPC_WARN(s, "No client with ID '%u', failing operation.", client_id); 737 + 738 + return NULL; 739 + } 740 + 741 + static xrt_result_t 742 + get_client_app_state_locked(struct ipc_server *s, uint32_t client_id, struct ipc_app_state *out_ias) 743 + { 744 + volatile struct ipc_client_state *ics = find_client_locked(s, client_id); 745 + if (ics == NULL) { 746 + return XRT_ERROR_IPC_FAILURE; 747 + } 748 + 749 + struct ipc_app_state ias = ics->client_state; 750 + ias.io_active = ics->io_active; 751 + 752 + // @todo: track this data in the ipc_client_state struct 753 + ias.primary_application = false; 754 + 755 + // The active client is decided by index, so get that from the ics. 756 + int index = ics->server_thread_index; 757 + 758 + if (s->global_state.active_client_index == index) { 759 + ias.primary_application = true; 760 + } 761 + 762 + *out_ias = ias; 763 + 764 + return XRT_SUCCESS; 765 + } 766 + 767 + static xrt_result_t 768 + set_active_client_locked(struct ipc_server *s, uint32_t client_id) 769 + { 770 + volatile struct ipc_client_state *ics = find_client_locked(s, client_id); 771 + if (ics == NULL) { 772 + return XRT_ERROR_IPC_FAILURE; 773 + } 774 + 775 + // The active client is decided by index, so get that from the ics. 776 + int index = ics->server_thread_index; 777 + 778 + if (index != s->global_state.active_client_index) { 779 + s->global_state.active_client_index = index; 780 + } 781 + 782 + return XRT_SUCCESS; 783 + } 784 + 785 + static xrt_result_t 786 + toggle_io_client_locked(struct ipc_server *s, uint32_t client_id) 700 787 { 701 - if (client_id != s->global_state.active_client_index) { 702 - s->global_state.active_client_index = client_id; 788 + volatile struct ipc_client_state *ics = find_client_locked(s, client_id); 789 + if (ics == NULL) { 790 + return XRT_ERROR_IPC_FAILURE; 703 791 } 792 + 793 + ics->io_active = !ics->io_active; 794 + 795 + return XRT_SUCCESS; 704 796 } 705 797 798 + 706 799 /* 707 800 * 708 801 * Exported functions. 709 802 * 710 803 */ 711 804 712 - void 713 - ipc_server_set_active_client(struct ipc_server *s, int client_id) 805 + 806 + xrt_result_t 807 + ipc_server_get_client_app_state(struct ipc_server *s, uint32_t client_id, struct ipc_app_state *out_ias) 808 + { 809 + os_mutex_lock(&s->global_state.lock); 810 + xrt_result_t xret = get_client_app_state_locked(s, client_id, out_ias); 811 + os_mutex_unlock(&s->global_state.lock); 812 + 813 + return xret; 814 + } 815 + 816 + xrt_result_t 817 + ipc_server_set_active_client(struct ipc_server *s, uint32_t client_id) 818 + { 819 + os_mutex_lock(&s->global_state.lock); 820 + xrt_result_t xret = set_active_client_locked(s, client_id); 821 + os_mutex_unlock(&s->global_state.lock); 822 + 823 + return xret; 824 + } 825 + 826 + xrt_result_t 827 + ipc_server_toggle_io_client(struct ipc_server *s, uint32_t client_id) 714 828 { 715 829 os_mutex_lock(&s->global_state.lock); 716 - set_active_client_locked(s, client_id); 830 + xrt_result_t xret = toggle_io_client_locked(s, client_id); 717 831 os_mutex_unlock(&s->global_state.lock); 832 + 833 + return xret; 718 834 } 719 835 720 836 void ··· 742 858 s->global_state.last_active_client_index); 743 859 } else { 744 860 // Update active client 745 - set_active_client_locked(s, ics->server_thread_index); 861 + set_active_client_locked(s, ics->client_state.id); 862 + 746 863 // For new active regular sessions update all clients. 747 864 update_server_state_locked(s); 748 865 }
+5 -1
src/xrt/ipc/shared/ipc_protocol.h
··· 285 285 286 286 struct ipc_client_list 287 287 { 288 - int32_t ids[IPC_MAX_CLIENTS]; 288 + uint32_t ids[IPC_MAX_CLIENTS]; 289 + uint32_t id_count; 289 290 }; 290 291 291 292 /*! ··· 295 296 */ 296 297 struct ipc_app_state 297 298 { 299 + // Stable and unique ID of the client, only unique within this instance. 300 + uint32_t id; 301 + 298 302 bool primary_application; 299 303 bool session_active; 300 304 bool session_visible;
+1 -1
src/xrt/ipc/shared/proto.json
··· 16 16 {"name": "id", "type": "uint32_t"} 17 17 ], 18 18 "out": [ 19 - {"name": "desc", "type": "struct ipc_app_state"} 19 + {"name": "ias", "type": "struct ipc_app_state"} 20 20 ] 21 21 }, 22 22
+7 -15
src/xrt/targets/ctl/main.c
··· 43 43 } 44 44 45 45 P("Clients:\n"); 46 - for (uint32_t i = 0; i < IPC_MAX_CLIENTS; i++) { 47 - if (clients.ids[i] < 0) { 48 - continue; 49 - } 46 + for (uint32_t i = 0; i < clients.id_count; i++) { 47 + uint32_t id = clients.ids[i]; 50 48 51 49 struct ipc_app_state cs; 52 - r = ipc_call_system_get_client_info(ipc_c, i, &cs); 50 + r = ipc_call_system_get_client_info(ipc_c, id, &cs); 53 51 if (r != XRT_SUCCESS) { 54 - PE("Failed to get client info for client %d.\n", i); 52 + PE("Failed to get client info for client %d.\n", id); 55 53 return 1; 56 54 } 57 55 ··· 145 143 switch (c) { 146 144 case 'p': 147 145 s_val = atoi(optarg); 148 - if (s_val >= 0 && s_val < IPC_MAX_CLIENTS) { 149 - op_mode = MODE_SET_PRIMARY; 150 - } 146 + op_mode = MODE_SET_PRIMARY; 151 147 break; 152 148 case 'f': 153 149 s_val = atoi(optarg); 154 - if (s_val >= 0 && s_val < IPC_MAX_CLIENTS) { 155 - op_mode = MODE_SET_FOCUSED; 156 - } 150 + op_mode = MODE_SET_FOCUSED; 157 151 break; 158 152 case 'i': 159 153 s_val = atoi(optarg); 160 - if (s_val >= 0 && s_val < IPC_MAX_CLIENTS) { 161 - op_mode = MODE_TOGGLE_IO; 162 - } 154 + op_mode = MODE_TOGGLE_IO; 163 155 break; 164 156 case '?': 165 157 if (optopt == 's') {