1.1 --- a/libipc/lib/src/server.c Mon Mar 20 14:52:03 2023 +0100
1.2 +++ b/libipc/lib/src/server.c Mon Mar 20 18:08:44 2023 +0100
1.3 @@ -1,7 +1,8 @@
1.4 /*
1.5 * Server binding/registration.
1.6 *
1.7 - * Copyright (C) 2018, 2019, 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
1.8 + * Copyright (C) 2018, 2019, 2020, 2021, 2022,
1.9 + * 2023 Paul Boddie <paul@boddie.org.uk>
1.10 *
1.11 * This program is free software; you can redistribute it and/or
1.12 * modify it under the terms of the GNU General Public License as
1.13 @@ -37,15 +38,16 @@
1.14 /* Associate an IRQ with the IPC gate in the main thread to handle gate deletion
1.15 notifications. */
1.16
1.17 -long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq)
1.18 +long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_umword_t id)
1.19 {
1.20 - return ipc_server_apply_irq_for_thread(cap, irq, l4re_env()->main_thread);
1.21 + return ipc_server_apply_irq_for_thread(cap, irq, id, l4re_env()->main_thread);
1.22 }
1.23
1.24 /* Associate an IRQ with the IPC gate in the given thread to handle gate deletion
1.25 notifications. */
1.26
1.27 -long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_cap_idx_t thread)
1.28 +long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq,
1.29 + l4_umword_t id, l4_cap_idx_t thread)
1.30 {
1.31 /* Create an IRQ for the gate. */
1.32
1.33 @@ -57,7 +59,7 @@
1.34 /* Bind the IRQ to the thread, presenting the label if it provides the
1.35 incoming message. */
1.36
1.37 - err = ipc_bind_irq(*irq, (l4_umword_t) *irq, thread);
1.38 + err = ipc_bind_irq(*irq, id, thread);
1.39
1.40 if (err)
1.41 {
1.42 @@ -162,7 +164,7 @@
1.43
1.44 if (name != NULL)
1.45 {
1.46 - err = ipc_server_bind(name, (l4_umword_t) &config, &config.server);
1.47 + err = ipc_server_bind(name, (l4_umword_t) &config.endpoint, &config.server);
1.48 if (err)
1.49 return err;
1.50 }
1.51 @@ -211,17 +213,20 @@
1.52
1.53
1.54
1.55 -/* A server main loop handling endpoint deletion for an IPC gate dedicated to
1.56 - a particular object within its own thread. */
1.57 +/* A server main loop handling endpoint deletion for IPC gates. The supplied
1.58 + configuration object indicates common properties for components exposed via
1.59 + IPC gates whose messages are handled by this loop. Where an IRQ is received
1.60 + for the principal IPC gate, as indicated by the supplied configuration, the
1.61 + loop terminates. */
1.62
1.63 long ipc_server_managed_loop(ipc_server_config_type *config)
1.64 {
1.65 ipc_message_t msg;
1.66 - l4_umword_t label, irq_label;
1.67 + l4_umword_t label;
1.68
1.69 /* Permit other endpoints by dynamically interpreting the label. */
1.70
1.71 - ipc_server_config_type *config_from_label;
1.72 + ipc_server_endpoint_type *endpoint;
1.73
1.74 /* Declare the extent to which capabilities are expected in messages. */
1.75
1.76 @@ -245,19 +250,36 @@
1.77 if (l4_ipc_error(msg.tag, l4_utcb()))
1.78 continue;
1.79
1.80 - /* Message involves the IPC gate itself. */
1.81 + /* Obtain the endpoint and determine whether it represents an IRQ or a
1.82 + component. */
1.83
1.84 - irq_label = (l4_umword_t) config->irq;
1.85 + endpoint = (ipc_server_endpoint_type *) label;
1.86 +
1.87 + /* Message involves the IRQ. */
1.88
1.89 - if (!config->notifications || (config->notifications && (label != irq_label)))
1.90 + if (l4_is_valid_cap(endpoint->irq))
1.91 {
1.92 - config_from_label = (ipc_server_config_type *) label;
1.93 - config_from_label->handler(&msg, config_from_label->handler_obj);
1.94 + /* Finalise the associated configuration. */
1.95 +
1.96 + if (endpoint->config->finaliser != NULL)
1.97 + endpoint->config->finaliser(config);
1.98 +
1.99 + /* Terminate if the principal configuration is involved. */
1.100 +
1.101 + if (endpoint->config == config)
1.102 + break;
1.103 }
1.104
1.105 - /* Message involves the IRQ or a termination condition occurred. */
1.106 + /* Message involves a component. */
1.107
1.108 - else if ((config->notifications && (label == irq_label)) || msg.terminating)
1.109 + else
1.110 + {
1.111 + endpoint->config->handler(&msg, endpoint->config->handler_obj);
1.112 + }
1.113 +
1.114 + /* A termination condition occurred. */
1.115 +
1.116 + if (msg.terminating)
1.117 break;
1.118 }
1.119
1.120 @@ -274,12 +296,7 @@
1.121 {
1.122 ipc_server_config_type *config = (ipc_server_config_type *) data;
1.123
1.124 - long err = ipc_server_managed_loop(config);
1.125 -
1.126 - if (config->finaliser != NULL)
1.127 - config->finaliser(config);
1.128 -
1.129 - return (void *) err;
1.130 + return (void *) ipc_server_managed_loop(config);
1.131 }
1.132
1.133 /* Wait for an incoming message via an IPC gate dedicated to a particular
1.134 @@ -310,10 +327,10 @@
1.135 config->server = L4_INVALID_CAP;
1.136 }
1.137
1.138 - if (l4_is_valid_cap(config->irq))
1.139 + if (l4_is_valid_cap(config->irq_endpoint.irq))
1.140 {
1.141 - ipc_cap_free_um(config->irq);
1.142 - config->irq = L4_INVALID_CAP;
1.143 + ipc_cap_free_um(config->irq_endpoint.irq);
1.144 + config->irq_endpoint.irq = L4_INVALID_CAP;
1.145 }
1.146 }
1.147
1.148 @@ -355,10 +372,16 @@
1.149 config->thread = l4re_env()->main_thread;
1.150 config->server = L4_INVALID_CAP;
1.151
1.152 - /* No notifications and with IRQ to be potentially allocated. */
1.153 + /* Define the general endpoint with invalid IRQ capability. */
1.154 +
1.155 + config->endpoint.irq = L4_INVALID_CAP;
1.156 + config->endpoint.config = config;
1.157
1.158 - config->notifications = 0;
1.159 - config->irq = L4_INVALID_CAP;
1.160 + /* Disable notifications, with the IRQ and associated configuration
1.161 + potentially defined later. */
1.162 +
1.163 + config->irq_endpoint.irq = L4_INVALID_CAP;
1.164 + config->irq_endpoint.config = NULL;
1.165 }
1.166
1.167 /* Initialise but do not start a server using the given configuration. */
1.168 @@ -371,7 +394,7 @@
1.169
1.170 if (l4_is_invalid_cap(config->server))
1.171 {
1.172 - err = ipc_server_new_for_thread(&config->server, config, config->thread);
1.173 + err = ipc_server_new_for_thread(&config->server, &config->endpoint, config->thread);
1.174
1.175 if (err)
1.176 return err;
1.177 @@ -379,16 +402,17 @@
1.178
1.179 /* Allocate an IRQ for notifications if requested. */
1.180
1.181 - if (config->notifications)
1.182 + if (config->irq_endpoint.config != NULL)
1.183 {
1.184 - err = ipc_server_apply_irq_for_thread(config->server, &config->irq, config->thread);
1.185 + err = ipc_server_apply_irq_for_thread(config->server, &config->irq_endpoint.irq,
1.186 + (l4_umword_t) &config->irq_endpoint, config->thread);
1.187
1.188 if (err)
1.189 return err;
1.190
1.191 /* Unmask the interrupt. */
1.192
1.193 - ipc_init_irq(config->irq);
1.194 + ipc_init_irq(config->irq_endpoint.irq);
1.195 }
1.196
1.197 return L4_EOK;