1 /* 2 * Resource server functionality. 3 * 4 * Copyright (C) 2018, 2019, 2020, 2021 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) _resource, &_config->server); 38 } 39 40 /* Start in the same thread with no deletion notifications or finalisation. */ 41 42 long ResourceServer::start() 43 { 44 resource_init_config(_config, _resource); 45 _config->thread = pthread_l4_cap(pthread_self()); 46 return resource_start_config(_config, _resource); 47 } 48 49 /* Start a new thread with deletion notifications and finalisation. */ 50 51 long ResourceServer::start_thread() 52 { 53 pthread_t thread; 54 pthread_attr_t attr; 55 56 pthread_attr_init(&attr); 57 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 58 59 resource_init_config(_config, _resource); 60 pthread_create(&thread, &attr, ipc_server_start_mainloop, _config); 61 resource_set_config_threaded(_config, pthread_l4_cap(thread), 1); 62 63 return resource_start_config(_config, _resource); 64 } 65 66 67 68 /* Initialise a server configuration for a resource. */ 69 70 void resource_init_config(ipc_server_config_type *config, Resource *resource) 71 { 72 config->handler_obj = resource->interface(); 73 config->finaliser_obj = resource; 74 config->expected_items = resource->expected_items(); 75 config->handler = resource->handler(); 76 } 77 78 /* Set a configuration to be threaded. */ 79 80 void resource_set_config_threaded(ipc_server_config_type *config, 81 l4_cap_idx_t thread, int new_thread) 82 { 83 config->finaliser = resource_thread_finaliser; 84 config->new_thread = new_thread; 85 config->thread = thread; 86 config->notifications = 1; 87 } 88 89 /* Activate a resource and start a server for it. */ 90 91 long resource_start_config(ipc_server_config_type *config, Resource *resource) 92 { 93 resource->activate(); 94 long err = ipc_server_start_config(config); 95 96 /* Discard any server resources if starting it failed. */ 97 98 if (err) 99 { 100 ipc_server_finalise_config(config); 101 ipc_server_discard_thread(config); 102 } 103 104 return err; 105 } 106 107 108 109 /* A finaliser for exposed resources. */ 110 111 void resource_thread_finaliser(ipc_server_config_type *config) 112 { 113 Resource *resource = reinterpret_cast<Resource *>(config->finaliser_obj); 114 115 /* Close and delete the resource. */ 116 117 resource->close(); 118 delete resource; 119 120 /* Release the capabilities. */ 121 122 ipc_server_finalise_config(config); 123 delete config; 124 }