L4Re/departure

Changeset

530:a82f362d9f14
2023-03-20 Paul Boddie raw files shortlog changelog graph Changed IPC message handling to interpret gate labels as generic endpoint addresses, with endpoint structures representing components and notification IRQs. ipc-config-endpoints
libfsserver/lib/generic/resource_server.cc (file) libipc/include/ipc/server.h (file) libipc/lib/src/server.c (file)
     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;