1.1 --- a/include/ipc/cap_alloc.h Sat Jan 23 18:59:17 2021 +0100
1.2 +++ b/include/ipc/cap_alloc.h Sun Feb 14 01:06:09 2021 +0100
1.3 @@ -1,7 +1,7 @@
1.4 /*
1.5 * Capability allocation and management.
1.6 *
1.7 - * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
1.8 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
1.9 *
1.10 * This program is free software; you can redistribute it and/or
1.11 * modify it under the terms of the GNU General Public License as
1.12 @@ -25,6 +25,7 @@
1.13
1.14 EXTERN_C_BEGIN
1.15
1.16 +long ipc_cap_alloc_init(void);
1.17 l4_cap_idx_t ipc_cap_alloc(void);
1.18
1.19 int ipc_cap_free(l4_cap_idx_t cap);
2.1 --- a/include/ipc/message.h Sat Jan 23 18:59:17 2021 +0100
2.2 +++ b/include/ipc/message.h Sun Feb 14 01:06:09 2021 +0100
2.3 @@ -1,7 +1,7 @@
2.4 /*
2.5 * Interprocess communication message abstraction.
2.6 *
2.7 - * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
2.8 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
2.9 *
2.10 * This program is free software; you can redistribute it and/or
2.11 * modify it under the terms of the GNU General Public License as
2.12 @@ -90,6 +90,7 @@
2.13 void ipc_message_wait(ipc_message_t *msg, l4_umword_t *label);
2.14 void ipc_message_reply(ipc_message_t *msg);
2.15 void ipc_message_discard(ipc_message_t *msg);
2.16 +void ipc_message_free(ipc_message_t *msg);
2.17
2.18 /* Helper operations. */
2.19
3.1 --- a/include/ipc/server.h Sat Jan 23 18:59:17 2021 +0100
3.2 +++ b/include/ipc/server.h Sun Feb 14 01:06:09 2021 +0100
3.3 @@ -135,6 +135,10 @@
3.4
3.5 void ipc_server_finalise_config(ipc_server_config_type *config);
3.6
3.7 +/* Discard any thread created but not initiated. */
3.8 +
3.9 +void ipc_server_discard_thread(ipc_server_config_type *config);
3.10 +
3.11 /* Initialise a server configuration. */
3.12
3.13 void ipc_server_init_config(ipc_server_config_type *config);
4.1 --- a/include/ipc/util_ipc.h Sat Jan 23 18:59:17 2021 +0100
4.2 +++ b/include/ipc/util_ipc.h Sun Feb 14 01:06:09 2021 +0100
4.3 @@ -1,7 +1,7 @@
4.4 /*
4.5 * Interprocess communication abstractions.
4.6 *
4.7 - * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
4.8 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
4.9 *
4.10 * This program is free software; you can redistribute it and/or
4.11 * modify it under the terms of the GNU General Public License as
4.12 @@ -39,6 +39,7 @@
4.13 void _export_capability(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_cap_idx_t ref);
4.14 void _export_fpage(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_snd_fpage_t fpage);
4.15 void _export_page(l4_msgtag_t tag, l4_msg_regs_t *mregs, int item, l4_umword_t hot_spot, l4_fpage_t fpage);
4.16 +void _free_expected_capabilities(l4_buf_regs_t *bregs, int number);
4.17 long _import_capability(l4_msgtag_t tag, l4_buf_regs_t *bregs, l4_msg_regs_t *mregs, int item, l4_cap_idx_t *ref);
4.18 long _import_dataspace(l4_msgtag_t tag, l4_buf_regs_t *bregs, l4_msg_regs_t *mregs, int item, l4re_ds_t *mem, l4_addr_t *addr);
4.19 long _import_fpage(l4_msgtag_t tag, l4_buf_regs_t *bregs, l4_msg_regs_t *mregs, int item, l4_snd_fpage_t *fpage);
5.1 --- a/lib/src/cap_alloc.c Sat Jan 23 18:59:17 2021 +0100
5.2 +++ b/lib/src/cap_alloc.c Sun Feb 14 01:06:09 2021 +0100
5.3 @@ -1,7 +1,7 @@
5.4 /*
5.5 * Capability allocation and management.
5.6 *
5.7 - * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
5.8 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
5.9 *
5.10 * This program is free software; you can redistribute it and/or
5.11 * modify it under the terms of the GNU General Public License as
5.12 @@ -32,6 +32,8 @@
5.13
5.14 #include <l4/re/env.h>
5.15 #include <l4/sys/consts.h>
5.16 +#include <l4/sys/factory.h>
5.17 +#include <l4/sys/semaphore.h>
5.18 #include <l4/sys/task.h>
5.19 #include <l4/sys/types.h>
5.20
5.21 @@ -65,9 +67,34 @@
5.22
5.23
5.24
5.25 +static l4_cap_idx_t semaphore = L4_INVALID_CAP;
5.26 +
5.27 +/* Bootstrap the semaphore support needed by the allocation function. */
5.28 +
5.29 +long ipc_cap_alloc_init()
5.30 +{
5.31 + if (l4_is_invalid_cap(semaphore))
5.32 + {
5.33 + semaphore = ipc_cap_alloc();
5.34 +
5.35 + if (l4_is_invalid_cap(semaphore))
5.36 + return -L4_ENOENT;
5.37 +
5.38 + if (l4_error(l4_factory_create(l4re_env()->factory, L4_PROTO_SEMAPHORE, semaphore)))
5.39 + {
5.40 + ipc_cap_free_um(semaphore);
5.41 + return -L4_ENOENT;
5.42 + }
5.43 +
5.44 + l4_semaphore_up(semaphore);
5.45 + }
5.46 +
5.47 + return L4_EOK;
5.48 +}
5.49 +
5.50 /* Reserve and return a capability index. */
5.51
5.52 -l4_cap_idx_t ipc_cap_alloc()
5.53 +static l4_cap_idx_t _ipc_cap_alloc(void)
5.54 {
5.55 int current;
5.56 unsigned int *group, selector;
5.57 @@ -119,9 +146,26 @@
5.58 return L4_INVALID_CAP;
5.59 }
5.60
5.61 +l4_cap_idx_t ipc_cap_alloc()
5.62 +{
5.63 + l4_cap_idx_t cap;
5.64 +
5.65 + /* Allocate a capability in the critical section, then return. */
5.66 +
5.67 + if (l4_is_valid_cap(semaphore))
5.68 + l4_semaphore_down(semaphore, L4_IPC_NEVER);
5.69 +
5.70 + cap = _ipc_cap_alloc();
5.71 +
5.72 + if (l4_is_valid_cap(semaphore))
5.73 + l4_semaphore_up(semaphore);
5.74 +
5.75 + return cap;
5.76 +}
5.77 +
5.78 /* Release a capability. */
5.79
5.80 -int ipc_cap_free(l4_cap_idx_t cap)
5.81 +static int _ipc_cap_free(l4_cap_idx_t cap)
5.82 {
5.83 int index;
5.84 unsigned int *group, selector;
5.85 @@ -150,9 +194,24 @@
5.86 return 1;
5.87 }
5.88
5.89 +int ipc_cap_free(l4_cap_idx_t cap)
5.90 +{
5.91 + int result;
5.92 +
5.93 + if (l4_is_valid_cap(semaphore))
5.94 + l4_semaphore_down(semaphore, L4_IPC_NEVER);
5.95 +
5.96 + result = _ipc_cap_free(cap);
5.97 +
5.98 + if (l4_is_valid_cap(semaphore))
5.99 + l4_semaphore_up(semaphore);
5.100 +
5.101 + return result;
5.102 +}
5.103 +
5.104 /* Free the indicated capability and unmap it. */
5.105
5.106 -int ipc_cap_free_um(l4_cap_idx_t cap)
5.107 +static int _ipc_cap_free_um(l4_cap_idx_t cap)
5.108 {
5.109 if (ipc_cap_free(cap))
5.110 {
5.111 @@ -162,3 +221,18 @@
5.112
5.113 return 0;
5.114 }
5.115 +
5.116 +int ipc_cap_free_um(l4_cap_idx_t cap)
5.117 +{
5.118 + int result;
5.119 +
5.120 + if (l4_is_valid_cap(semaphore))
5.121 + l4_semaphore_down(semaphore, L4_IPC_NEVER);
5.122 +
5.123 + result = _ipc_cap_free_um(cap);
5.124 +
5.125 + if (l4_is_valid_cap(semaphore))
5.126 + l4_semaphore_up(semaphore);
5.127 +
5.128 + return result;
5.129 +}
6.1 --- a/lib/src/irq.c Sat Jan 23 18:59:17 2021 +0100
6.2 +++ b/lib/src/irq.c Sun Feb 14 01:06:09 2021 +0100
6.3 @@ -1,7 +1,7 @@
6.4 /*
6.5 * Interrupt request handling.
6.6 *
6.7 - * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
6.8 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
6.9 *
6.10 * This program is free software; you can redistribute it and/or
6.11 * modify it under the terms of the GNU General Public License as
6.12 @@ -21,10 +21,8 @@
6.13
6.14 #include <l4/re/env.h>
6.15 #include <l4/sys/factory.h>
6.16 -#include <l4/sys/ipc.h>
6.17 #include <l4/sys/irq.h>
6.18 #include <l4/sys/rcv_endpoint.h>
6.19 -#include <l4/sys/utcb.h>
6.20
6.21 #include "cap_alloc.h"
6.22 #include "irq.h"
6.23 @@ -37,19 +35,20 @@
6.24
6.25 long ipc_create_irq(l4_cap_idx_t *irq)
6.26 {
6.27 - l4_msgtag_t tag;
6.28 long err;
6.29
6.30 *irq = ipc_cap_alloc();
6.31
6.32 if (l4_is_invalid_cap(*irq))
6.33 - return -L4_ENOMEM;
6.34 + return -L4_ENOENT;
6.35
6.36 - tag = l4_factory_create_irq(l4re_env()->factory, *irq);
6.37 - err = l4_error(tag);
6.38 + err = l4_error(l4_factory_create_irq(l4re_env()->factory, *irq));
6.39
6.40 if (err)
6.41 + {
6.42 + ipc_cap_free_um(*irq);
6.43 return err;
6.44 + }
6.45
6.46 return L4_EOK;
6.47 }
6.48 @@ -65,8 +64,7 @@
6.49
6.50 long ipc_bind_irq(l4_cap_idx_t irq, l4_umword_t id, l4_cap_idx_t thread)
6.51 {
6.52 - l4_msgtag_t tag = l4_rcv_ep_bind_thread(irq, thread, id);
6.53 - long err = l4_error(tag);
6.54 + long err = l4_error(l4_rcv_ep_bind_thread(irq, thread, id));
6.55
6.56 if (err)
6.57 return err;
7.1 --- a/lib/src/mem_ipc.c Sat Jan 23 18:59:17 2021 +0100
7.2 +++ b/lib/src/mem_ipc.c Sun Feb 14 01:06:09 2021 +0100
7.3 @@ -1,7 +1,7 @@
7.4 /*
7.5 * Memory sharing abstractions.
7.6 *
7.7 - * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
7.8 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
7.9 *
7.10 * This program is free software; you can redistribute it and/or
7.11 * modify it under the terms of the GNU General Public License as
8.1 --- a/lib/src/message.c Sat Jan 23 18:59:17 2021 +0100
8.2 +++ b/lib/src/message.c Sun Feb 14 01:06:09 2021 +0100
8.3 @@ -1,7 +1,7 @@
8.4 /*
8.5 * Interprocess communication message abstraction.
8.6 *
8.7 - * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
8.8 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
8.9 *
8.10 * This program is free software; you can redistribute it and/or
8.11 * modify it under the terms of the GNU General Public License as
8.12 @@ -66,6 +66,13 @@
8.13 return L4_EOK;
8.14 }
8.15
8.16 +/* Free capabilities expected in messages. */
8.17 +
8.18 +void ipc_message_free(ipc_message_t *msg)
8.19 +{
8.20 + _free_expected_capabilities(&msg->bregs, msg->expected_items);
8.21 +}
8.22 +
8.23 /* Clear message attributes for sending and response handling. */
8.24
8.25 void ipc_message_new(ipc_message_t *msg)
9.1 --- a/lib/src/server.c Sat Jan 23 18:59:17 2021 +0100
9.2 +++ b/lib/src/server.c Sun Feb 14 01:06:09 2021 +0100
9.3 @@ -1,7 +1,7 @@
9.4 /*
9.5 * Server binding/registration.
9.6 *
9.7 - * Copyright (C) 2018, 2019, 2020 Paul Boddie <paul@boddie.org.uk>
9.8 + * Copyright (C) 2018, 2019, 2020, 2021 Paul Boddie <paul@boddie.org.uk>
9.9 *
9.10 * This program is free software; you can redistribute it and/or
9.11 * modify it under the terms of the GNU General Public License as
9.12 @@ -45,8 +45,6 @@
9.13
9.14 long ipc_server_apply_irq_for_thread(l4_cap_idx_t cap, l4_cap_idx_t *irq, l4_cap_idx_t thread)
9.15 {
9.16 - l4_msgtag_t tag;
9.17 -
9.18 /* Create an IRQ for the gate. */
9.19
9.20 long err = ipc_create_irq(irq);
9.21 @@ -57,26 +55,28 @@
9.22 /* Bind the IRQ to the thread, presenting the label if it provides the
9.23 incoming message. */
9.24
9.25 - tag = l4_rcv_ep_bind_thread(*irq, thread, (l4_umword_t) *irq);
9.26 + err = l4_error(l4_rcv_ep_bind_thread(*irq, thread, (l4_umword_t) *irq));
9.27
9.28 - err = l4_error(tag);
9.29 if (err)
9.30 + {
9.31 + ipc_cap_free_um(*irq);
9.32 return err;
9.33 + }
9.34
9.35 /* Register for notifications. The thread associated with the gate seems to be
9.36 needed. */
9.37
9.38 - tag = l4_thread_register_del_irq(thread, *irq);
9.39 + err = l4_error(l4_thread_register_del_irq(thread, *irq));
9.40
9.41 - err = l4_error(tag);
9.42 if (err)
9.43 + {
9.44 + ipc_cap_free_um(*irq);
9.45 return err;
9.46 + }
9.47
9.48 /* Decrease the reference count on the server capability (IPC gate). */
9.49
9.50 - tag = l4_kobject_dec_refcnt(cap, 1);
9.51 -
9.52 - return l4_error(tag);
9.53 + return l4_error(l4_kobject_dec_refcnt(cap, 1));
9.54 }
9.55
9.56
9.57 @@ -86,8 +86,6 @@
9.58
9.59 long ipc_server_bind(const char *name, l4_umword_t id, l4_cap_idx_t *server)
9.60 {
9.61 - l4_msgtag_t tag;
9.62 -
9.63 /* Obtain a reference to the device. */
9.64
9.65 *server = l4re_env_get_cap(name);
9.66 @@ -98,8 +96,7 @@
9.67 /* Bind to an IPC gate with the label identifying the server as message
9.68 destination. */
9.69
9.70 - tag = l4_rcv_ep_bind_thread(*server, l4re_env()->main_thread, id);
9.71 - return l4_error(tag);
9.72 + return l4_error(l4_rcv_ep_bind_thread(*server, l4re_env()->main_thread, id));
9.73 }
9.74
9.75 /* Initialise a new server capability, binding it to the main thread. */
9.76 @@ -133,15 +130,21 @@
9.77
9.78 long ipc_server_new_gate_for_thread(l4_cap_idx_t *ref, l4_cap_idx_t thread, l4_umword_t id)
9.79 {
9.80 + long err;
9.81 +
9.82 *ref = ipc_cap_alloc();
9.83
9.84 if (l4_is_invalid_cap(*ref))
9.85 - return -L4_ENOMEM;
9.86 + return -L4_ENOENT;
9.87
9.88 /* Associate the object with an IPC gate. */
9.89
9.90 - l4_factory_create_gate(l4re_env()->factory, *ref, thread, id);
9.91 - return L4_EOK;
9.92 + err = l4_error(l4_factory_create_gate(l4re_env()->factory, *ref, thread, id));
9.93 +
9.94 + if (err)
9.95 + ipc_cap_free_um(*ref);
9.96 +
9.97 + return err;
9.98 }
9.99
9.100
9.101 @@ -201,6 +204,10 @@
9.102 break;
9.103 }
9.104
9.105 + /* Free expected capabilities. */
9.106 +
9.107 + ipc_message_free(&msg);
9.108 +
9.109 return L4_EOK;
9.110 }
9.111
9.112 @@ -242,10 +249,27 @@
9.113 void ipc_server_finalise_config(ipc_server_config_type *config)
9.114 {
9.115 if (l4_is_valid_cap(config->server))
9.116 + {
9.117 ipc_cap_free_um(config->server);
9.118 + config->server = L4_INVALID_CAP;
9.119 + }
9.120
9.121 if (l4_is_valid_cap(config->irq))
9.122 + {
9.123 ipc_cap_free_um(config->irq);
9.124 + config->irq = L4_INVALID_CAP;
9.125 + }
9.126 +}
9.127 +
9.128 +/* Discard any thread created but not initiated. */
9.129 +
9.130 +void ipc_server_discard_thread(ipc_server_config_type *config)
9.131 +{
9.132 + if (config->new_thread && l4_is_valid_cap(config->thread))
9.133 + {
9.134 + ipc_cap_free_um(config->thread);
9.135 + config->thread = L4_INVALID_CAP;
9.136 + }
9.137 }
9.138
9.139 /* Initialise a server configuration. */
10.1 --- a/lib/src/util_ipc.c Sat Jan 23 18:59:17 2021 +0100
10.2 +++ b/lib/src/util_ipc.c Sun Feb 14 01:06:09 2021 +0100
10.3 @@ -1,7 +1,7 @@
10.4 /*
10.5 * Interprocess communication abstractions.
10.6 *
10.7 - * Copyright (C) 2018, 2019 Paul Boddie <paul@boddie.org.uk>
10.8 + * Copyright (C) 2018, 2019, 2021 Paul Boddie <paul@boddie.org.uk>
10.9 *
10.10 * This program is free software; you can redistribute it and/or
10.11 * modify it under the terms of the GNU General Public License as
10.12 @@ -35,10 +35,14 @@
10.13 long _expect_capabilities(l4_buf_regs_t *bregs, int number)
10.14 {
10.15 int i;
10.16 + long err;
10.17
10.18 for (i = 0; i < number; i++)
10.19 - if (_expect_capability(bregs, i))
10.20 - return -L4_ENOMEM;
10.21 + {
10.22 + err = _expect_capability(bregs, i);
10.23 + if (err)
10.24 + return err;
10.25 + }
10.26
10.27 return L4_EOK;
10.28 }
10.29 @@ -48,8 +52,9 @@
10.30 long _expect_capability(l4_buf_regs_t *bregs, int item)
10.31 {
10.32 l4_cap_idx_t future = ipc_cap_alloc();
10.33 +
10.34 if (l4_is_invalid_cap(future))
10.35 - return -L4_ENOMEM;
10.36 + return -L4_ENOENT;
10.37
10.38 /* Indicate the expectation of a capability in return. */
10.39
10.40 @@ -90,6 +95,21 @@
10.41 mregs->mr[words + item * 2 + 1] = fpage.raw;
10.42 }
10.43
10.44 +/* Free expected capabilities held by the buffer registers. */
10.45 +
10.46 +void _free_expected_capabilities(l4_buf_regs_t *bregs, int number)
10.47 +{
10.48 + int i;
10.49 + l4_cap_idx_t cap;
10.50 +
10.51 + for (i = 0; i < number; i++)
10.52 + {
10.53 + cap = bregs->br[i] & L4_CAP_MASK;
10.54 + if (l4_is_valid_cap(cap))
10.55 + ipc_cap_free_um(cap);
10.56 + }
10.57 +}
10.58 +
10.59 /* Import from the message the capability at the given item position. */
10.60
10.61 long _import_capability(l4_msgtag_t tag, l4_buf_regs_t *bregs,
10.62 @@ -125,18 +145,28 @@
10.63 *mem = ipc_cap_alloc();
10.64
10.65 err = _import_capability(tag, bregs, mregs, item, mem);
10.66 +
10.67 if (err)
10.68 + {
10.69 + ipc_cap_free_um(*mem);
10.70 return err;
10.71 + }
10.72
10.73 /* Attach the dataspace to a region. */
10.74
10.75 err = ipc_dataspace_size(*mem, &size);
10.76 if (err)
10.77 + {
10.78 + ipc_cap_free_um(*mem);
10.79 return err;
10.80 + }
10.81
10.82 err = ipc_attach_dataspace(*mem, size, (void **) addr);
10.83 if (err)
10.84 + {
10.85 + ipc_cap_free_um(*mem);
10.86 return err;
10.87 + }
10.88
10.89 return L4_EOK;
10.90 }