1.1 --- a/Makefile Wed Mar 24 23:18:06 2021 +0100
1.2 +++ b/Makefile Wed Mar 24 23:44:53 2021 +0100
1.3 @@ -2,8 +2,8 @@
1.4 L4DIR ?= $(PKGDIR)/../..
1.5
1.6 TARGET = \
1.7 - dstest_block_client dstest_host_client dstest_test_client \
1.8 - dstest_block_server dstest_host_server dstest_test_server
1.9 + dstest_block_client dstest_host_client dstest_pipe_client dstest_test_client \
1.10 + dstest_block_server dstest_host_server dstest_pipe_server dstest_test_server
1.11
1.12 MODE = static
1.13
1.14 @@ -24,13 +24,16 @@
1.15 opener_context_object_NAME = OpenerContextObject
1.16 opener_context_object_INTERFACES = dataspace opener_context
1.17
1.18 -COMP_INTERFACES_CC = mapped_file_object opener_context_object
1.19 +pipe_object_NAME = PipeObject
1.20 +pipe_object_INTERFACES = dataspace pipe
1.21 +
1.22 +COMP_INTERFACES_CC = mapped_file_object opener_context_object pipe_object
1.23
1.24 # Individual interfaces.
1.25
1.26 -CLIENT_INTERFACES_CC = dataspace file mapped_file opener opener_context
1.27 +CLIENT_INTERFACES_CC = dataspace file mapped_file opener opener_context pipe pipe_opener
1.28
1.29 -SERVER_INTERFACES_CC = opener $(call common_interfaces,$(COMP_INTERFACES_CC))
1.30 +SERVER_INTERFACES_CC = opener pipe_opener $(call common_interfaces,$(COMP_INTERFACES_CC))
1.31
1.32 # Generated and plain source files.
1.33
1.34 @@ -44,13 +47,16 @@
1.35
1.36 PLAIN_SRC_CC_dstest_host_client = dstest_host_client.cc file.cc
1.37
1.38 +PLAIN_SRC_CC_dstest_pipe_client = dstest_pipe_client.cc file.cc
1.39 +
1.40 PLAIN_SRC_CC_dstest_test_client = dstest_test_client.cc file.cc
1.41
1.42 PLAIN_SRC_CC_common_server = \
1.43 access_map.cc accessing.cc accessor.cc \
1.44 flexpage.cc file_pager.cc ipc.cc memory.cc \
1.45 opener_resource.cc opener_context_resource.cc \
1.46 - page_mapper.cc page_queue.cc pager.cc pages.cc paging.cc \
1.47 + page_mapper.cc page_queue.cc pager.cc \
1.48 + pages.cc pages_conserving.cc paging.cc \
1.49 region.cc resource_server.cc simple_pager.cc
1.50
1.51 PLAIN_SRC_CC_dstest_block_server = \
1.52 @@ -64,6 +70,12 @@
1.53 dstest_host_server.cc \
1.54 files/host_file_accessor.cc files/host_file_opener.cc
1.55
1.56 +PLAIN_SRC_CC_dstest_pipe_server = \
1.57 + $(PLAIN_SRC_CC_common_server) \
1.58 + dstest_pipe_server.cc \
1.59 + pipe_opener_resource.cc pipe_pager.cc \
1.60 + files/pipe_accessor.cc files/pipe_paging.cc
1.61 +
1.62 PLAIN_SRC_CC_dstest_test_server = \
1.63 $(PLAIN_SRC_CC_common_server) \
1.64 dstest_test_server.cc \
1.65 @@ -81,6 +93,11 @@
1.66 $(PLAIN_SRC_CC_dstest_host_client) \
1.67 $(COMMON_SRC_CC)
1.68
1.69 +SRC_CC_dstest_pipe_client = \
1.70 + $(CLIENT_INTERFACES_SRC_CC) \
1.71 + $(PLAIN_SRC_CC_dstest_pipe_client) \
1.72 + $(COMMON_SRC_CC)
1.73 +
1.74 SRC_CC_dstest_test_client = \
1.75 $(CLIENT_INTERFACES_SRC_CC) \
1.76 $(PLAIN_SRC_CC_dstest_test_client) \
1.77 @@ -96,6 +113,11 @@
1.78 $(PLAIN_SRC_CC_dstest_host_server) \
1.79 $(COMMON_SRC_CC)
1.80
1.81 +SRC_CC_dstest_pipe_server = \
1.82 + $(SERVER_INTERFACES_SRC_CC) \
1.83 + $(PLAIN_SRC_CC_dstest_pipe_server) \
1.84 + $(COMMON_SRC_CC)
1.85 +
1.86 SRC_CC_dstest_test_server = \
1.87 $(SERVER_INTERFACES_SRC_CC) \
1.88 $(PLAIN_SRC_CC_dstest_test_server) \
1.89 @@ -112,10 +134,14 @@
1.90
1.91 $(PLAIN_SRC_CC_dstest_host_client): $(CLIENT_INTERFACES_SRC_CC)
1.92
1.93 +$(PLAIN_SRC_CC_dstest_pipe_client): $(CLIENT_INTERFACES_SRC_CC)
1.94 +
1.95 $(PLAIN_SRC_CC_dstest_test_client): $(CLIENT_INTERFACES_SRC_CC)
1.96
1.97 $(PLAIN_SRC_CC_dstest_block_server): $(SERVER_INTERFACES_SRC_CC)
1.98
1.99 $(PLAIN_SRC_CC_dstest_host_server): $(SERVER_INTERFACES_SRC_CC)
1.100
1.101 +$(PLAIN_SRC_CC_dstest_pipe_server): $(SERVER_INTERFACES_SRC_CC)
1.102 +
1.103 $(PLAIN_SRC_CC_dstest_test_server): $(SERVER_INTERFACES_SRC_CC)
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/conf/dstest_pipe.cfg Wed Mar 24 23:44:53 2021 +0100
2.3 @@ -0,0 +1,23 @@
2.4 +-- vim:set ft=lua:
2.5 +
2.6 +local L4 = require("L4");
2.7 +
2.8 +local l = L4.default_loader;
2.9 +
2.10 +local server = l:new_channel();
2.11 +
2.12 +l:start({
2.13 + caps = {
2.14 + server = server:svr(),
2.15 + },
2.16 + log = { "server", "r" },
2.17 + },
2.18 + "rom/dstest_pipe_server");
2.19 +
2.20 +l:start({
2.21 + caps = {
2.22 + server = server,
2.23 + },
2.24 + log = { "client", "g" },
2.25 + },
2.26 + "rom/dstest_pipe_client");
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/conf/dstest_pipe.list Wed Mar 24 23:44:53 2021 +0100
3.3 @@ -0,0 +1,25 @@
3.4 +entry dstest_pipe
3.5 +roottask moe rom/dstest_pipe.cfg
3.6 +module dstest_pipe.cfg
3.7 +module l4re
3.8 +module ned
3.9 +module dstest_pipe_client
3.10 +module dstest_pipe_server
3.11 +module lib4re-c.so
3.12 +module lib4re-c-util.so
3.13 +module lib4re.so
3.14 +module lib4re-util.so
3.15 +module libc_be_l4refile.so
3.16 +module libc_be_l4re.so
3.17 +module libc_be_socket_noop.so
3.18 +module libc_support_misc.so
3.19 +module libdl.so
3.20 +module libipc.so
3.21 +module libl4sys-direct.so
3.22 +module libl4sys.so
3.23 +module libl4util.so
3.24 +module libld-l4.so
3.25 +module libpthread.so
3.26 +module libstdc++.so
3.27 +module libsupc++.so
3.28 +module libuc_c.so
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/dstest_pipe_client.cc Wed Mar 24 23:44:53 2021 +0100
4.3 @@ -0,0 +1,117 @@
4.4 +/*
4.5 + * Test pipe operations.
4.6 + *
4.7 + * Copyright (C) 2020, 2021 Paul Boddie <paul@boddie.org.uk>
4.8 + *
4.9 + * This program is free software; you can redistribute it and/or
4.10 + * modify it under the terms of the GNU General Public License as
4.11 + * published by the Free Software Foundation; either version 2 of
4.12 + * the License, or (at your option) any later version.
4.13 + *
4.14 + * This program is distributed in the hope that it will be useful,
4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 + * GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License
4.20 + * along with this program; if not, write to the Free Software
4.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
4.22 + * Boston, MA 02110-1301, USA
4.23 + */
4.24 +
4.25 +#include <l4/re/env.h>
4.26 +#include <l4/sys/err.h>
4.27 +
4.28 +#include <stdio.h>
4.29 +#include <string.h>
4.30 +#include <stdlib.h>
4.31 +
4.32 +#include "file.h"
4.33 +#include "memory_utils.h"
4.34 +
4.35 +
4.36 +
4.37 +static void show(file_t *file, offset_t step, offset_t sample)
4.38 +{
4.39 + /* Allocate a buffer for sampling from the file. */
4.40 +
4.41 + char buf[sample + 1];
4.42 +
4.43 + for (offset_t offset = 0; offset < file_populated_span(file); offset += step)
4.44 + {
4.45 + printf("show %ld of %ld...\n", offset, file_populated_span(file));
4.46 +
4.47 + unsigned long remaining = file_populated_span(file) - offset;
4.48 + unsigned long sample_remaining = remaining < sample ? remaining : sample;
4.49 +
4.50 + printf("%ld bytes from %p...\n", sample_remaining, (file->memory + offset));
4.51 + strncpy(buf, (file->memory + offset), sample_remaining);
4.52 + buf[sample_remaining] = '\0';
4.53 + printf("%s\n", buf);
4.54 + }
4.55 +}
4.56 +
4.57 +int main(void)
4.58 +{
4.59 + /* Obtain access to the filesystem. */
4.60 +
4.61 + l4_cap_idx_t server = l4re_env_get_cap("server");
4.62 +
4.63 + /* Invoke the open method to receive the file reference. */
4.64 +
4.65 + file_t reader, writer;
4.66 + long err = pipe_open(&reader, &writer, server);
4.67 +
4.68 + if (err)
4.69 + {
4.70 + printf("Could not obtain pipe: %s\n", l4sys_errtostr(err));
4.71 + return 1;
4.72 + }
4.73 +
4.74 + /* Use the writer to fill the pipe with data. */
4.75 +
4.76 + for (int region = 0; region < 3; region++)
4.77 + {
4.78 + printf("Write %ld to pipe at %p...\n", file_span(&writer), writer.memory);
4.79 +
4.80 + memset(writer.memory, (int) 'a' + region, file_span(&writer));
4.81 +
4.82 + err = pipe_written(&writer, file_span(&writer));
4.83 +
4.84 + if (err)
4.85 + {
4.86 + printf("Written data error: %s\n", l4sys_errtostr(err));
4.87 + return 1;
4.88 + }
4.89 +
4.90 + show(&writer, page(1), 60);
4.91 +
4.92 + err = pipe_next(&writer);
4.93 +
4.94 + if (err)
4.95 + {
4.96 + printf("Region traversal error: %s\n", l4sys_errtostr(err));
4.97 + return 1;
4.98 + }
4.99 + }
4.100 +
4.101 + /* Use the reader to obtain data from the pipe. */
4.102 +
4.103 + err = pipe_current(&reader);
4.104 +
4.105 + while (!err)
4.106 + {
4.107 + printf("show...\n");
4.108 + show(&reader, page(1), 60);
4.109 + err = pipe_next(&reader);
4.110 + }
4.111 +
4.112 + if (err)
4.113 + printf("Reading termination condition: %s\n", l4sys_errtostr(err));
4.114 +
4.115 + printf("Data shown.\n");
4.116 +
4.117 + return 0;
4.118 +}
4.119 +
4.120 +// vim: tabstop=2 expandtab shiftwidth=2
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/dstest_pipe_server.cc Wed Mar 24 23:44:53 2021 +0100
5.3 @@ -0,0 +1,58 @@
5.4 +/*
5.5 + * Test pipe operations.
5.6 + *
5.7 + * Copyright (C) 2020, 2021 Paul Boddie <paul@boddie.org.uk>
5.8 + *
5.9 + * This program is free software; you can redistribute it and/or
5.10 + * modify it under the terms of the GNU General Public License as
5.11 + * published by the Free Software Foundation; either version 2 of
5.12 + * the License, or (at your option) any later version.
5.13 + *
5.14 + * This program is distributed in the hope that it will be useful,
5.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.17 + * GNU General Public License for more details.
5.18 + *
5.19 + * You should have received a copy of the GNU General Public License
5.20 + * along with this program; if not, write to the Free Software
5.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
5.22 + * Boston, MA 02110-1301, USA
5.23 + */
5.24 +
5.25 +#include <l4/sys/err.h>
5.26 +
5.27 +#include <stdio.h>
5.28 +
5.29 +#include "memory.h"
5.30 +#include "pages_conserving.h"
5.31 +#include "pipe_opener_resource.h"
5.32 +#include "resource_server.h"
5.33 +
5.34 +
5.35 +
5.36 +const unsigned int MEMORY_PAGES = 20;
5.37 +const unsigned int PIPE_PAGES = 2;
5.38 +
5.39 +int main(void)
5.40 +{
5.41 + /* Some memory plus infrastructure. */
5.42 +
5.43 + Memory mem(MEMORY_PAGES);
5.44 + PagesConserving pages(&mem, PIPE_PAGES);
5.45 + PipeOpenerResource opener(&pages);
5.46 +
5.47 + /* Register a server associating it with the given object. */
5.48 +
5.49 + ResourceServer server(&opener);
5.50 + long err = server.bind("server");
5.51 +
5.52 + if (err)
5.53 + {
5.54 + printf("Could not bind server: %s\n", l4sys_errtostr(err));
5.55 + return 1;
5.56 + }
5.57 +
5.58 + printf("Starting server...\n");
5.59 + server.start();
5.60 + return 0;
5.61 +}
6.1 --- a/file.cc Wed Mar 24 23:18:06 2021 +0100
6.2 +++ b/file.cc Wed Mar 24 23:44:53 2021 +0100
6.3 @@ -28,6 +28,8 @@
6.4 #include "file_client.h"
6.5 #include "opener_client.h"
6.6 #include "opener_context_client.h"
6.7 +#include "pipe_client.h"
6.8 +#include "pipe_opener_client.h"
6.9 #include "mapped_file_client.h"
6.10
6.11 #include "file.h"
6.12 @@ -229,4 +231,90 @@
6.13 return 0;
6.14 }
6.15
6.16 +
6.17 +
6.18 +/* Open two pipe endpoints using the given pipe server. */
6.19 +
6.20 +long pipe_open(file_t *reader, file_t *writer, l4_cap_idx_t server)
6.21 +{
6.22 + client_PipeOpener opener(server);
6.23 +
6.24 + file_init(reader);
6.25 + file_init(writer);
6.26 +
6.27 + long err = opener.pipe(&reader->ref, &writer->ref);
6.28 + if (err)
6.29 + return err;
6.30 +
6.31 + err = pipe_next(writer) || pipe_next(reader);
6.32 +
6.33 + if (err)
6.34 + {
6.35 + file_close(reader);
6.36 + file_close(writer);
6.37 + }
6.38 +
6.39 + return err;
6.40 +}
6.41 +
6.42 +/* Access the current region for a pipe endpoint. */
6.43 +
6.44 +long pipe_current(file_t *pipe)
6.45 +{
6.46 + client_Pipe _pipe(pipe->ref);
6.47 + long err = _pipe.current_region(&pipe->data_end, &pipe->size);
6.48 + char *memory = pipe->memory;
6.49 +
6.50 + if (err)
6.51 + return err;
6.52 +
6.53 + pipe->end_pos = pipe->size;
6.54 +
6.55 + err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory);
6.56 + if (err)
6.57 + return err;
6.58 +
6.59 + if (memory != NULL)
6.60 + ipc_detach_dataspace(memory);
6.61 +
6.62 + return L4_EOK;
6.63 +}
6.64 +
6.65 +/* Access the next region for a pipe endpoint, updating the eventual size of
6.66 + the current region. */
6.67 +
6.68 +long pipe_next(file_t *pipe)
6.69 +{
6.70 + client_Pipe _pipe(pipe->ref);
6.71 + long err = _pipe.next_region(&pipe->data_end, &pipe->size);
6.72 + char *memory = pipe->memory;
6.73 +
6.74 + if (err)
6.75 + return err;
6.76 +
6.77 + pipe->end_pos = pipe->size;
6.78 +
6.79 + err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory);
6.80 + if (err)
6.81 + return err;
6.82 +
6.83 + if (memory != NULL)
6.84 + ipc_detach_dataspace(memory);
6.85 +
6.86 + return L4_EOK;
6.87 +}
6.88 +
6.89 +/* Set the size of the written region. */
6.90 +
6.91 +long pipe_written(file_t *pipe, offset_t size)
6.92 +{
6.93 + if (size <= pipe->size)
6.94 + {
6.95 + pipe->data_end = size;
6.96 + return L4_EOK;
6.97 + }
6.98 + else
6.99 + return -L4_EINVAL;
6.100 +}
6.101 +
6.102 // vim: tabstop=2 expandtab shiftwidth=2
7.1 --- a/file.h Wed Mar 24 23:18:06 2021 +0100
7.2 +++ b/file.h Wed Mar 24 23:44:53 2021 +0100
7.3 @@ -78,6 +78,18 @@
7.4 char *file_string_get(file_t *file, offset_t offset);
7.5 int file_string_set(file_t *file, const char *data, offset_t offset, offset_t *written);
7.6
7.7 +
7.8 +
7.9 +/* Pipe operations. */
7.10 +
7.11 +long pipe_open(file_t *reader, file_t *writer, l4_cap_idx_t server);
7.12 +
7.13 +/* Pipe region operations. */
7.14 +
7.15 +long pipe_current(file_t *pipe);
7.16 +long pipe_next(file_t *pipe);
7.17 +long pipe_written(file_t *pipe, offset_t size);
7.18 +
7.19 EXTERN_C_END
7.20
7.21 // vim: tabstop=2 expandtab shiftwidth=2
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/files/pipe_accessor.cc Wed Mar 24 23:44:53 2021 +0100
8.3 @@ -0,0 +1,43 @@
8.4 +#include "pipe_accessor.h"
8.5 +
8.6 +#include <string.h>
8.7 +
8.8 +PipeAccessor::PipeAccessor()
8.9 +: Accessor(0)
8.10 +{
8.11 +}
8.12 +
8.13 +/* Perform any closing operation on the file. */
8.14 +
8.15 +void PipeAccessor::close()
8.16 +{
8.17 +}
8.18 +
8.19 +/* Perform any opening operation on the file. */
8.20 +
8.21 +void PipeAccessor::open()
8.22 +{
8.23 +}
8.24 +
8.25 +/* Data transfer helper methods. */
8.26 +
8.27 +void PipeAccessor::fill_populated(Flexpage *flexpage)
8.28 +{
8.29 + offset_t filepos = flexpage->base_offset;
8.30 + offset_t addr = flexpage->base_addr;
8.31 +
8.32 + /* Tag the region with file state. */
8.33 +
8.34 + flexpage->region->fill(fileid, filepos);
8.35 +
8.36 + /* File the flexpage with zero. */
8.37 +
8.38 + memset((void *) addr, 0, flexpage->size);
8.39 +}
8.40 +
8.41 +void PipeAccessor::flush_populated(Flexpage *flexpage)
8.42 +{
8.43 + flexpage->region->flush();
8.44 +}
8.45 +
8.46 +// vim: tabstop=4 expandtab shiftwidth=4
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/files/pipe_accessor.h Wed Mar 24 23:44:53 2021 +0100
9.3 @@ -0,0 +1,25 @@
9.4 +#pragma once
9.5 +
9.6 +#include "accessor.h"
9.7 +
9.8 +/* A pipe accessor, providing flexpages for pipe sections. */
9.9 +
9.10 +class PipeAccessor : public Accessor
9.11 +{
9.12 +protected:
9.13 +
9.14 + /* Data transfer helper methods. */
9.15 +
9.16 + virtual void fill_populated(Flexpage *flexpage);
9.17 +
9.18 + virtual void flush_populated(Flexpage *flexpage);
9.19 +
9.20 +public:
9.21 + explicit PipeAccessor();
9.22 +
9.23 + virtual void close();
9.24 +
9.25 + virtual void open();
9.26 +};
9.27 +
9.28 +// vim: tabstop=4 expandtab shiftwidth=4
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/files/pipe_paging.cc Wed Mar 24 23:44:53 2021 +0100
10.3 @@ -0,0 +1,35 @@
10.4 +#include "pipe_paging.h"
10.5 +
10.6 +PipePaging::PipePaging()
10.7 +{
10.8 +}
10.9 +
10.10 +/* Add a region to the sequence. */
10.11 +
10.12 +void PipePaging::add_region(PageMapper *mapper)
10.13 +{
10.14 + _regions.push_back(mapper);
10.15 +}
10.16 +
10.17 +/* Return the first region in the sequence. */
10.18 +
10.19 +PageMapper *PipePaging::first_region()
10.20 +{
10.21 + return _regions.front();
10.22 +}
10.23 +
10.24 +/* Return the next region for the reader. If only a single region remains, with
10.25 + the reader wishing to move to the next, return NULL. */
10.26 +
10.27 +PageMapper *PipePaging::next_region()
10.28 +{
10.29 + if (_regions.size() > 1)
10.30 + {
10.31 + _regions.pop_front();
10.32 + return _regions.front();
10.33 + }
10.34 + else
10.35 + return NULL;
10.36 +}
10.37 +
10.38 +// vim: tabstop=4 expandtab shiftwidth=4
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/files/pipe_paging.h Wed Mar 24 23:44:53 2021 +0100
11.3 @@ -0,0 +1,25 @@
11.4 +#pragma once
11.5 +
11.6 +#include <list>
11.7 +
11.8 +#include "page_mapper.h"
11.9 +
11.10 +/* Pipe paging support, maintaining the sequence of active regions or sections
11.11 + in a pipe. */
11.12 +
11.13 +class PipePaging
11.14 +{
11.15 +protected:
11.16 + std::list<PageMapper *> _regions;
11.17 +
11.18 +public:
11.19 + explicit PipePaging();
11.20 +
11.21 + virtual void add_region(PageMapper *mapper);
11.22 +
11.23 + virtual PageMapper *first_region();
11.24 +
11.25 + virtual PageMapper *next_region();
11.26 +};
11.27 +
11.28 +// vim: tabstop=4 expandtab shiftwidth=4
12.1 --- a/pager.cc Wed Mar 24 23:18:06 2021 +0100
12.2 +++ b/pager.cc Wed Mar 24 23:44:53 2021 +0100
12.3 @@ -7,12 +7,16 @@
12.4 Pager::Pager(PageMapper *mapper, flags_t flags)
12.5 : _start(0), _size(0), _mapper(mapper), _flags(flags)
12.6 {
12.7 - _mapper->attach();
12.8 + /* Some pagers may not be initialised with a mapper. */
12.9 +
12.10 + if (_mapper != NULL)
12.11 + _mapper->attach();
12.12 }
12.13
12.14 void Pager::close()
12.15 {
12.16 - _mapper->detach();
12.17 + if (_mapper != NULL)
12.18 + _mapper->detach();
12.19 }
12.20
12.21 /* Flush data to the file. */
13.1 --- a/pages.h Wed Mar 24 23:18:06 2021 +0100
13.2 +++ b/pages.h Wed Mar 24 23:44:53 2021 +0100
13.3 @@ -20,15 +20,15 @@
13.4
13.5 explicit Pages();
13.6
13.7 - Flexpage *remove();
13.8 + virtual Flexpage *remove();
13.9
13.10 - bool reserve(PageOwner *owner, Flexpage *flexpage);
13.11 + virtual bool reserve(PageOwner *owner, Flexpage *flexpage);
13.12
13.13 - Flexpage *flexpage();
13.14 + virtual Flexpage *flexpage();
13.15
13.16 - void queue(PageOwner *owner, Flexpage *flexpage);
13.17 + virtual void queue(PageOwner *owner, Flexpage *flexpage);
13.18
13.19 - void release(Flexpage *flexpage);
13.20 + virtual void release(Flexpage *flexpage);
13.21 };
13.22
13.23 // vim: tabstop=4 expandtab shiftwidth=4
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/pages_conserving.cc Wed Mar 24 23:44:53 2021 +0100
14.3 @@ -0,0 +1,98 @@
14.4 +#include "pages_conserving.h"
14.5 +
14.6 +PagesConserving::PagesConserving(Memory *memory, unsigned int increment)
14.7 +: Pages(memory), _increment(increment)
14.8 +{
14.9 +}
14.10 +
14.11 +PagesConserving::PagesConserving()
14.12 +: Pages(), _increment(1)
14.13 +{
14.14 +}
14.15 +
14.16 +
14.17 +
14.18 +/* Refuse to obtain a new flexpage directly. All flexpages must be obtained from
14.19 + the page queue. */
14.20 +
14.21 +Flexpage *PagesConserving::flexpage()
14.22 +{
14.23 + return NULL;
14.24 +}
14.25 +
14.26 +/* Pretend to queue an entry associating the given 'owner' and 'flexpage'.
14.27 + Since this collection "conserves" flexpages, they will not be queued unless
14.28 + completely unused. */
14.29 +
14.30 +void PagesConserving::queue(PageOwner *owner, Flexpage *flexpage)
14.31 +{
14.32 + (void) owner; (void) flexpage;
14.33 +}
14.34 +
14.35 +/* Pretend to reserve a flexpage already being used by 'owner' and 'flexpage'.
14.36 + Since flexpages are not queued when in use, there is nothing to reserve. */
14.37 +
14.38 +bool PagesConserving::reserve(PageOwner *owner, Flexpage *flexpage)
14.39 +{
14.40 + (void) owner; (void) flexpage;
14.41 + return true;
14.42 +}
14.43 +
14.44 +
14.45 +
14.46 +/* Decrease the provision of flexpages to pipes. */
14.47 +
14.48 +bool PagesConserving::decrease()
14.49 +{
14.50 + // NOTE: Need to remove flexpages from the queue.
14.51 + // NOTE: This might need to happen incrementally in case some pages are not
14.52 + // NOTE: back in the queue for whatever reason.
14.53 +
14.54 + return true;
14.55 +}
14.56 +
14.57 +/* Increase the provision of flexpages to pipes, returning whether allocation
14.58 + succeeded. */
14.59 +
14.60 +bool PagesConserving::increase()
14.61 +{
14.62 + unsigned int regions = _increment;
14.63 + std::list<Region *> allocated;
14.64 + std::list<Region *>::iterator it;
14.65 +
14.66 + /* Allocate regions for the defined increment value. */
14.67 +
14.68 + while (regions)
14.69 + {
14.70 + Region *r = _memory->region();
14.71 +
14.72 + /* Free all allocated regions if not all regions can be allocated. */
14.73 +
14.74 + if (r == NULL)
14.75 + {
14.76 + for (it = allocated.begin(); it != allocated.end(); it++)
14.77 + _memory->release(r);
14.78 +
14.79 + return false;
14.80 + }
14.81 +
14.82 + allocated.push_back(r);
14.83 + regions--;
14.84 + }
14.85 +
14.86 + /* Queue flexpages for the regions. */
14.87 +
14.88 + for (it = allocated.begin(); it != allocated.end(); it++)
14.89 + _queue.push(NULL, new Flexpage(*it));
14.90 +
14.91 + return true;
14.92 +}
14.93 +
14.94 +/* Return the allocation increment. */
14.95 +
14.96 +offset_t PagesConserving::allocation()
14.97 +{
14.98 + return _memory->region_size() * _increment;
14.99 +}
14.100 +
14.101 +// vim: tabstop=4 expandtab shiftwidth=4
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/pages_conserving.h Wed Mar 24 23:44:53 2021 +0100
15.3 @@ -0,0 +1,37 @@
15.4 +#pragma once
15.5 +
15.6 +#include "pages.h"
15.7 +
15.8 +
15.9 +
15.10 +/* A page collection where the pages are "conserved", meaning that they are not
15.11 + queued for reuse unless they are completely unused. */
15.12 +
15.13 +class PagesConserving : public Pages
15.14 +{
15.15 +protected:
15.16 + unsigned int _increment;
15.17 +
15.18 +public:
15.19 + explicit PagesConserving(Memory *memory, unsigned int increment=1);
15.20 +
15.21 + explicit PagesConserving();
15.22 +
15.23 + /* Specialised methods. */
15.24 +
15.25 + virtual Flexpage *flexpage();
15.26 +
15.27 + virtual void queue(PageOwner *owner, Flexpage *flexpage);
15.28 +
15.29 + virtual bool reserve(PageOwner *owner, Flexpage *flexpage);
15.30 +
15.31 + /* Memory control methods. */
15.32 +
15.33 + virtual bool decrease();
15.34 +
15.35 + virtual bool increase();
15.36 +
15.37 + virtual offset_t allocation();
15.38 +};
15.39 +
15.40 +// vim: tabstop=4 expandtab shiftwidth=4
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/pipe_opener_resource.cc Wed Mar 24 23:44:53 2021 +0100
16.3 @@ -0,0 +1,62 @@
16.4 +#include "pipe_opener_resource.h"
16.5 +#include "pipe_opener_server.h"
16.6 +#include "pipe_pager.h"
16.7 +#include "resource_server.h"
16.8 +
16.9 +
16.10 +
16.11 +/* Support for providing access to pipes. */
16.12 +
16.13 +PipeOpenerResource::PipeOpenerResource(PagesConserving *pages)
16.14 +: _pages(pages)
16.15 +{
16.16 +}
16.17 +
16.18 +int PipeOpenerResource::expected_items()
16.19 +{
16.20 + return PipeOpener_expected_items;
16.21 +}
16.22 +
16.23 +ipc_server_handler_type PipeOpenerResource::handler()
16.24 +{
16.25 + return (ipc_server_handler_type) handle_PipeOpener;
16.26 +}
16.27 +
16.28 +
16.29 +
16.30 +/* Pipe opener interface methods. */
16.31 +
16.32 +long PipeOpenerResource::pipe(l4_cap_idx_t *reader, l4_cap_idx_t *writer)
16.33 +{
16.34 + /* Both endpoints will employ a common paging coordinator. */
16.35 +
16.36 + PipePaging *paging = new PipePaging();
16.37 +
16.38 + /* Each endpoint will have its own pager. */
16.39 +
16.40 + /* NOTE: Failure to open an endpoint should invalidate both, plus the
16.41 + paging object. Also, any active server thread would need to be
16.42 + cancelled. */
16.43 +
16.44 + return open_endpoint(paging, false, reader) || open_endpoint(paging, true, writer);
16.45 +}
16.46 +
16.47 +long PipeOpenerResource::open_endpoint(PipePaging *paging, bool writer, l4_cap_idx_t *endpoint)
16.48 +{
16.49 + PipePager *pager = new PipePager(_pages, paging, writer);
16.50 +
16.51 + /* Start the endpoint server in a new thread.
16.52 + If the thread does not start, the resource should be finalised. */
16.53 +
16.54 + ResourceServer server(pager);
16.55 + long err = server.start_thread();
16.56 +
16.57 + /* Return the server capability to the caller. */
16.58 +
16.59 + if (!err)
16.60 + *endpoint = server.config()->server;
16.61 +
16.62 + return err;
16.63 +}
16.64 +
16.65 +// vim: tabstop=4 expandtab shiftwidth=4
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/pipe_opener_resource.h Wed Mar 24 23:44:53 2021 +0100
17.3 @@ -0,0 +1,34 @@
17.4 +#pragma once
17.5 +
17.6 +#include "pages_conserving.h"
17.7 +#include "pipe_opener_interface.h"
17.8 +#include "pipe_paging.h"
17.9 +#include "resource.h"
17.10 +
17.11 +/* Support for providing access to pipes. */
17.12 +
17.13 +class PipeOpenerResource : public Resource, public PipeOpener
17.14 +{
17.15 +protected:
17.16 + PagesConserving *_pages;
17.17 +
17.18 + long open_endpoint(PipePaging *paging, bool writer, l4_cap_idx_t *endpoint);
17.19 +
17.20 +public:
17.21 + explicit PipeOpenerResource(PagesConserving *pages);
17.22 +
17.23 + /* Server details. */
17.24 +
17.25 + int expected_items();
17.26 +
17.27 + ipc_server_handler_type handler();
17.28 +
17.29 + void *interface()
17.30 + { return static_cast<PipeOpener *>(this); }
17.31 +
17.32 + /* PipeOpener interface methods. */
17.33 +
17.34 + long pipe(l4_cap_idx_t *reader, l4_cap_idx_t *writer);
17.35 +};
17.36 +
17.37 +// vim: tabstop=4 expandtab shiftwidth=4
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/pipe_pager.cc Wed Mar 24 23:44:53 2021 +0100
18.3 @@ -0,0 +1,125 @@
18.4 +#include "pipe_pager.h"
18.5 +#include "pipe_object_server.h"
18.6 +
18.7 +/* Initialise a pager for a pipe with a shared page mapper for moderating
18.8 + access to loaded pages. At first, no mapper will be configured: this must be
18.9 + done by requesting a region. */
18.10 +
18.11 +PipePager::PipePager(PagesConserving *pages, PipePaging *paging, bool writer)
18.12 +: Pager(NULL, writer ? L4_FPAGE_RW : L4_FPAGE_RO),
18.13 + _pages(pages), _paging(paging), _writer(writer)
18.14 +{
18.15 + /* Set the size of each paged region to the amount allocation for such
18.16 + regions. */
18.17 +
18.18 + _size = _pages->allocation();
18.19 +}
18.20 +
18.21 +int PipePager::expected_items()
18.22 +{
18.23 + return PipeObject_expected_items;
18.24 +}
18.25 +
18.26 +ipc_server_handler_type PipePager::handler()
18.27 +{
18.28 + return (ipc_server_handler_type) handle_PipeObject;
18.29 +}
18.30 +
18.31 +
18.32 +
18.33 +/* Support paging. */
18.34 +
18.35 +long PipePager::map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region)
18.36 +{
18.37 + return Pager::map(offset, hot_spot, flags, region);
18.38 +}
18.39 +
18.40 +
18.41 +
18.42 +/* Return details of the current region. */
18.43 +
18.44 +long PipePager::current_region(offset_t *populated_size, offset_t *size)
18.45 +{
18.46 + if (_mapper != NULL)
18.47 + {
18.48 + *populated_size = _mapper->get_data_size();
18.49 + *size = _size;
18.50 + return L4_EOK;
18.51 + }
18.52 + else
18.53 + return -L4_EIO;
18.54 +}
18.55 +
18.56 +/* Obtain the next region and its details. */
18.57 +
18.58 +long PipePager::next_region(offset_t *populated_size, offset_t *size)
18.59 +{
18.60 + /* Obtain a new region if writing. */
18.61 +
18.62 + if (_writer)
18.63 + return next_region_for_writer(populated_size, size);
18.64 + else
18.65 + return next_region_for_reader(populated_size, size);
18.66 +}
18.67 +
18.68 +long PipePager::next_region_for_reader(offset_t *populated_size, offset_t *size)
18.69 +{
18.70 + /* Obtain the next region if a current region is defined. */
18.71 +
18.72 + if (_mapper != NULL)
18.73 + {
18.74 + PageMapper *mapper = _paging->next_region();
18.75 +
18.76 + /* Return an error if no next region currently exists. */
18.77 +
18.78 + if (mapper == NULL)
18.79 + return -L4_EIO;
18.80 +
18.81 + /* Detach and discard the current page mapper. */
18.82 +
18.83 + _mapper->detach();
18.84 + delete _mapper;
18.85 +
18.86 + _mapper = mapper;
18.87 + }
18.88 +
18.89 + /* Obtain the first region if no mapper is defined. */
18.90 +
18.91 + else
18.92 + _mapper = _paging->first_region();
18.93 +
18.94 + /* Return the details of the now-current region. */
18.95 +
18.96 + return current_region(populated_size, size);
18.97 +}
18.98 +
18.99 +long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size)
18.100 +{
18.101 + /* Set the populated size before moving on. */
18.102 +
18.103 + if (_mapper != NULL)
18.104 + _mapper->set_data_size(*populated_size);
18.105 +
18.106 + /* A guaranteed amount of memory is reserved for the pipe. */
18.107 +
18.108 + if (!_pages->increase())
18.109 + return -L4_ENOMEM;
18.110 +
18.111 + /* Set the page mapper for the region. */
18.112 +
18.113 + _mapper = new PageMapper(&_accessor, _pages);
18.114 + _mapper->attach();
18.115 +
18.116 + /* Record the mapper as the latest region in the accessor. */
18.117 +
18.118 + _paging->add_region(_mapper);
18.119 +
18.120 + /* Set the region size to the allocated amount. */
18.121 +
18.122 + *size = _size;
18.123 + *populated_size = 0;
18.124 +
18.125 + return L4_EOK;
18.126 +}
18.127 +
18.128 +// vim: tabstop=4 expandtab shiftwidth=4
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/pipe_pager.h Wed Mar 24 23:44:53 2021 +0100
19.3 @@ -0,0 +1,48 @@
19.4 +#pragma once
19.5 +
19.6 +#include "pipe_accessor.h"
19.7 +#include "pipe_object_interface.h"
19.8 +#include "pipe_paging.h"
19.9 +#include "pager.h"
19.10 +#include "pages_conserving.h"
19.11 +
19.12 +/* A pager abstraction for a pipe. */
19.13 +
19.14 +class PipePager : public Pager, public PipeObject
19.15 +{
19.16 +protected:
19.17 + PipeAccessor _accessor;
19.18 + PagesConserving *_pages;
19.19 + PipePaging *_paging;
19.20 + bool _writer;
19.21 +
19.22 + /* Helper methods. */
19.23 +
19.24 + virtual long next_region_for_reader(offset_t *populated_size, offset_t *size);
19.25 +
19.26 + virtual long next_region_for_writer(offset_t *populated_size, offset_t *size);
19.27 +
19.28 +public:
19.29 + explicit PipePager(PagesConserving *pages, PipePaging *paging, bool writer);
19.30 +
19.31 + /* Server details. */
19.32 +
19.33 + int expected_items();
19.34 +
19.35 + ipc_server_handler_type handler();
19.36 +
19.37 + void *interface()
19.38 + { return static_cast<PipeObject *>(this); }
19.39 +
19.40 + /* Pager methods. */
19.41 +
19.42 + virtual long map(unsigned long offset, l4_addr_t hot_spot, flags_t flags, l4_snd_fpage_t *region);
19.43 +
19.44 + /* Pipe methods. */
19.45 +
19.46 + virtual long current_region(offset_t *populated_size, offset_t *size);
19.47 +
19.48 + virtual long next_region(offset_t *populated_size, offset_t *size);
19.49 +};
19.50 +
19.51 +// vim: tabstop=4 expandtab shiftwidth=4