# HG changeset patch # User Paul Boddie # Date 1679332124 -3600 # Node ID a82f362d9f14388f0ea488234a89820235fdd307 # Parent 89e3e3e0864bbaf278381137d7f66023e93e640b Changed IPC message handling to interpret gate labels as generic endpoint addresses, with endpoint structures representing components and notification IRQs. diff -r 89e3e3e0864b -r a82f362d9f14 libfsserver/lib/generic/resource_server.cc --- a/libfsserver/lib/generic/resource_server.cc Mon Mar 20 14:52:03 2023 +0100 +++ b/libfsserver/lib/generic/resource_server.cc Mon Mar 20 18:08:44 2023 +0100 @@ -35,7 +35,7 @@ long ResourceServer::bind(const char *name) { - return ipc_server_bind(name, (l4_umword_t) _config, &_config->server); + return ipc_server_bind(name, (l4_umword_t) &_config->endpoint, &_config->server); } /* Start in the same thread indicating whether deletion notifications and @@ -55,7 +55,7 @@ if (finalisation) { _config->finaliser = resource_same_thread_finaliser; - _config->notifications = 1; + _config->irq_endpoint.config = _config; } return resource_start_config(_config, _resource); @@ -118,7 +118,7 @@ config->finaliser = resource_thread_finaliser; config->config_thread = new_thread; config->thread = thread; - config->notifications = 1; + config->irq_endpoint.config = config; } /* Activate a resource and start a server for it. */ diff -r 89e3e3e0864b -r a82f362d9f14 libipc/include/ipc/server.h --- a/libipc/include/ipc/server.h Mon Mar 20 14:52:03 2023 +0100 +++ b/libipc/include/ipc/server.h Mon Mar 20 18:08:44 2023 +0100 @@ -43,16 +43,37 @@ #define ipc_server_add_config(CONFIG, TYPE, POINTER, THREAD) \ _ipc_server_add_config(CONFIG, &config_##TYPE, (TYPE *) POINTER, THREAD) + + /* A handler function type. */ typedef void (*ipc_server_handler_type)(ipc_message_t *, void *); + + /* A finaliser function type. */ struct ipc_server_config_type; typedef void (*ipc_server_finaliser_type)(struct ipc_server_config_type *); + + +/* A generic type for server endpoints. */ + +typedef struct ipc_server_endpoint_type +{ + struct ipc_server_config_type *config; + + /* Receive deletion notifications via an IRQ for the associated + configuration. This is only defined for IRQ endpoints. */ + + l4_cap_idx_t irq; + +} ipc_server_endpoint_type; + + + /* A server configuration type. */ typedef struct ipc_server_config_type @@ -77,18 +98,18 @@ int config_thread; - /* Thread and IPC capabilities. */ + /* Thread and IPC gate capabilities. */ - l4_cap_idx_t thread; - l4_cap_idx_t server; + l4_cap_idx_t thread, server; - /* Receive deletion notifications via an IRQ. */ + /* The generic endpoint object and IRQ endpoint. */ - int notifications; - l4_cap_idx_t irq; + ipc_server_endpoint_type endpoint, irq_endpoint; } ipc_server_config_type; + + /* Server configuration defaults. */ typedef struct ipc_server_default_config_type @@ -102,11 +123,12 @@ /* Associate a notification IRQ with an IPC gate in the main thread. */ -long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq); +long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_umword_t id); /* Associate a notification IRQ with an IPC gate in the given thread. */ -long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_cap_idx_t thread); +long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, + l4_umword_t id, l4_cap_idx_t thread); /* Bind the main thread to a named IPC gate capability. */ diff -r 89e3e3e0864b -r a82f362d9f14 libipc/lib/src/server.c --- a/libipc/lib/src/server.c Mon Mar 20 14:52:03 2023 +0100 +++ b/libipc/lib/src/server.c Mon Mar 20 18:08:44 2023 +0100 @@ -1,7 +1,8 @@ /* * Server binding/registration. * - * Copyright (C) 2018, 2019, 2020, 2021, 2022 Paul Boddie + * Copyright (C) 2018, 2019, 2020, 2021, 2022, + * 2023 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -37,15 +38,16 @@ /* Associate an IRQ with the IPC gate in the main thread to handle gate deletion notifications. */ -long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq) +long ipc_server_apply_irq(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_umword_t id) { - return ipc_server_apply_irq_for_thread(cap, irq, l4re_env()->main_thread); + return ipc_server_apply_irq_for_thread(cap, irq, id, l4re_env()->main_thread); } /* Associate an IRQ with the IPC gate in the given thread to handle gate deletion notifications. */ -long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_cap_idx_t thread) +long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, + l4_umword_t id, l4_cap_idx_t thread) { /* Create an IRQ for the gate. */ @@ -57,7 +59,7 @@ /* Bind the IRQ to the thread, presenting the label if it provides the incoming message. */ - err = ipc_bind_irq(*irq, (l4_umword_t) *irq, thread); + err = ipc_bind_irq(*irq, id, thread); if (err) { @@ -162,7 +164,7 @@ if (name != NULL) { - err = ipc_server_bind(name, (l4_umword_t) &config, &config.server); + err = ipc_server_bind(name, (l4_umword_t) &config.endpoint, &config.server); if (err) return err; } @@ -211,17 +213,20 @@ -/* A server main loop handling endpoint deletion for an IPC gate dedicated to - a particular object within its own thread. */ +/* A server main loop handling endpoint deletion for IPC gates. The supplied + configuration object indicates common properties for components exposed via + IPC gates whose messages are handled by this loop. Where an IRQ is received + for the principal IPC gate, as indicated by the supplied configuration, the + loop terminates. */ long ipc_server_managed_loop(ipc_server_config_type *config) { ipc_message_t msg; - l4_umword_t label, irq_label; + l4_umword_t label; /* Permit other endpoints by dynamically interpreting the label. */ - ipc_server_config_type *config_from_label; + ipc_server_endpoint_type *endpoint; /* Declare the extent to which capabilities are expected in messages. */ @@ -245,19 +250,36 @@ if (l4_ipc_error(msg.tag, l4_utcb())) continue; - /* Message involves the IPC gate itself. */ + /* Obtain the endpoint and determine whether it represents an IRQ or a + component. */ - irq_label = (l4_umword_t) config->irq; + endpoint = (ipc_server_endpoint_type *) label; + + /* Message involves the IRQ. */ - if (!config->notifications || (config->notifications && (label != irq_label))) + if (l4_is_valid_cap(endpoint->irq)) { - config_from_label = (ipc_server_config_type *) label; - config_from_label->handler(&msg, config_from_label->handler_obj); + /* Finalise the associated configuration. */ + + if (endpoint->config->finaliser != NULL) + endpoint->config->finaliser(config); + + /* Terminate if the principal configuration is involved. */ + + if (endpoint->config == config) + break; } - /* Message involves the IRQ or a termination condition occurred. */ + /* Message involves a component. */ - else if ((config->notifications && (label == irq_label)) || msg.terminating) + else + { + endpoint->config->handler(&msg, endpoint->config->handler_obj); + } + + /* A termination condition occurred. */ + + if (msg.terminating) break; } @@ -274,12 +296,7 @@ { ipc_server_config_type *config = (ipc_server_config_type *) data; - long err = ipc_server_managed_loop(config); - - if (config->finaliser != NULL) - config->finaliser(config); - - return (void *) err; + return (void *) ipc_server_managed_loop(config); } /* Wait for an incoming message via an IPC gate dedicated to a particular @@ -310,10 +327,10 @@ config->server = L4_INVALID_CAP; } - if (l4_is_valid_cap(config->irq)) + if (l4_is_valid_cap(config->irq_endpoint.irq)) { - ipc_cap_free_um(config->irq); - config->irq = L4_INVALID_CAP; + ipc_cap_free_um(config->irq_endpoint.irq); + config->irq_endpoint.irq = L4_INVALID_CAP; } } @@ -355,10 +372,16 @@ config->thread = l4re_env()->main_thread; config->server = L4_INVALID_CAP; - /* No notifications and with IRQ to be potentially allocated. */ + /* Define the general endpoint with invalid IRQ capability. */ + + config->endpoint.irq = L4_INVALID_CAP; + config->endpoint.config = config; - config->notifications = 0; - config->irq = L4_INVALID_CAP; + /* Disable notifications, with the IRQ and associated configuration + potentially defined later. */ + + config->irq_endpoint.irq = L4_INVALID_CAP; + config->irq_endpoint.config = NULL; } /* Initialise but do not start a server using the given configuration. */ @@ -371,7 +394,7 @@ if (l4_is_invalid_cap(config->server)) { - err = ipc_server_new_for_thread(&config->server, config, config->thread); + err = ipc_server_new_for_thread(&config->server, &config->endpoint, config->thread); if (err) return err; @@ -379,16 +402,17 @@ /* Allocate an IRQ for notifications if requested. */ - if (config->notifications) + if (config->irq_endpoint.config != NULL) { - err = ipc_server_apply_irq_for_thread(config->server, &config->irq, config->thread); + err = ipc_server_apply_irq_for_thread(config->server, &config->irq_endpoint.irq, + (l4_umword_t) &config->irq_endpoint, config->thread); if (err) return err; /* Unmask the interrupt. */ - ipc_init_irq(config->irq); + ipc_init_irq(config->irq_endpoint.irq); } return L4_EOK;