1.1 --- a/libfsserver/lib/generic/resource_server.cc Mon Mar 20 14:52:03 2023 +0100
1.2 +++ b/libfsserver/lib/generic/resource_server.cc Mon Mar 20 18:08:44 2023 +0100
1.3 @@ -35,7 +35,7 @@
1.4
1.5 long ResourceServer::bind(const char *name)
1.6 {
1.7 - return ipc_server_bind(name, (l4_umword_t) _config, &_config->server);
1.8 + return ipc_server_bind(name, (l4_umword_t) &_config->endpoint, &_config->server);
1.9 }
1.10
1.11 /* Start in the same thread indicating whether deletion notifications and
1.12 @@ -55,7 +55,7 @@
1.13 if (finalisation)
1.14 {
1.15 _config->finaliser = resource_same_thread_finaliser;
1.16 - _config->notifications = 1;
1.17 + _config->irq_endpoint.config = _config;
1.18 }
1.19
1.20 return resource_start_config(_config, _resource);
1.21 @@ -118,7 +118,7 @@
1.22 config->finaliser = resource_thread_finaliser;
1.23 config->config_thread = new_thread;
1.24 config->thread = thread;
1.25 - config->notifications = 1;
1.26 + config->irq_endpoint.config = config;
1.27 }
1.28
1.29 /* Activate a resource and start a server for it. */
2.1 --- a/libipc/include/ipc/server.h Mon Mar 20 14:52:03 2023 +0100
2.2 +++ b/libipc/include/ipc/server.h Mon Mar 20 18:08:44 2023 +0100
2.3 @@ -43,16 +43,37 @@
2.4 #define ipc_server_add_config(CONFIG, TYPE, POINTER, THREAD) \
2.5 _ipc_server_add_config(CONFIG, &config_##TYPE, (TYPE *) POINTER, THREAD)
2.6
2.7 +
2.8 +
2.9 /* A handler function type. */
2.10
2.11 typedef void (*ipc_server_handler_type)(ipc_message_t *, void *);
2.12
2.13 +
2.14 +
2.15 /* A finaliser function type. */
2.16
2.17 struct ipc_server_config_type;
2.18
2.19 typedef void (*ipc_server_finaliser_type)(struct ipc_server_config_type *);
2.20
2.21 +
2.22 +
2.23 +/* A generic type for server endpoints. */
2.24 +
2.25 +typedef struct ipc_server_endpoint_type
2.26 +{
2.27 + struct ipc_server_config_type *config;
2.28 +
2.29 + /* Receive deletion notifications via an IRQ for the associated
2.30 + configuration. This is only defined for IRQ endpoints. */
2.31 +
2.32 + l4_cap_idx_t irq;
2.33 +
2.34 +} ipc_server_endpoint_type;
2.35 +
2.36 +
2.37 +
2.38 /* A server configuration type. */
2.39
2.40 typedef struct ipc_server_config_type
2.41 @@ -77,18 +98,18 @@
2.42
2.43 int config_thread;
2.44
2.45 - /* Thread and IPC capabilities. */
2.46 + /* Thread and IPC gate capabilities. */
2.47
2.48 - l4_cap_idx_t thread;
2.49 - l4_cap_idx_t server;
2.50 + l4_cap_idx_t thread, server;
2.51
2.52 - /* Receive deletion notifications via an IRQ. */
2.53 + /* The generic endpoint object and IRQ endpoint. */
2.54
2.55 - int notifications;
2.56 - l4_cap_idx_t irq;
2.57 + ipc_server_endpoint_type endpoint, irq_endpoint;
2.58
2.59 } ipc_server_config_type;
2.60
2.61 +
2.62 +
2.63 /* Server configuration defaults. */
2.64
2.65 typedef struct ipc_server_default_config_type
2.66 @@ -102,11 +123,12 @@
2.67
2.68 /* Associate a notification IRQ with an IPC gate in the main thread. */
2.69
2.70 -long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq);
2.71 +long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_umword_t id);
2.72
2.73 /* Associate a notification IRQ with an IPC gate in the given thread. */
2.74
2.75 -long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_cap_idx_t thread);
2.76 +long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq,
2.77 + l4_umword_t id, l4_cap_idx_t thread);
2.78
2.79 /* Bind the main thread to a named IPC gate capability. */
2.80
3.1 --- a/libipc/lib/src/server.c Mon Mar 20 14:52:03 2023 +0100
3.2 +++ b/libipc/lib/src/server.c Mon Mar 20 18:08:44 2023 +0100
3.3 @@ -1,7 +1,8 @@
3.4 /*
3.5 * Server binding/registration.
3.6 *
3.7 - * Copyright (C) 2018, 2019, 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
3.8 + * Copyright (C) 2018, 2019, 2020, 2021, 2022,
3.9 + * 2023 Paul Boddie <paul@boddie.org.uk>
3.10 *
3.11 * This program is free software; you can redistribute it and/or
3.12 * modify it under the terms of the GNU General Public License as
3.13 @@ -37,15 +38,16 @@
3.14 /* Associate an IRQ with the IPC gate in the main thread to handle gate deletion
3.15 notifications. */
3.16
3.17 -long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq)
3.18 +long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_umword_t id)
3.19 {
3.20 - return ipc_server_apply_irq_for_thread(cap, irq, l4re_env()->main_thread);
3.21 + return ipc_server_apply_irq_for_thread(cap, irq, id, l4re_env()->main_thread);
3.22 }
3.23
3.24 /* Associate an IRQ with the IPC gate in the given thread to handle gate deletion
3.25 notifications. */
3.26
3.27 -long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_cap_idx_t thread)
3.28 +long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq,
3.29 + l4_umword_t id, l4_cap_idx_t thread)
3.30 {
3.31 /* Create an IRQ for the gate. */
3.32
3.33 @@ -57,7 +59,7 @@
3.34 /* Bind the IRQ to the thread, presenting the label if it provides the
3.35 incoming message. */
3.36
3.37 - err = ipc_bind_irq(*irq, (l4_umword_t) *irq, thread);
3.38 + err = ipc_bind_irq(*irq, id, thread);
3.39
3.40 if (err)
3.41 {
3.42 @@ -162,7 +164,7 @@
3.43
3.44 if (name != NULL)
3.45 {
3.46 - err = ipc_server_bind(name, (l4_umword_t) &config, &config.server);
3.47 + err = ipc_server_bind(name, (l4_umword_t) &config.endpoint, &config.server);
3.48 if (err)
3.49 return err;
3.50 }
3.51 @@ -211,17 +213,20 @@
3.52
3.53
3.54
3.55 -/* A server main loop handling endpoint deletion for an IPC gate dedicated to
3.56 - a particular object within its own thread. */
3.57 +/* A server main loop handling endpoint deletion for IPC gates. The supplied
3.58 + configuration object indicates common properties for components exposed via
3.59 + IPC gates whose messages are handled by this loop. Where an IRQ is received
3.60 + for the principal IPC gate, as indicated by the supplied configuration, the
3.61 + loop terminates. */
3.62
3.63 long ipc_server_managed_loop(ipc_server_config_type *config)
3.64 {
3.65 ipc_message_t msg;
3.66 - l4_umword_t label, irq_label;
3.67 + l4_umword_t label;
3.68
3.69 /* Permit other endpoints by dynamically interpreting the label. */
3.70
3.71 - ipc_server_config_type *config_from_label;
3.72 + ipc_server_endpoint_type *endpoint;
3.73
3.74 /* Declare the extent to which capabilities are expected in messages. */
3.75
3.76 @@ -245,19 +250,36 @@
3.77 if (l4_ipc_error(msg.tag, l4_utcb()))
3.78 continue;
3.79
3.80 - /* Message involves the IPC gate itself. */
3.81 + /* Obtain the endpoint and determine whether it represents an IRQ or a
3.82 + component. */
3.83
3.84 - irq_label = (l4_umword_t) config->irq;
3.85 + endpoint = (ipc_server_endpoint_type *) label;
3.86 +
3.87 + /* Message involves the IRQ. */
3.88
3.89 - if (!config->notifications || (config->notifications && (label != irq_label)))
3.90 + if (l4_is_valid_cap(endpoint->irq))
3.91 {
3.92 - config_from_label = (ipc_server_config_type *) label;
3.93 - config_from_label->handler(&msg, config_from_label->handler_obj);
3.94 + /* Finalise the associated configuration. */
3.95 +
3.96 + if (endpoint->config->finaliser != NULL)
3.97 + endpoint->config->finaliser(config);
3.98 +
3.99 + /* Terminate if the principal configuration is involved. */
3.100 +
3.101 + if (endpoint->config == config)
3.102 + break;
3.103 }
3.104
3.105 - /* Message involves the IRQ or a termination condition occurred. */
3.106 + /* Message involves a component. */
3.107
3.108 - else if ((config->notifications && (label == irq_label)) || msg.terminating)
3.109 + else
3.110 + {
3.111 + endpoint->config->handler(&msg, endpoint->config->handler_obj);
3.112 + }
3.113 +
3.114 + /* A termination condition occurred. */
3.115 +
3.116 + if (msg.terminating)
3.117 break;
3.118 }
3.119
3.120 @@ -274,12 +296,7 @@
3.121 {
3.122 ipc_server_config_type *config = (ipc_server_config_type *) data;
3.123
3.124 - long err = ipc_server_managed_loop(config);
3.125 -
3.126 - if (config->finaliser != NULL)
3.127 - config->finaliser(config);
3.128 -
3.129 - return (void *) err;
3.130 + return (void *) ipc_server_managed_loop(config);
3.131 }
3.132
3.133 /* Wait for an incoming message via an IPC gate dedicated to a particular
3.134 @@ -310,10 +327,10 @@
3.135 config->server = L4_INVALID_CAP;
3.136 }
3.137
3.138 - if (l4_is_valid_cap(config->irq))
3.139 + if (l4_is_valid_cap(config->irq_endpoint.irq))
3.140 {
3.141 - ipc_cap_free_um(config->irq);
3.142 - config->irq = L4_INVALID_CAP;
3.143 + ipc_cap_free_um(config->irq_endpoint.irq);
3.144 + config->irq_endpoint.irq = L4_INVALID_CAP;
3.145 }
3.146 }
3.147
3.148 @@ -355,10 +372,16 @@
3.149 config->thread = l4re_env()->main_thread;
3.150 config->server = L4_INVALID_CAP;
3.151
3.152 - /* No notifications and with IRQ to be potentially allocated. */
3.153 + /* Define the general endpoint with invalid IRQ capability. */
3.154 +
3.155 + config->endpoint.irq = L4_INVALID_CAP;
3.156 + config->endpoint.config = config;
3.157
3.158 - config->notifications = 0;
3.159 - config->irq = L4_INVALID_CAP;
3.160 + /* Disable notifications, with the IRQ and associated configuration
3.161 + potentially defined later. */
3.162 +
3.163 + config->irq_endpoint.irq = L4_INVALID_CAP;
3.164 + config->irq_endpoint.config = NULL;
3.165 }
3.166
3.167 /* Initialise but do not start a server using the given configuration. */
3.168 @@ -371,7 +394,7 @@
3.169
3.170 if (l4_is_invalid_cap(config->server))
3.171 {
3.172 - err = ipc_server_new_for_thread(&config->server, config, config->thread);
3.173 + err = ipc_server_new_for_thread(&config->server, &config->endpoint, config->thread);
3.174
3.175 if (err)
3.176 return err;
3.177 @@ -379,16 +402,17 @@
3.178
3.179 /* Allocate an IRQ for notifications if requested. */
3.180
3.181 - if (config->notifications)
3.182 + if (config->irq_endpoint.config != NULL)
3.183 {
3.184 - err = ipc_server_apply_irq_for_thread(config->server, &config->irq, config->thread);
3.185 + err = ipc_server_apply_irq_for_thread(config->server, &config->irq_endpoint.irq,
3.186 + (l4_umword_t) &config->irq_endpoint, config->thread);
3.187
3.188 if (err)
3.189 return err;
3.190
3.191 /* Unmask the interrupt. */
3.192
3.193 - ipc_init_irq(config->irq);
3.194 + ipc_init_irq(config->irq_endpoint.irq);
3.195 }
3.196
3.197 return L4_EOK;