1 /* 2 * Resource server functionality. 3 * 4 * Copyright (C) 2018, 2019, 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <l4/sys/types.h> 23 24 #include <pthread-l4.h> 25 #include <pthread.h> 26 27 #include "resource_server.h" 28 29 30 31 /* Convenience server methods. */ 32 33 /* Bind to a named IPC gate capability. */ 34 35 long ResourceServer::bind(const char *name) 36 { 37 return ipc_server_bind(name, (l4_umword_t) _config, &_config->server); 38 } 39 40 /* Start in the same thread indicating whether deletion notifications and 41 finalisation are to be used. */ 42 43 long ResourceServer::start(bool finalisation) 44 { 45 resource_init_config(_config, _resource); 46 _config->thread = pthread_l4_cap(pthread_self()); 47 48 if (finalisation) 49 { 50 _config->finaliser = resource_same_thread_finaliser; 51 _config->notifications = 1; 52 } 53 54 return resource_start_config(_config, _resource); 55 } 56 57 /* Start a new thread with deletion notifications and finalisation. */ 58 59 long ResourceServer::start_thread() 60 { 61 pthread_t thread; 62 pthread_attr_t attr; 63 long err; 64 65 pthread_attr_init(&attr); 66 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 67 68 resource_init_config(_config, _resource); 69 70 err = pthread_create(&thread, &attr, ipc_server_start_mainloop, _config); 71 if (err) 72 return err; 73 74 resource_set_config_threaded(_config, pthread_l4_cap(thread), 1); 75 76 return resource_start_config(_config, _resource); 77 } 78 79 /* A convenience method starting a thread and returning the server capability 80 employed via the given parameter. */ 81 82 long ResourceServer::start_thread(l4_cap_idx_t *server) 83 { 84 long err = start_thread(); 85 86 if (!err) 87 *server = _config->server; 88 89 return err; 90 } 91 92 93 94 /* Initialise a server configuration for a resource. */ 95 96 void resource_init_config(ipc_server_config_type *config, Resource *resource) 97 { 98 ipc_server_default_config_type default_config = resource->config(); 99 100 config->handler_obj = resource->interface(); 101 config->finaliser_obj = resource; 102 config->expected_items = default_config.expected_items; 103 config->handler = default_config.handler; 104 } 105 106 /* Set a configuration to be threaded. */ 107 108 void resource_set_config_threaded(ipc_server_config_type *config, 109 l4_cap_idx_t thread, int new_thread) 110 { 111 config->finaliser = resource_thread_finaliser; 112 config->config_thread = new_thread; 113 config->thread = thread; 114 config->notifications = 1; 115 } 116 117 /* Activate a resource and start a server for it. */ 118 119 long resource_start_config(ipc_server_config_type *config, Resource *resource) 120 { 121 resource->activate(); 122 long err = ipc_server_start_config(config); 123 124 /* Discard any server resources if starting it failed. */ 125 126 if (err) 127 { 128 ipc_server_finalise_config(config); 129 ipc_server_discard_thread(config); 130 } 131 132 return err; 133 } 134 135 136 137 /* A finaliser for exposed resources in the same thread. */ 138 139 void resource_same_thread_finaliser(ipc_server_config_type *config) 140 { 141 Resource *resource = reinterpret_cast<Resource *>(config->finaliser_obj); 142 143 /* Close but do not delete the resource since it is assumed that it is being 144 managed by the thread. */ 145 146 resource->close(); 147 148 /* Release the capabilities. */ 149 150 ipc_server_finalise_config(config); 151 delete config; 152 } 153 154 /* A finaliser for exposed resources in a different thread. */ 155 156 void resource_thread_finaliser(ipc_server_config_type *config) 157 { 158 Resource *resource = reinterpret_cast<Resource *>(config->finaliser_obj); 159 160 /* Close and delete the resource. */ 161 162 resource->close(); 163 delete resource; 164 165 /* Release the capabilities. */ 166 167 ipc_server_finalise_config(config); 168 delete config; 169 } 170 171 // vim: tabstop=2 expandtab shiftwidth=2