# HG changeset patch # User Paul Boddie # Date 1618521317 -7200 # Node ID b6dab1e89e3c6b1bcd42bee06c4ec669a60e94ea # Parent bf981cb9a709b3ef7d8b26138cfa998a4e37b6da Reorganised into a collection of packages for each area of functionality. diff -r bf981cb9a709 -r b6dab1e89e3c Control --- a/Control Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -requires: libstdc++ libc libipc -provides: dstest -maintainer: paul@boddie.org.uk diff -r bf981cb9a709 -r b6dab1e89e3c Makefile --- a/Makefile Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +0,0 @@ -PKGDIR ?= . -L4DIR ?= $(PKGDIR)/../.. - -TARGET = \ - dstest_block_client dstest_block_client_simple \ - dstest_host_client \ - dstest_pipe_client \ - dstest_test_client \ - dstest_block_server \ - dstest_host_server \ - dstest_pipe_server \ - dstest_test_server - -MODE = static - -# Locations for interface input and generated output. - -IDL_DIR = $(L4DIR)/pkg/libsystypes/idl -IDL_MK_DIR = $(L4DIR)/idl4re/mk -IDL_BUILD_DIR = . -IDL_EXPORT_DIR = . - -include $(IDL_MK_DIR)/idl.mk - -# Compound interfaces. - -mapped_file_object_NAME = MappedFileObject -mapped_file_object_INTERFACES = dataspace file mapped_file - -opener_context_object_NAME = OpenerContextObject -opener_context_object_INTERFACES = dataspace opener_context - -pipe_object_NAME = PipeObject -pipe_object_INTERFACES = dataspace pipe - -COMP_INTERFACES_CC = mapped_file_object opener_context_object pipe_object - -# Individual interfaces. - -CLIENT_INTERFACES_CC = dataspace file mapped_file opener opener_context pipe pipe_opener - -SERVER_INTERFACES_CC = opener pipe_opener $(call common_interfaces,$(COMP_INTERFACES_CC)) - -# Generated and plain source files. - -CLIENT_INTERFACES_SRC_CC = $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC)) - -SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC) $(COMP_INTERFACES_CC)) - -COMMON_SRC_CC = memory/memory_utils.cc - -PLAIN_SRC_CC_dstest_block_client = tests/dstest_block_client.cc client/file.cc - -PLAIN_SRC_CC_dstest_block_client_simple = tests/dstest_block_client_simple.cc client/client.cc client/file.cc - -PLAIN_SRC_CC_dstest_host_client = tests/dstest_host_client.cc client/file.cc - -PLAIN_SRC_CC_dstest_pipe_client = tests/dstest_pipe_client.cc client/file.cc - -PLAIN_SRC_CC_dstest_test_client = tests/dstest_test_client.cc client/file.cc - -PLAIN_SRC_CC_common_server = \ - generic/accessor.cc generic/pager.cc \ - generic/resource_server.cc \ - mapping/access_map.cc mapping/flexpage.cc mapping/ipc.cc \ - memory/memory_incremental.cc mapping/page_mapper.cc \ - memory/memory_preallocated.cc memory/region.cc \ - pages/page_queue.cc pages/page_queue_partitioned.cc \ - pages/page_queue_shared.cc pages/pages.cc - -PLAIN_SRC_CC_common_file_server = \ - files/file_pager.cc files/file_paging.cc \ - files/opener_resource.cc files/opener_context_resource.cc \ - generic/simple_pager.cc - -PLAIN_SRC_CC_dstest_block_server = \ - $(PLAIN_SRC_CC_common_server) \ - $(PLAIN_SRC_CC_common_file_server) \ - files/block_file_accessor.cc files/block_file_opener.cc \ - files/host_file_accessor.cc files/host_file_opener.cc \ - servers/block_file_server.cc - -PLAIN_SRC_CC_dstest_host_server = \ - $(PLAIN_SRC_CC_common_server) \ - $(PLAIN_SRC_CC_common_file_server) \ - files/host_file_accessor.cc files/host_file_opener.cc \ - servers/host_file_server.cc - -PLAIN_SRC_CC_dstest_pipe_server = \ - $(PLAIN_SRC_CC_common_server) \ - pipes/pipe_opener_resource.cc pipes/pipe_pager.cc \ - pipes/pipe_accessor.cc pipes/pipe_paging.cc \ - servers/pipe_server.cc - -PLAIN_SRC_CC_dstest_test_server = \ - $(PLAIN_SRC_CC_common_server) \ - $(PLAIN_SRC_CC_common_file_server) \ - files/test_file_accessor.cc files/test_file_opener.cc \ - servers/test_file_server.cc - -# Normal definitions. - -SRC_CC_dstest_block_client = \ - $(CLIENT_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_block_client) \ - $(COMMON_SRC_CC) - -SRC_CC_dstest_block_client_simple = \ - $(CLIENT_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_block_client_simple) \ - $(COMMON_SRC_CC) - -SRC_CC_dstest_host_client = \ - $(CLIENT_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_host_client) \ - $(COMMON_SRC_CC) - -SRC_CC_dstest_pipe_client = \ - $(CLIENT_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_pipe_client) \ - $(COMMON_SRC_CC) - -SRC_CC_dstest_test_client = \ - $(CLIENT_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_test_client) \ - $(COMMON_SRC_CC) - -SRC_CC_dstest_block_server = \ - $(SERVER_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_block_server) \ - $(COMMON_SRC_CC) - -SRC_CC_dstest_host_server = \ - $(SERVER_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_host_server) \ - $(COMMON_SRC_CC) - -SRC_CC_dstest_pipe_server = \ - $(SERVER_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_pipe_server) \ - $(COMMON_SRC_CC) - -SRC_CC_dstest_test_server = \ - $(SERVER_INTERFACES_SRC_CC) \ - $(PLAIN_SRC_CC_dstest_test_server) \ - $(COMMON_SRC_CC) - -REQUIRES_LIBS = l4re_c-util libipc libstdc++ libsystypes - -PRIVATE_INCDIR = $(PKGDIR) $(PKGDIR)/client \ - $(PKGDIR)/files $(PKGDIR)/generic \ - $(PKGDIR)/mapping $(PKGDIR)/memory \ - $(PKGDIR)/pages $(PKGDIR)/pipes \ - $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR) - -include $(L4DIR)/mk/prog.mk -include $(IDL_MK_DIR)/interface_rules.mk - -$(PLAIN_SRC_CC_dstest_block_client): $(CLIENT_INTERFACES_SRC_CC) - -$(PLAIN_SRC_CC_dstest_block_client_simple): $(CLIENT_INTERFACES_SRC_CC) - -$(PLAIN_SRC_CC_dstest_host_client): $(CLIENT_INTERFACES_SRC_CC) - -$(PLAIN_SRC_CC_dstest_pipe_client): $(CLIENT_INTERFACES_SRC_CC) - -$(PLAIN_SRC_CC_dstest_test_client): $(CLIENT_INTERFACES_SRC_CC) - -$(PLAIN_SRC_CC_dstest_block_server): $(SERVER_INTERFACES_SRC_CC) - -$(PLAIN_SRC_CC_dstest_host_server): $(SERVER_INTERFACES_SRC_CC) - -$(PLAIN_SRC_CC_dstest_pipe_server): $(SERVER_INTERFACES_SRC_CC) - -$(PLAIN_SRC_CC_dstest_test_server): $(SERVER_INTERFACES_SRC_CC) diff -r bf981cb9a709 -r b6dab1e89e3c client/client.cc --- a/client/client.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,390 +0,0 @@ -/* - * Filesystem client functions. - * - * Copyright (C) 2018, 2019, 2020, 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include - -#include -#include - -#include "client.h" - - - -/* Default size of pipe regions. */ - -const offset_t DEFAULT_PIPE_SIZE = 4096; - - - -/* Close a filesystem object. */ - -void client_close(file_t *file) -{ - if (file == NULL) - return; - - file_close(file); - free(file); -} - - - -/* Open a filesystem object. */ - -file_t *client_open(const char *name, flags_t flags) -{ - file_t *file = (file_t *) malloc(sizeof(file_t)); - - if (file == NULL) - return NULL; - - l4_cap_idx_t server = l4re_env_get_cap("server"); - - if (file_open(file, name, flags, server)) - { - free(file); - return NULL; - } - - return file; -} - - - -/* Open a pipe object. */ - -long client_pipe(file_t **reader, file_t **writer) -{ - *reader = (file_t *) malloc(sizeof(file_t)); - - if (*reader == NULL) - return -L4_ENOMEM; - - *writer = (file_t *) malloc(sizeof(file_t)); - - if (*writer == NULL) - { - free(*reader); - return -L4_ENOMEM; - } - - l4_cap_idx_t server = l4re_env_get_cap("pipes"); - - long err = pipe_open(DEFAULT_PIPE_SIZE, *reader, *writer, server); - - if (err) - { - free(*reader); - free(*writer); - } - - return err; -} - - - -/* Flush data conditionally to the filesystem object. */ - -static long _flush(file_t *file, offset_t position) -{ - long err; - - /* Where the position is outside the current region, re-map. */ - - if ((position < file->start_pos) || (position >= file->end_pos)) - { - if (file->can_mmap) - { - if (file_mmap(file, position, file_span(file))) - return -L4_EIO; - } - - /* Strict conditions for region navigation in pipes. */ - - else if ((position != file->end_pos) || - (client_next_region(file) == NULL)) - return -L4_EIO; - } - - /* Otherwise, flush any written data in the current region and update the - file size details. */ - - else - { - err = client_flush(file); - - if (err) - return err; - } - - /* Update the current data offset. */ - - file->data_current = position - file->start_pos; - return L4_EOK; -} - - - -/* Flush data explicitly to the filesystem object. */ - -long client_flush(file_t *file) -{ - if (file == NULL) - return -L4_EINVAL; - - /* Flush and retain most buffer settings. */ - - return file_flush(file); -} - - - -/* Map a memory region to a file. */ - -void *client_mmap(file_t *file, offset_t position, offset_t length) -{ - if ((file == NULL) || (file_mmap(file, position, length))) - return NULL; - - return file->memory; -} - - - -/* Obtain the current region of a pipe. */ - -void *client_current_region(file_t *file) -{ - if ((file == NULL) || (pipe_current(file))) - return NULL; - - return file->memory; -} - - - -/* Obtain the next region of a pipe. */ - -void *client_next_region(file_t *file) -{ - if ((file == NULL) || (pipe_next(file))) - return NULL; - - return file->memory; -} - - - -/* Read from the filesystem object into the buffer provided. */ - -offset_t client_read(file_t *file, void *buf, offset_t count) -{ - if (file == NULL) - return 0; - - /* Amount available in the descriptor buffer already. */ - - offset_t available = file_data_available(file); - offset_t to_transfer, total = 0; - - while (count > 0) - { - /* If there is no data, try and obtain more data. */ - - if (!available) - { - /* Flush any unwritten data, preparing to read from the file position at - the end of the data, and returning if no new data is available. */ - - if (_flush(file, file_data_end_position(file))) - break; - - available = file_data_available(file); - - if (!available) - break; - } - - /* Transfer data into the supplied buffer. */ - - to_transfer = available <= count ? available : count; - - file_data_read(file, (char *) buf, to_transfer); - - /* Update counters. */ - - available -= to_transfer; - - count -= to_transfer; - total += to_transfer; - - buf = ((char *) buf + to_transfer); - } - - return total; -} - - - -/* Ensure that the buffer can provide the needed data. */ - -offset_t client_seek(file_t *file, offset_t offset, int whence) -{ - if (file == NULL) - return 0; - - offset_t position, current = file_data_current_position(file), change; - - switch (whence) - { - case SEEK_SET: - position = offset; - break; - - case SEEK_CUR: - position = current + offset; - break; - - case SEEK_END: - position = file->size + offset; - break; - - default: - /* NOTE: Set errno to EINVAL. */ - return -1; - } - - /* Retain the current position if unchanged. */ - - if (position == current) - return position; - - /* Move forward in the file. */ - - if (position > current) - { - change = position - current; - - /* Move towards the end of available data. - Request new data if not enough is available. */ - - if (change <= file_data_available(file)) - { - file->data_current += change; - return position; - } - } - - /* Move backward in the file. */ - - else - { - change = current - position; - - /* Move towards the start of available data. - Request new data if moving beyond the start of the data. */ - - if (change <= file->data_current) - { - file->data_current -= change; - return position; - } - } - - /* Handle unwritten data and reset the buffer for reading. */ - - _flush(file, position); - return position; -} - - - -long client_tell(file_t *file) -{ - if (file == NULL) - return -L4_EINVAL; - - return file_data_current_position(file); -} - - - -/* Write to the filesystem object from the buffer provided. */ - -offset_t client_write(file_t *file, const void *buf, offset_t count) -{ - if (file == NULL) - return 0; - - /* Attempt to ensure that the file can accept the amount of data to be - written. This may not resize to the needed amount if a file has a fixed - size, but data will still be written to any available space. */ - - offset_t needed_size = file_data_current_position(file) + count; - - if (file->size < needed_size) - { - file_resize(file, needed_size); - - if (file->size < needed_size) - count = file->size - file_data_current_position(file); - } - - /* Space remaining in the descriptor buffer. */ - - offset_t space = file_data_space(file); - offset_t to_transfer, total = 0; - - while (count > 0) - { - /* If no space is available, try and send data, reset the buffer. */ - - if (!space) - { - /* Flush any unwritten data and continue writing from the current data - position. */ - - if (_flush(file, file_data_current_position(file))) - break; - - space = file_data_space(file); - } - - /* Transfer data into the supplied buffer. */ - - to_transfer = space <= count ? space : count; - - file_data_write(file, (char *) buf, to_transfer); - - /* Update counters. */ - - space -= to_transfer; - - count -= to_transfer; - total += to_transfer; - - buf = ((char *) buf + to_transfer); - } - - return total; -} - -// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c client/client.h --- a/client/client.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Filesystem client functions. - * - * Copyright (C) 2018, 2019, 2020, 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "file.h" - -EXTERN_C_BEGIN - -/* File operations. */ - -void client_close(file_t *file); -file_t *client_open(const char *name, flags_t flags); -long client_pipe(file_t **reader, file_t **writer); - -/* File and region operations. */ - -long client_flush(file_t *file); -void *client_mmap(file_t *file, offset_t position, offset_t length); - -/* Pipe region operations. */ - -void *client_current_region(file_t *file); -void *client_next_region(file_t *file); - -/* File data operations. */ - -offset_t client_read(file_t *file, void *buf, offset_t count); -offset_t client_write(file_t *file, const void *buf, offset_t count); - -/* File navigation operations. */ - -offset_t client_seek(file_t *file, offset_t offset, int whence); -long client_tell(file_t *file); - -EXTERN_C_END - -// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c client/file.cc --- a/client/file.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,452 +0,0 @@ -/* - * File access convenience functions. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include -#include - -#include - -#include "dataspace_client.h" -#include "file_client.h" -#include "opener_client.h" -#include "opener_context_client.h" -#include "pipe_client.h" -#include "pipe_opener_client.h" -#include "mapped_file_client.h" - -#include "file.h" - - - -/* Update the extent of the file in a region using the region start and end - positions and the file size. */ - -static void _update_extent(file_t *file) -{ - /* Handle files ending after or within the region. */ - - if (file->size > file->start_pos) - { - if (file->size > file->end_pos) - file->data_end = file->end_pos - file->start_pos; - else - file->data_end = file->size - file->start_pos; - } - - /* Handle files ending before the region. */ - - else - file->data_end = 0; -} - - - -/* Initialise the given file structure. */ - -void file_init(file_t *file) -{ - file->memory = NULL; - file->ref = L4_INVALID_CAP; - file->start_pos = 0; - file->end_pos = 0; - file->data_end = 0; - file->data_current = 0; - file->can_mmap = 1; -} - - - -/* Release resources for the given file. */ - -void file_close(file_t *file) -{ - if (l4_is_valid_cap(file->ref)) - ipc_cap_free_um(file->ref); - - if (file->memory != NULL) - ipc_detach_dataspace(file->memory); - - file_init(file); -} - -/* Open a file using the given structure, indicating the filename and - filesystem server. The file_mmap function should be used to obtain access to - memory providing file data. This is a convenience function invoking - file_context and file_context_open. */ - -long file_open(file_t *file, const char *filename, flags_t flags, l4_cap_idx_t server) -{ - file_t context; - long err; - - err = file_context(&context, server); - if (err) - return err; - - if (!file_string_set(&context, filename, 0, NULL)) - return -L4_ENOMEM; - - err = file_context_open(file, flags, &context); - - /* Close the context, although a separate mechanism could permit contexts to - open several files. */ - - file_close(&context); - return err; -} - - - -/* Initialise a file structure for a context obtained from the given server - attaching memory to communicate filename information. */ - -long file_context(file_t *file, l4_cap_idx_t server) -{ - if (l4_is_invalid_cap(server)) - return -L4_EINVAL; - - client_Opener opener(server); - offset_t size; - flags_t flags; - long err; - - file_init(file); - - err = opener.context(&file->ref); - if (err) - return err; - - client_Dataspace context_ds(file->ref); - - err = context_ds.info(&size, &flags); - if (err) - return err; - - file->start_pos = 0; - file->end_pos = size; - - return ipc_attach_dataspace(file->ref, size, (void **) &file->memory); -} - -/* Open a file using the given structure and context. */ - -long file_context_open(file_t *file, flags_t flags, file_t *context) -{ - client_OpenerContext openercontext(context->ref); - file_init(file); - return openercontext.open(flags, &file->size, &file->ref); -} - - - -/* Flush populated data and obtain an updated file size and populated data - details. */ - -long file_flush(file_t *file) -{ - client_File _file(file->ref); - long err = _file.flush(file->data_current, &file->size); - - if (err) - return err; - - _update_extent(file); - - return L4_EOK; -} - -/* Map a region of the given file to a memory region, obtaining an updated file - size and populated data details. Unmap any previously mapped region. */ - -long file_mmap(file_t *file, offset_t position, offset_t length) -{ - char *memory = file->memory; - client_MappedFile mapped_file(file->ref); - long err = mapped_file.mmap(position, length, &file->start_pos, - &file->end_pos, &file->size); - - if (err) - return err; - - _update_extent(file); - - err = ipc_attach_dataspace(file->ref, file_span(file), (void **) &file->memory); - if (err) - return err; - - if (memory != NULL) - ipc_detach_dataspace(memory); - - return L4_EOK; -} - -/* Resize a file, obtaining updated file size and populated data details. */ - -long file_resize(file_t *file, offset_t size) -{ - client_File _file(file->ref); - offset_t file_size = size; - long err = _file.resize(&file_size); - - if (err) - return err; - - file->size = file_size; - _update_extent(file); - return L4_EOK; -} - - - -/* Return the amount of data in the mapped region for the given file. */ - -offset_t file_populated_span(file_t *file) -{ - offset_t size = file_span(file); - return (file->data_end < size) ? file->data_end : size; -} - -/* Return the size of the mapped region for the given file. */ - -offset_t file_span(file_t *file) -{ - return file->end_pos - file->start_pos; -} - - - -/* Get a pointer to any terminated string at the given offset or NULL if the - data from offset is not terminated. */ - -char *file_string_get(file_t *file, offset_t offset) -{ - offset_t limit = file_span(file) - offset; - - if (strnlen(file->memory + offset, limit) < limit) - return file->memory + offset; - else - return NULL; -} - -/* Copy a string to the mapped region at the given offset, returning 1 (true) - where all characters were copied, 0 (false) otherwise. The precise number of - characters copied, excluding the zero terminator is provided via the written - parameter if it is not specified as NULL. */ - -int file_string_set(file_t *file, const char *data, offset_t offset, - offset_t *written) -{ - offset_t i, pos, limit = file_span(file); - - /* Do not attempt to copy data with an invalid offset. */ - - if (offset >= limit) - { - if (written != NULL) - *written = 0; - return 0; - } - - /* Copy the data to the given offset, stopping at the end of the region. */ - - for (i = 0, pos = offset; pos < limit; i++, pos++) - { - file->memory[pos] = data[i]; - - /* Terminator written, can return immediately. */ - - if (!data[i]) - { - if (written != NULL) - *written = pos - offset; - return 1; - } - } - - /* Terminate the incomplete string at the end of the region. */ - - file->memory[limit - 1] = '\0'; - if (written != NULL) - *written = limit - 1 - offset; - return 0; -} - - - -/* Return the number of remaining populated bytes in the region. */ - -offset_t file_data_available(file_t *file) -{ - return file_populated_span(file) - file->data_current; -} - -/* Return the current data offset in the region. */ - -char *file_data_current(file_t *file) -{ - return file->memory + file->data_current; -} - -/* Return the current access position in the file. */ - -offset_t file_data_current_position(file_t *file) -{ - return file->start_pos + file->data_current; -} - -/* Return the position of the end of the populated bytes in the region. */ - -offset_t file_data_end_position(file_t *file) -{ - return file->start_pos + file->data_end; -} - -/* Return the amount of remaining space in the region. */ - -offset_t file_data_space(file_t *file) -{ - return file_span(file) - file->data_current; -} - - - -/* Copy data to the given buffer from the current data position, updating the - position. */ - -void file_data_read(file_t *file, char *buf, size_t to_transfer) -{ - memcpy(buf, file_data_current(file), to_transfer); - - /* Update position details. */ - - file->data_current += to_transfer; -} - -/* Copy data from the given buffer to the current data position, updating the - position and the extent of populated data if this was exceeded. */ - -void file_data_write(file_t *file, char *buf, size_t to_transfer) -{ - memcpy(file_data_current(file), buf, to_transfer); - - /* Update position details. */ - - file->data_current += to_transfer; - - if (file->data_current > file->data_end) - file->data_end = file->data_current; -} - - - -/* Open two pipe endpoints using the given pipe server. */ - -long pipe_open(offset_t size, file_t *reader, file_t *writer, l4_cap_idx_t server) -{ - if (l4_is_invalid_cap(server)) - return -L4_EINVAL; - - client_PipeOpener opener(server); - - file_init(reader); - file_init(writer); - - /* Pipes can usually only be accessed via region navigation. */ - - reader->can_mmap = 0; - writer->can_mmap = 0; - - long err = opener.pipe(size, &reader->ref, &writer->ref); - if (err) - return err; - - err = pipe_next(writer) || pipe_next(reader); - - if (err) - { - file_close(reader); - file_close(writer); - } - - return err; -} - -/* Access the current region for a pipe endpoint. */ - -long pipe_current(file_t *pipe) -{ - client_Pipe _pipe(pipe->ref); - long err = _pipe.current_region(&pipe->data_end, &pipe->size); - char *memory = pipe->memory; - - if (err) - return err; - - pipe->end_pos = pipe->size; - - err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory); - if (err) - return err; - - if (memory != NULL) - ipc_detach_dataspace(memory); - - return L4_EOK; -} - -/* Access the next region for a pipe endpoint, updating the eventual size of - the current region. */ - -long pipe_next(file_t *pipe) -{ - client_Pipe _pipe(pipe->ref); - long err = _pipe.next_region(&pipe->data_end, &pipe->size); - char *memory = pipe->memory; - - if (err) - return err; - - pipe->end_pos = pipe->size; - - err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory); - if (err) - return err; - - if (memory != NULL) - ipc_detach_dataspace(memory); - - return L4_EOK; -} - -/* Set the size of the written region. */ - -long pipe_written(file_t *pipe, offset_t size) -{ - if (size <= pipe->size) - { - pipe->data_end = size; - return L4_EOK; - } - else - return -L4_EINVAL; -} - -// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c client/file.h --- a/client/file.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* - * File access convenience functions and types. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include - -#include - - - -EXTERN_C_BEGIN - -/* File access abstraction. */ - -typedef struct -{ - /* File object reference. */ - - l4_cap_idx_t ref; - - /* Mapped memory accessing a file region. */ - - char *memory; - - /* File region parameters. */ - - offset_t start_pos, end_pos; /* start and end positions of region */ - offset_t data_end; /* amount/extent of data in the region */ - offset_t data_current; /* client access offset */ - - /* Total size of file. */ - - offset_t size; - - /* Arbitrary memory mapping support. */ - - int can_mmap; - -} file_t; - - - -/* File operations. */ - -void file_close(file_t *file); -long file_open(file_t *file, const char *filename, flags_t flags, l4_cap_idx_t server); - -/* File lifecycle operations. */ - -long file_context(file_t *file, l4_cap_idx_t server); -long file_context_open(file_t *file, flags_t flags, file_t *context); -void file_init(file_t *file); - -/* File and region operations. */ - -long file_flush(file_t *file); -long file_mmap(file_t *file, offset_t position, offset_t length); -long file_resize(file_t *file, offset_t size); - -/* File and region properties. */ - -offset_t file_populated_span(file_t *file); -offset_t file_span(file_t *file); - -/* Convenience functions. */ - -char *file_string_get(file_t *file, offset_t offset); -int file_string_set(file_t *file, const char *data, offset_t offset, offset_t *written); - -/* Client data functions. */ - -offset_t file_data_available(file_t *file); -char *file_data_current(file_t *file); -offset_t file_data_current_position(file_t *file); -offset_t file_data_end_position(file_t *file); -offset_t file_data_space(file_t *file); - -/* Client data transfer functions. */ - -void file_data_read(file_t *file, char *buf, size_t to_transfer); -void file_data_write(file_t *file, char *buf, size_t to_transfer); - - - -/* Pipe operations. */ - -long pipe_open(offset_t size, file_t *reader, file_t *writer, l4_cap_idx_t server); - -/* Pipe region operations. */ - -long pipe_current(file_t *pipe); -long pipe_next(file_t *pipe); -long pipe_written(file_t *pipe, offset_t size); - -EXTERN_C_END - -// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c files/block_file_accessor.cc --- a/files/block_file_accessor.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -/* - * A file accessor employing a rewritable memory area. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include - -#include - -#include "block_file_accessor.h" - - - -BlockFileAccessor::BlockFileAccessor(const char *path, fileid_t fileid) -: Accessor(fileid) -{ - /* Obtain the size of the file. */ - - struct stat buf; - - if (stat(path, &buf)) - { - _size = 0; - return; - } - - /* Allocate memory. */ - - _size = buf.st_size; - _data = (char *) malloc(_size); - - if (_data == NULL) - return; - - /* Load the file into memory and initialise the size. */ - - FILE *fp = fopen(path, "r"); - - if (fp == NULL) - { - free(_data); - return; - } - - _size = fread(_data, sizeof(char), _size, fp); - - fclose(fp); -} - -/* Update the size of the file. */ - -void BlockFileAccessor::set_size(offset_t size) -{ - void *new_data = realloc(_data, size); - - if (new_data != NULL) - { - _data = (char *) new_data; - - if (size > _size) - memset(_data + _size, 0, size - _size); - - Accessor::set_size(size); - } -} - -/* Data transfer helper methods. */ - -/* Fill the populated portion of a flexpage. */ - -void BlockFileAccessor::fill_populated(Flexpage *flexpage) -{ - offset_t filepos = flexpage->base_offset; - offset_t addr = flexpage->base_addr; - offset_t populated_size = std::min(flexpage->size, _size - filepos); - - /* Tag the region with file state. */ - - flexpage->region->fill(fileid, filepos); - - /* Fill the region with file content. */ - - memcpy((void *) addr, _data + filepos, populated_size); - - /* Pad the flexpage with zero. */ - - if (populated_size < flexpage->size) - memset((void *) (addr + populated_size), 0, flexpage->size - populated_size); -} - -/* Flush the populated portion of a flexpage. */ - -void BlockFileAccessor::flush_populated(Flexpage *flexpage) -{ - offset_t filepos = flexpage->base_offset; - offset_t addr = flexpage->base_addr; - offset_t populated_size = std::min(flexpage->size, _size - filepos); - - /* Remove the file state tag from the region. */ - - flexpage->region->flush(); - - /* Copy the populated region to the block memory. */ - - memcpy((void *) (_data + filepos), (const void *) addr, populated_size); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/block_file_accessor.h --- a/files/block_file_accessor.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * A file accessor employing a rewritable memory area. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "accessor.h" - - - -/* A block file accessor, providing flexpages corresponding to the regions of - loaded files. */ - -class BlockFileAccessor : public Accessor -{ -protected: - char *_data; - - /* Data transfer helper methods. */ - - virtual void fill_populated(Flexpage *flexpage); - - virtual void flush_populated(Flexpage *flexpage); - -public: - explicit BlockFileAccessor(const char *path, fileid_t fileid); - - virtual void set_size(offset_t size); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/block_file_opener.cc --- a/files/block_file_opener.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,37 +0,0 @@ -/* - * An opener for a file employing a rewritable memory area. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "block_file_accessor.h" -#include "block_file_opener.h" - -/* Return a new accessor for 'fileid'. */ - -Accessor *BlockFileOpener::make_accessor(fileid_t fileid) -{ - FilePaths::iterator found = _paths.find(fileid); - - if (found != _paths.end()) - return new BlockFileAccessor(found->second, fileid); - else - return NULL; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/block_file_opener.h --- a/files/block_file_opener.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * An opener for a file employing a rewritable memory area. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "host_file_opener.h" - - - -/* Support for providing access to files. */ - -class BlockFileOpener : public HostFileOpener -{ -protected: - /* Configurable methods. */ - - virtual Accessor *make_accessor(fileid_t fileid); - -public: - explicit BlockFileOpener(Pages *pages) - : HostFileOpener(pages) - { - } -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/file_pager.cc --- a/files/file_pager.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * File-specific pager functionality. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "file_pager.h" -#include "mapped_file_object_server.h" - - - -/* Initialise a pager for a file with a unique file identifier and shared page - mapper for moderating access to loaded pages. */ - -FilePager::FilePager(fileid_t fileid, PageMapper *mapper, flags_t flags, - FilePaging *paging) -: Pager(mapper, flags), _paging(paging), fileid(fileid) -{ -} - -int FilePager::expected_items() -{ - return MappedFileObject_expected_items; -} - -ipc_server_handler_type FilePager::handler() -{ - return (ipc_server_handler_type) handle_MappedFileObject; -} - - - -/* Close the pager, removing the mapper from the paging registry if - appropriate. */ - -void FilePager::close() -{ - _paging->detach_pager(fileid, _mapper); -} - - - -/* File-specific operations. */ - -long FilePager::flush(offset_t populated_size, offset_t *size) -{ - return Pager::flush(populated_size, size); -} - -long FilePager::resize(offset_t *size) -{ - return Pager::resize(size); -} - -long FilePager::mmap(offset_t position, offset_t length, offset_t *start_pos, - offset_t *end_pos, offset_t *size) -{ - /* Set the limits of the paged region. */ - - return Pager::mmap(position, length, start_pos, end_pos, size); -} - - - -/* Generic pager operations. */ - -long FilePager::map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region) -{ - return Pager::map(offset, hot_spot, flags, region); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/file_pager.h --- a/files/file_pager.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * File-specific pager functionality. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "mapped_file_object_interface.h" -#include "pager.h" -#include "file_paging.h" - - - -/* A pager abstraction for a file. */ - -class FilePager : public Pager, public MappedFileObject -{ -protected: - FilePaging *_paging; - -public: - fileid_t fileid; - - explicit FilePager(fileid_t fileid, PageMapper *mapper, flags_t flags, - FilePaging *paging); - - virtual void close(); - - /* Server details. */ - - int expected_items(); - - ipc_server_handler_type handler(); - - void *interface() - { return static_cast(this); } - - /* File methods. */ - - virtual long flush(offset_t populated_size, offset_t *size); - - virtual long resize(offset_t *size); - - /* Pager and mapped file methods. */ - - virtual long map(offset_t offset, address_t hot_spot, flags_t flags, - l4_snd_fpage_t *region); - - virtual long mmap(offset_t position, offset_t length, offset_t *start_pos, - offset_t *end_pos, offset_t *size); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/file_paging.cc --- a/files/file_paging.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/* - * General functionality supporting file paging. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "file_pager.h" -#include "file_paging.h" - -#include - - - -FilePaging::FilePaging(Pages *pages) -: _pages(pages) -{ -} - - - -/* Return any registered page mapper for the given 'fileid' or NULL if no such - mapper is registered. */ - -PageMapper *FilePaging::get(fileid_t fileid) -{ - FileMapping::iterator entry = _mappers.find(fileid); - PageMapper *mapper; - - if (entry == _mappers.end()) - mapper = NULL; - else - mapper = entry->second; - - return mapper; -} - -/* Register a page 'mapper' for the given 'fileid'. */ - -void FilePaging::set(fileid_t fileid, PageMapper *mapper) -{ - FileMapping::iterator entry = _mappers.find(fileid); - - if (entry == _mappers.end()) - _mappers[fileid] = mapper; -} - - - -/* Convert opening flags to map-compatible paging flags. */ - -flags_t FilePaging::get_flags(flags_t flags) -{ - return flags & (O_WRONLY | O_RDWR) ? L4RE_DS_MAP_FLAG_RW : L4RE_DS_MAP_FLAG_RO; -} - - - -/* Obtain a page mapper for the 'fileid' or register a new one in the - paging object. */ - -PageMapper *FilePaging::get_mapper(fileid_t fileid) -{ - /* Obtain any registered page mapper. */ - - PageMapper *mapper = get(fileid); - - if (mapper != NULL) - return mapper; - - /* Make an accessor and page mapper, registering the mapper. */ - - Accessor *accessor = make_accessor(fileid); - mapper = new PageMapper(accessor, _pages); - - set(fileid, mapper); - - return mapper; -} - - - -/* Return a pager initialised with a page mapper. */ - -Pager *FilePaging::get_pager(fileid_t fileid, flags_t flags) -{ - std::lock_guard guard(_lock); - - /* Initialise the pager with the mapper and a reference to this object for - closing the mapper and accessor. */ - - PageMapper *mapper = get_mapper(fileid); - return new FilePager(fileid, mapper, flags, this); -} - -/* Detach a pager, potentially removing its resources. */ - -void FilePaging::detach_pager(fileid_t fileid, PageMapper *mapper) -{ - std::lock_guard guard(_lock); - - if (!mapper->detach()) - { - _mappers.erase(fileid); - delete mapper->accessor(); - delete mapper; - } -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/file_paging.h --- a/files/file_paging.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/* - * General functionality supporting file paging. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include -#include - -#include "accessor.h" -#include "pager.h" -#include "page_mapper.h" - - - -/* Mapping type from accessors to page mappers. */ - -typedef std::map FileMapping; -typedef std::pair FileMappingEntry; - - - -/* A registry of mappers for accessors. */ - -class FilePaging -{ -protected: - Pages *_pages; - - FileMapping _mappers; - std::mutex _lock; - - /* Pager initialisation methods. */ - - PageMapper *get_mapper(fileid_t fileid); - - Pager *get_pager(fileid_t fileid, flags_t flags); - - /* Configurable methods. */ - - virtual fileid_t get_fileid(const char *path) = 0; - - virtual flags_t get_flags(flags_t flags); - - virtual Accessor *make_accessor(fileid_t fileid) = 0; - - /* Mapper registry access. */ - - PageMapper *get(fileid_t fileid); - - void set(fileid_t fileid, PageMapper *mapper); - -public: - explicit FilePaging(Pages *pages); - - virtual ~FilePaging() - { - } - - /* Methods for the pager. */ - - void detach_pager(fileid_t fileid, PageMapper *mapper); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/host_file_accessor.cc --- a/files/host_file_accessor.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -/* - * A file accessor employing a "host" file provided via the C library. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include - -#include "host_file_accessor.h" - -HostFileAccessor::HostFileAccessor(const char *path, fileid_t fileid) -: Accessor(fileid), _path(path) -{ - /* Initialise the size of the file. */ - - struct stat buf; - - if (!stat(_path, &buf)) - _size = buf.st_size; - else - _size = 0; -} - -/* Perform any closing operation on the file. */ - -void HostFileAccessor::close() -{ - fclose(_fp); -} - -/* Perform any opening operation on the file. */ - -void HostFileAccessor::open() -{ - _fp = fopen(_path, "r"); -} - -/* Data transfer helper methods. */ - -void HostFileAccessor::fill_populated(Flexpage *flexpage) -{ - offset_t filepos = flexpage->base_offset; - offset_t addr = flexpage->base_addr; - - /* Seek to the offset in the file. */ - - fseek(_fp, filepos, SEEK_SET); - - /* Tag the region with file state. */ - - flexpage->region->fill(fileid, filepos); - - /* Fill the region with file content. */ - - size_t nread = fread((void *) addr, sizeof(char), flexpage->size, _fp); - - /* Pad the flexpage with zero. */ - - memset((void *) (addr + nread), 0, flexpage->size - nread); -} - -void HostFileAccessor::flush_populated(Flexpage *flexpage) -{ - flexpage->region->flush(); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/host_file_accessor.h --- a/files/host_file_accessor.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * A file accessor employing a "host" file provided via the C library. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#include "accessor.h" - - - -/* A host filesystem file accessor, providing flexpages corresponding to file - regions. */ - -class HostFileAccessor : public Accessor -{ -protected: - const char *_path; - FILE *_fp; - - /* Data transfer helper methods. */ - - virtual void fill_populated(Flexpage *flexpage); - - virtual void flush_populated(Flexpage *flexpage); - -public: - explicit HostFileAccessor(const char *path, fileid_t fileid); - - virtual void close(); - - virtual void open(); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/host_file_opener.cc --- a/files/host_file_opener.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * An opener for a "host" file provided via the C library. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include - -#include "host_file_accessor.h" -#include "host_file_opener.h" - -/* Return a file identifier for the given 'path'. */ - -fileid_t HostFileOpener::get_fileid(const char *path) -{ - struct stat statbuf; - - /* Obtain the inode number. - NOTE: This does not handle errors! */ - - stat(path, &statbuf); - - _paths.insert(FilePathEntry(statbuf.st_ino, path)); - - return statbuf.st_ino; -} - -/* Return a new accessor for 'fileid'. */ - -Accessor *HostFileOpener::make_accessor(fileid_t fileid) -{ - FilePaths::iterator found = _paths.find(fileid); - - if (found != _paths.end()) - return new HostFileAccessor(found->second, fileid); - else - return NULL; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/host_file_opener.h --- a/files/host_file_opener.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * An opener for a "host" file provided via the C library. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#include "opener_resource.h" - - - -/* Collection types. */ - -typedef std::map FilePaths; -typedef std::pair FilePathEntry; - - - -/* Support for providing access to files. */ - -class HostFileOpener : public OpenerResource -{ -protected: - FilePaths _paths; - - /* Configurable methods. */ - - virtual fileid_t get_fileid(const char *path); - - virtual Accessor *make_accessor(fileid_t fileid); - -public: - explicit HostFileOpener(Pages *pages) - : OpenerResource(pages) - { - } -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/opener_context_resource.cc --- a/files/opener_context_resource.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -/* - * A context resource offering support for opening files. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "opener_context_resource.h" -#include "opener_context_object_server.h" -#include "opener_resource.h" -#include "resource_server.h" - -#include - - - -/* Support for providing access to files. */ - -OpenerContextResource::OpenerContextResource(OpenerResource *opener, Memory *memory) -: SimplePager(memory), _opener(opener) -{ -} - -int OpenerContextResource::expected_items() -{ - return OpenerContextObject_expected_items; -} - -ipc_server_handler_type OpenerContextResource::handler() -{ - return (ipc_server_handler_type) handle_OpenerContextObject; -} - - - -/* Data access methods. */ - -char *OpenerContextResource::get_path() -{ - char *buffer = _region->read(); - offset_t size = _region->size(); - - /* Confine the path to the limit of the buffer. */ - - if ((buffer != NULL) && (strnlen(buffer, size) < size)) - return buffer; - else - return NULL; -} - - - -/* Opener context interface methods. */ - -long OpenerContextResource::open(flags_t flags, offset_t *size, l4_cap_idx_t *file) -{ - char *path = get_path(); - - if (path == NULL) - return -L4_EINVAL; - - Pager *pager = _opener->open(path, flags); - - /* Complete the initialisation and start a server in a new thread. - If the thread does not start, the resource should be finalised. */ - - ResourceServer server(pager); - long err = server.start_thread(); - - if (!err) - { - /* Return the file size. */ - /* Return the server capability to the caller. */ - - *size = pager->get_data_size(); - *file = server.config()->server; - } - - return err; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/opener_context_resource.h --- a/files/opener_context_resource.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * A context resource offering support for opening files. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "opener_context_object_interface.h" -#include "simple_pager.h" - - - -/* Forward declaration. */ - -class OpenerResource; - - - -/* Support for indicating files to be opened. */ - -class OpenerContextResource : public SimplePager, public OpenerContextObject -{ -protected: - OpenerResource *_opener; - -public: - explicit OpenerContextResource(OpenerResource *opener, Memory *memory=NULL); - - /* Server details. */ - - int expected_items(); - - ipc_server_handler_type handler(); - - void *interface() - { return static_cast(this); } - - /* Data access methods. */ - - char *get_path(); - - /* Opener context interface methods. */ - - long open(flags_t flags, offset_t *size, l4_cap_idx_t *file); - - /* Pager/dataspace methods. */ - - long map(unsigned long offset, address_t hot_spot, flags_t flags, - l4_snd_fpage_t *region) - { return SimplePager::map(offset, hot_spot, flags, region); } - - long info(unsigned long *size, unsigned long *flags) - { return SimplePager::info(size, flags); } -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/opener_resource.cc --- a/files/opener_resource.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * A resource offering support for creating contexts and opening files. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "opener_server.h" -#include "opener_resource.h" -#include "resource_server.h" - -/* Support for providing access to files. */ - -OpenerResource::OpenerResource(Pages *pages) -: FilePaging(pages) -{ -} - -int OpenerResource::expected_items() -{ - return Opener_expected_items; -} - -ipc_server_handler_type OpenerResource::handler() -{ - return (ipc_server_handler_type) handle_Opener; -} - - - -/* Return a pager object for the given path and flags. */ - -Pager *OpenerResource::open(const char *path, flags_t flags) -{ - fileid_t fileid = get_fileid(path); - - if (fileid == FILEID_INVALID) - return NULL; - - return get_pager(fileid, get_flags(flags)); -} - - - -/* Opener interface methods. */ - -long OpenerResource::context(l4_cap_idx_t *context) -{ - OpenerContextResource *resource = new OpenerContextResource(this); - - /* Complete the initialisation and start a server in a new thread. - If the thread does not start, the resource should be finalised. */ - - ResourceServer server(resource); - long err = server.start_thread(); - - /* Return the server capability to the caller. */ - - if (!err) - *context = server.config()->server; - - return err; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/opener_resource.h --- a/files/opener_resource.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * A resource offering support for creating contexts and opening files. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#include "file_paging.h" -#include "opener_context_resource.h" -#include "opener_interface.h" -#include "pages.h" -#include "resource.h" - - - -/* Support for providing access to files. */ - -class OpenerResource : public Resource, public FilePaging, public Opener -{ -public: - explicit OpenerResource(Pages *pages); - - /* Server details. */ - - int expected_items(); - - ipc_server_handler_type handler(); - - void *interface() - { return static_cast(this); } - - /* Direct access methods. */ - - Pager *open(const char *path, flags_t flags); - - /* Opener interface methods. */ - - long context(l4_cap_idx_t *context); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/test_file_accessor.cc --- a/files/test_file_accessor.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * A test accessor producing generated content. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include -#include - -#include "test_file_accessor.h" - -TestFileAccessor::TestFileAccessor(fileid_t fileid, offset_t size) -: Accessor(fileid, size) -{ -} - -/* Data transfer helper methods. */ - -void TestFileAccessor::fill_populated(Flexpage *flexpage) -{ - Region *region = flexpage->region; - offset_t filepos = flexpage->base_offset; - - /* Tag the region with file state. */ - - region->fill(fileid, filepos); - - /* Write some data to each page of the flexpage in each region. This - allows each page to be tested regardless of how large each flexpage - or region is. */ - - offset_t addr = flexpage->base_addr; - offset_t limit = addr + flexpage->size; - - while (addr < limit) - { - /* Overwrite enough of any previous data to make the new data - readable. */ - - char tag[32]; - - sprintf(tag, "%ld:%ld", fileid, filepos); - - memset((void *) addr, 0, strlen(tag) + 1); - strcpy((char *) addr, tag); - - filepos += PAGE_SIZE; - addr += PAGE_SIZE; - } -} - -void TestFileAccessor::flush_populated(Flexpage *flexpage) -{ - flexpage->region->flush(); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/test_file_accessor.h --- a/files/test_file_accessor.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * A test accessor producing generated content. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "accessor.h" - - - -/* A file accessor, providing flexpages corresponding to file regions. */ - -class TestFileAccessor : public Accessor -{ -protected: - - /* Data transfer helper methods. */ - - virtual void fill_populated(Flexpage *flexpage); - - virtual void flush_populated(Flexpage *flexpage); - -public: - explicit TestFileAccessor(fileid_t fileid, offset_t size=0); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/test_file_opener.cc --- a/files/test_file_opener.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * An opener for a test file containing generated content. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "test_file_accessor.h" -#include "test_file_opener.h" - -#include - -/* Support for providing access to files. */ - -TestFileOpener::TestFileOpener(Pages *pages, offset_t file_size) -: OpenerResource(pages), _file_size(file_size) -{ -} - -/* Return a file identifier for the given 'path'. */ - -fileid_t TestFileOpener::get_fileid(const char *path) -{ - /* NOTE: Just convert the path to a number. */ - - return atol(path); -} - -/* Return a new accessor for 'fileid'. */ - -Accessor *TestFileOpener::make_accessor(fileid_t fileid) -{ - return new TestFileAccessor(fileid, _file_size); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c files/test_file_opener.h --- a/files/test_file_opener.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * An opener for a test file containing generated content. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "opener_resource.h" - - - -/* Support for providing access to files. */ - -class TestFileOpener : public OpenerResource -{ -protected: - offset_t _file_size; - - /* Configurable methods. */ - - virtual fileid_t get_fileid(const char *path); - - virtual Accessor *make_accessor(fileid_t fileid); - -public: - explicit TestFileOpener(Pages *pages, offset_t file_size=0); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c generic/accessor.cc --- a/generic/accessor.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * Generic accessor functionality. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "accessor.h" - -#include - - - -Accessor::Accessor(fileid_t fileid, offset_t size) -: _size(size), fileid(fileid) -{ -} - -/* Return the size of the file. */ - -offset_t Accessor::get_size() -{ - return _size; -} - -/* Update the size of the file. */ - -void Accessor::set_size(offset_t size) -{ - _size = size; -} - -/* Perform any closing operation on the file. */ - -void Accessor::close() -{ -} - -/* Perform any opening operation on the file. */ - -void Accessor::open() -{ -} - -/* Data transfer methods. */ - -void Accessor::fill(Flexpage *flexpage) -{ - /* Filling completely beyond the end of file should produce an empty - flexpage. This could potentially be a shared read-only flexpage that - would be replaced by an independent writable flexpage if ever written. */ - - if (flexpage->base_offset < _size) - fill_populated(flexpage); - else - memset((void *) flexpage->base_addr, 0, flexpage->size); -} - -void Accessor::flush(Flexpage *flexpage) -{ - /* Flushing completely beyond the end of file should discard the - flexpage. */ - - if (flexpage->base_offset < _size) - flush_populated(flexpage); -} - -/* Data transfer helper methods. */ - -void Accessor::fill_populated(Flexpage *flexpage) -{ - (void) flexpage; -} - -void Accessor::flush_populated(Flexpage *flexpage) -{ - (void) flexpage; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c generic/accessor.h --- a/generic/accessor.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -/* - * Generic accessor functionality. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "flexpage.h" - - - -/* A file accessor, providing flexpages corresponding to file regions. */ - -class Accessor -{ -protected: - offset_t _size; - - /* Data transfer helper methods. */ - - virtual void fill_populated(Flexpage *flexpage); - - virtual void flush_populated(Flexpage *flexpage); - -public: - fileid_t fileid; - - explicit Accessor(fileid_t fileid, offset_t size=0); - - virtual ~Accessor() - { - } - - virtual offset_t get_size(); - - virtual void set_size(offset_t size); - - virtual void close(); - - virtual void open(); - - /* Data transfer methods. */ - - virtual void fill(Flexpage *flexpage); - - virtual void flush(Flexpage *flexpage); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c generic/pager.cc --- a/generic/pager.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,128 +0,0 @@ -/* - * Generic pager functionality. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "dataspace_server.h" -#include "ipc.h" -#include "pager.h" - - - -/* Initialise the pager with a page mapper and the given flags controlling - access to a file. */ - -Pager::Pager(PageMapper *mapper, flags_t flags) -: _start(0), _size(0), _mapper(mapper), _flags(flags) -{ - /* Some pagers may not be initialised with a mapper. */ - - if (_mapper != NULL) - _mapper->attach(); -} - -/* Close the pager. */ - -void Pager::close() -{ - if (_mapper != NULL) - _mapper->detach(); -} - -/* Flush data to the file. */ - -long Pager::flush(offset_t populated_size, offset_t *size) -{ - _mapper->flush_all(_start, populated_size); - - *size = _mapper->get_data_size(); - return L4_EOK; -} - -/* Resize the underlying file. */ - -long Pager::resize(offset_t *size) -{ - _mapper->set_data_size(*size); - - *size = _mapper->get_data_size(); - return L4_EOK; -} - -/* Expose a region of the file. */ - -long Pager::mmap(offset_t position, offset_t length, offset_t *start_pos, - offset_t *end_pos, offset_t *size) -{ - /* Define region characteristics. */ - - _start = trunc(position, PAGE_SIZE); - _size = round(position + length, PAGE_SIZE) - _start; - - /* Return the start and end positions plus populated extent. */ - - *start_pos = _start; - *end_pos = _start + _size; - *size = _mapper->get_data_size(); - - return L4_EOK; -} - -/* Map a flexpage corresponding to the dataspace 'offset' involving a 'hot_spot' - (flexpage offset). */ - -long Pager::map(offset_t offset, address_t hot_spot, flags_t flags, - l4_snd_fpage_t *region) -{ - offset_t file_offset = _start + offset; - offset_t max_offset = _start + _size; - - /* Prevent access beyond that defined by the pager. */ - - if (flags & ~_flags) - return -L4_EACCESS; - - Flexpage *flexpage = _mapper->get(file_offset, flags); - - /* Issue the flexpage via the IPC system. */ - - long err = ipc_prepare_flexpage(flexpage, file_offset, max_offset, hot_spot, - flags, region); - - if (!err) - err = complete_Dataspace_map(*region); - - /* After the flexpage is issued, it is queued for future reuse. */ - - _mapper->queue(flexpage); - - if (err) - return err; - - return IPC_MESSAGE_SENT; -} - -/* Return the total size of the data. */ - -offset_t Pager::get_data_size() -{ - return _mapper->get_data_size(); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c generic/pager.h --- a/generic/pager.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Generic pager functionality. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#include "page_mapper.h" -#include "resource.h" - - - -/* A pager exposing a dataspace. */ - -class Pager : public Resource -{ -protected: - offset_t _start, _size; - PageMapper *_mapper; - flags_t _flags; - -public: - explicit Pager(PageMapper *mapper, flags_t flags); - - virtual void close(); - - /* Paging methods. */ - - virtual long map(offset_t offset, address_t hot_spot, flags_t flags, - l4_snd_fpage_t *region); - - /* Limit methods. */ - - offset_t get_data_size(); - - /* File methods. */ - - virtual long flush(offset_t populated_size, offset_t *size); - - virtual long resize(offset_t *size); - - /* Mapped file methods. */ - - virtual long mmap(offset_t position, offset_t length, offset_t *start_pos, - offset_t *end_pos, offset_t *size); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c generic/resource.h --- a/generic/resource.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Common resource classes and functions. - * - * Copyright (C) 2018, 2019, 2020 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - - - -/* A generic class for an object potentially needing to be closed after use. */ - -class Resource -{ -public: - virtual ~Resource() - { - } - - /* Server details. */ - - virtual int expected_items() = 0; - - virtual ipc_server_handler_type handler() = 0; - - virtual void *interface() = 0; - - /* Deallocation of resources. */ - - virtual void close() - { - } - - /* Activation. */ - - virtual void activate() - { - } -}; diff -r bf981cb9a709 -r b6dab1e89e3c generic/resource_server.cc --- a/generic/resource_server.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Resource server functionality. - * - * Copyright (C) 2018, 2019, 2020, 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include - -#include -#include - -#include "resource_server.h" - - - -/* Convenience server methods. */ - -/* Bind to a named IPC gate capability. */ - -long ResourceServer::bind(const char *name) -{ - return ipc_server_bind(name, (l4_umword_t) _resource, &_config->server); -} - -/* Start in the same thread with no deletion notifications or finalisation. */ - -long ResourceServer::start() -{ - resource_init_config(_config, _resource); - _config->thread = pthread_l4_cap(pthread_self()); - return resource_start_config(_config, _resource); -} - -/* Start a new thread with deletion notifications and finalisation. */ - -long ResourceServer::start_thread() -{ - pthread_t thread; - pthread_attr_t attr; - long err; - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - resource_init_config(_config, _resource); - - err = pthread_create(&thread, &attr, ipc_server_start_mainloop, _config); - if (err) - return err; - - resource_set_config_threaded(_config, pthread_l4_cap(thread), 1); - - return resource_start_config(_config, _resource); -} - - - -/* Initialise a server configuration for a resource. */ - -void resource_init_config(ipc_server_config_type *config, Resource *resource) -{ - config->handler_obj = resource->interface(); - config->finaliser_obj = resource; - config->expected_items = resource->expected_items(); - config->handler = resource->handler(); -} - -/* Set a configuration to be threaded. */ - -void resource_set_config_threaded(ipc_server_config_type *config, - l4_cap_idx_t thread, int new_thread) -{ - config->finaliser = resource_thread_finaliser; - config->new_thread = new_thread; - config->thread = thread; - config->notifications = 1; -} - -/* Activate a resource and start a server for it. */ - -long resource_start_config(ipc_server_config_type *config, Resource *resource) -{ - resource->activate(); - long err = ipc_server_start_config(config); - - /* Discard any server resources if starting it failed. */ - - if (err) - { - ipc_server_finalise_config(config); - ipc_server_discard_thread(config); - } - - return err; -} - - - -/* A finaliser for exposed resources. */ - -void resource_thread_finaliser(ipc_server_config_type *config) -{ - Resource *resource = reinterpret_cast(config->finaliser_obj); - - /* Close and delete the resource. */ - - resource->close(); - delete resource; - - /* Release the capabilities. */ - - ipc_server_finalise_config(config); - delete config; -} - -// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c generic/resource_server.h --- a/generic/resource_server.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * Common resource server functions. - * - * Copyright (C) 2018, 2019, 2020 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "resource.h" -#include - - - -/* Convenience abstraction for blocking servers. */ - -class ResourceServer -{ -protected: - Resource *_resource; - ipc_server_config_type *_config; - -public: - explicit ResourceServer(Resource *resource) - : _resource(resource) - { - _config = new ipc_server_config_type; - ipc_server_init_config(_config); - } - - /* Access to configuration. */ - - ipc_server_config_type *config() - { return _config; } - - /* Server IPC gate allocation. */ - - long bind(const char *name); - - /* Server initiation. */ - - long start(); - - long start_thread(); -}; - - - -/* Server initialisation. */ - -void resource_init_config(ipc_server_config_type *config, Resource *resource); - -void resource_set_config_threaded(ipc_server_config_type *config, - l4_cap_idx_t thread, int new_thread); - -/* Server initiation. */ - -long resource_start_config(ipc_server_config_type *config, Resource *resource); - -/* Server finalisation. */ - -void resource_thread_finaliser(ipc_server_config_type *config); diff -r bf981cb9a709 -r b6dab1e89e3c generic/simple_pager.cc --- a/generic/simple_pager.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* - * A simple pager exposing a single memory region. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include - -#include "dataspace_server.h" -#include "memory_incremental.h" -#include "ipc.h" -#include "simple_pager.h" - - - -SimplePager::SimplePager(Memory *memory) -{ - if (memory == NULL) - _memory = new MemoryIncremental(); - else - _memory = memory; - - _region = _memory->region(); -} - -void SimplePager::close() -{ - if (_region != NULL) - { - _memory->release(_region); - _region = NULL; - } -} - -/* Map a flexpage corresponding to the dataspace 'offset' involving a 'hot_spot' - (flexpage offset). */ - -long SimplePager::map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region) -{ - Flexpage flexpage(_region); - - flexpage.reset(offset); - flexpage.upgrade(flags); - - /* Send the flexpage explicitly. */ - - long err = ipc_prepare_flexpage(&flexpage, offset, _region->size(), - hot_spot, flags, region); - - if (err) - return err; - - err = complete_Dataspace_map(*region); - - if (err) - return err; - - return IPC_MESSAGE_SENT; -} - -long SimplePager::info(offset_t *size, flags_t *flags) -{ - *size = _region->size(); - *flags = L4_FPAGE_RW; - - return L4_EOK; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c generic/simple_pager.h --- a/generic/simple_pager.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * A simple pager exposing a single memory region. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "dataspace_interface.h" -#include "flexpage.h" -#include "memory.h" -#include "resource.h" - - - -/* A simple pager exposing a single memory region as a dataspace. */ - -class SimplePager : public Dataspace, public Resource -{ -protected: - Memory *_memory; - Region *_region; - -public: - explicit SimplePager(Memory *memory=NULL); - - void close(); - - /* Paging methods. */ - - long map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region); - - long info(offset_t *size, flags_t *flags); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c generic/types.h --- a/generic/types.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * Miscellaneous types. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - - - -/* File identification. */ - -typedef unsigned long fileid_t; - -#define FILEID_INVALID (~0UL) - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/Control --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/Control Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,3 @@ +requires: libstdc++ libc libipc +provides: libfsclient +maintainer: paul@boddie.org.uk diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,4 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../../.. + +include $(L4DIR)/mk/subdir.mk diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/include/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/include/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,7 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../../.. + +PKGNAME = libfsclient +CONTRIB_HEADERS = 1 + +include $(L4DIR)/mk/include.mk diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/include/fsclient/client.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/include/fsclient/client.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,56 @@ +/* + * Filesystem client functions. + * + * Copyright (C) 2018, 2019, 2020, 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include "file.h" + +EXTERN_C_BEGIN + +/* File operations. */ + +void client_close(file_t *file); +file_t *client_open(const char *name, flags_t flags); +long client_pipe(file_t **reader, file_t **writer); + +/* File and region operations. */ + +long client_flush(file_t *file); +void *client_mmap(file_t *file, offset_t position, offset_t length); + +/* Pipe region operations. */ + +void *client_current_region(file_t *file); +void *client_next_region(file_t *file); + +/* File data operations. */ + +offset_t client_read(file_t *file, void *buf, offset_t count); +offset_t client_write(file_t *file, const void *buf, offset_t count); + +/* File navigation operations. */ + +offset_t client_seek(file_t *file, offset_t offset, int whence); +long client_tell(file_t *file); + +EXTERN_C_END + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/include/fsclient/file.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/include/fsclient/file.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,114 @@ +/* + * File access convenience functions and types. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include + + + +EXTERN_C_BEGIN + +/* File access abstraction. */ + +typedef struct +{ + /* File object reference. */ + + l4_cap_idx_t ref; + + /* Mapped memory accessing a file region. */ + + char *memory; + + /* File region parameters. */ + + offset_t start_pos, end_pos; /* start and end positions of region */ + offset_t data_end; /* amount/extent of data in the region */ + offset_t data_current; /* client access offset */ + + /* Total size of file. */ + + offset_t size; + + /* Arbitrary memory mapping support. */ + + int can_mmap; + +} file_t; + + + +/* File operations. */ + +void file_close(file_t *file); +long file_open(file_t *file, const char *filename, flags_t flags, l4_cap_idx_t server); + +/* File lifecycle operations. */ + +long file_context(file_t *file, l4_cap_idx_t server); +long file_context_open(file_t *file, flags_t flags, file_t *context); +void file_init(file_t *file); + +/* File and region operations. */ + +long file_flush(file_t *file); +long file_mmap(file_t *file, offset_t position, offset_t length); +long file_resize(file_t *file, offset_t size); + +/* File and region properties. */ + +offset_t file_populated_span(file_t *file); +offset_t file_span(file_t *file); + +/* Convenience functions. */ + +char *file_string_get(file_t *file, offset_t offset); +int file_string_set(file_t *file, const char *data, offset_t offset, offset_t *written); + +/* Client data functions. */ + +offset_t file_data_available(file_t *file); +char *file_data_current(file_t *file); +offset_t file_data_current_position(file_t *file); +offset_t file_data_end_position(file_t *file); +offset_t file_data_space(file_t *file); + +/* Client data transfer functions. */ + +void file_data_read(file_t *file, char *buf, size_t to_transfer); +void file_data_write(file_t *file, char *buf, size_t to_transfer); + + + +/* Pipe operations. */ + +long pipe_open(offset_t size, file_t *reader, file_t *writer, l4_cap_idx_t server); + +/* Pipe region operations. */ + +long pipe_current(file_t *pipe); +long pipe_next(file_t *pipe); +long pipe_written(file_t *pipe, offset_t size); + +EXTERN_C_END + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/lib/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/lib/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,4 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../../.. + +include $(L4DIR)/mk/subdir.mk diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/lib/src/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/lib/src/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,40 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../../.. + +TARGET = libfsclient.so libfsclient.a +PC_FILENAME = libfsclient + +# Locations for interface input and generated output. + +IDL_DIR = $(L4DIR)/pkg/libsystypes/idl +IDL_MK_DIR = $(L4DIR)/idl4re/mk +IDL_BUILD_DIR = . +IDL_EXPORT_DIR = . + +include $(IDL_MK_DIR)/idl.mk + +# Individual interfaces. + +CLIENT_INTERFACES_CC = dataspace file mapped_file opener opener_context pipe pipe_opener + +# Generated and plain source files. + +CLIENT_INTERFACES_SRC_CC = $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC)) + +PLAIN_SRC_CC = client.cc file.cc + +# Normal definitions. + +SRC_CC = \ + $(CLIENT_INTERFACES_SRC_CC) \ + $(PLAIN_SRC_CC) + +REQUIRES_LIBS = l4re_c-util libipc libstdc++ libsystypes + +PRIVATE_INCDIR = $(PKGDIR)/include/fsclient $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR) +CONTRIB_INCDIR = libfsclient + +include $(L4DIR)/mk/lib.mk +include $(IDL_MK_DIR)/interface_rules.mk + +$(PLAIN_SRC_CC): $(CLIENT_INTERFACES_SRC_CC) diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/lib/src/client.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/lib/src/client.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,390 @@ +/* + * Filesystem client functions. + * + * Copyright (C) 2018, 2019, 2020, 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include +#include + +#include "client.h" + + + +/* Default size of pipe regions. */ + +const offset_t DEFAULT_PIPE_SIZE = 4096; + + + +/* Close a filesystem object. */ + +void client_close(file_t *file) +{ + if (file == NULL) + return; + + file_close(file); + free(file); +} + + + +/* Open a filesystem object. */ + +file_t *client_open(const char *name, flags_t flags) +{ + file_t *file = (file_t *) malloc(sizeof(file_t)); + + if (file == NULL) + return NULL; + + l4_cap_idx_t server = l4re_env_get_cap("server"); + + if (file_open(file, name, flags, server)) + { + free(file); + return NULL; + } + + return file; +} + + + +/* Open a pipe object. */ + +long client_pipe(file_t **reader, file_t **writer) +{ + *reader = (file_t *) malloc(sizeof(file_t)); + + if (*reader == NULL) + return -L4_ENOMEM; + + *writer = (file_t *) malloc(sizeof(file_t)); + + if (*writer == NULL) + { + free(*reader); + return -L4_ENOMEM; + } + + l4_cap_idx_t server = l4re_env_get_cap("pipes"); + + long err = pipe_open(DEFAULT_PIPE_SIZE, *reader, *writer, server); + + if (err) + { + free(*reader); + free(*writer); + } + + return err; +} + + + +/* Flush data conditionally to the filesystem object. */ + +static long _flush(file_t *file, offset_t position) +{ + long err; + + /* Where the position is outside the current region, re-map. */ + + if ((position < file->start_pos) || (position >= file->end_pos)) + { + if (file->can_mmap) + { + if (file_mmap(file, position, file_span(file))) + return -L4_EIO; + } + + /* Strict conditions for region navigation in pipes. */ + + else if ((position != file->end_pos) || + (client_next_region(file) == NULL)) + return -L4_EIO; + } + + /* Otherwise, flush any written data in the current region and update the + file size details. */ + + else + { + err = client_flush(file); + + if (err) + return err; + } + + /* Update the current data offset. */ + + file->data_current = position - file->start_pos; + return L4_EOK; +} + + + +/* Flush data explicitly to the filesystem object. */ + +long client_flush(file_t *file) +{ + if (file == NULL) + return -L4_EINVAL; + + /* Flush and retain most buffer settings. */ + + return file_flush(file); +} + + + +/* Map a memory region to a file. */ + +void *client_mmap(file_t *file, offset_t position, offset_t length) +{ + if ((file == NULL) || (file_mmap(file, position, length))) + return NULL; + + return file->memory; +} + + + +/* Obtain the current region of a pipe. */ + +void *client_current_region(file_t *file) +{ + if ((file == NULL) || (pipe_current(file))) + return NULL; + + return file->memory; +} + + + +/* Obtain the next region of a pipe. */ + +void *client_next_region(file_t *file) +{ + if ((file == NULL) || (pipe_next(file))) + return NULL; + + return file->memory; +} + + + +/* Read from the filesystem object into the buffer provided. */ + +offset_t client_read(file_t *file, void *buf, offset_t count) +{ + if (file == NULL) + return 0; + + /* Amount available in the descriptor buffer already. */ + + offset_t available = file_data_available(file); + offset_t to_transfer, total = 0; + + while (count > 0) + { + /* If there is no data, try and obtain more data. */ + + if (!available) + { + /* Flush any unwritten data, preparing to read from the file position at + the end of the data, and returning if no new data is available. */ + + if (_flush(file, file_data_end_position(file))) + break; + + available = file_data_available(file); + + if (!available) + break; + } + + /* Transfer data into the supplied buffer. */ + + to_transfer = available <= count ? available : count; + + file_data_read(file, (char *) buf, to_transfer); + + /* Update counters. */ + + available -= to_transfer; + + count -= to_transfer; + total += to_transfer; + + buf = ((char *) buf + to_transfer); + } + + return total; +} + + + +/* Ensure that the buffer can provide the needed data. */ + +offset_t client_seek(file_t *file, offset_t offset, int whence) +{ + if (file == NULL) + return 0; + + offset_t position, current = file_data_current_position(file), change; + + switch (whence) + { + case SEEK_SET: + position = offset; + break; + + case SEEK_CUR: + position = current + offset; + break; + + case SEEK_END: + position = file->size + offset; + break; + + default: + /* NOTE: Set errno to EINVAL. */ + return -1; + } + + /* Retain the current position if unchanged. */ + + if (position == current) + return position; + + /* Move forward in the file. */ + + if (position > current) + { + change = position - current; + + /* Move towards the end of available data. + Request new data if not enough is available. */ + + if (change <= file_data_available(file)) + { + file->data_current += change; + return position; + } + } + + /* Move backward in the file. */ + + else + { + change = current - position; + + /* Move towards the start of available data. + Request new data if moving beyond the start of the data. */ + + if (change <= file->data_current) + { + file->data_current -= change; + return position; + } + } + + /* Handle unwritten data and reset the buffer for reading. */ + + _flush(file, position); + return position; +} + + + +long client_tell(file_t *file) +{ + if (file == NULL) + return -L4_EINVAL; + + return file_data_current_position(file); +} + + + +/* Write to the filesystem object from the buffer provided. */ + +offset_t client_write(file_t *file, const void *buf, offset_t count) +{ + if (file == NULL) + return 0; + + /* Attempt to ensure that the file can accept the amount of data to be + written. This may not resize to the needed amount if a file has a fixed + size, but data will still be written to any available space. */ + + offset_t needed_size = file_data_current_position(file) + count; + + if (file->size < needed_size) + { + file_resize(file, needed_size); + + if (file->size < needed_size) + count = file->size - file_data_current_position(file); + } + + /* Space remaining in the descriptor buffer. */ + + offset_t space = file_data_space(file); + offset_t to_transfer, total = 0; + + while (count > 0) + { + /* If no space is available, try and send data, reset the buffer. */ + + if (!space) + { + /* Flush any unwritten data and continue writing from the current data + position. */ + + if (_flush(file, file_data_current_position(file))) + break; + + space = file_data_space(file); + } + + /* Transfer data into the supplied buffer. */ + + to_transfer = space <= count ? space : count; + + file_data_write(file, (char *) buf, to_transfer); + + /* Update counters. */ + + space -= to_transfer; + + count -= to_transfer; + total += to_transfer; + + buf = ((char *) buf + to_transfer); + } + + return total; +} + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c libfsclient/lib/src/file.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsclient/lib/src/file.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,452 @@ +/* + * File access convenience functions. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include + +#include + +#include "dataspace_client.h" +#include "file_client.h" +#include "opener_client.h" +#include "opener_context_client.h" +#include "pipe_client.h" +#include "pipe_opener_client.h" +#include "mapped_file_client.h" + +#include "file.h" + + + +/* Update the extent of the file in a region using the region start and end + positions and the file size. */ + +static void _update_extent(file_t *file) +{ + /* Handle files ending after or within the region. */ + + if (file->size > file->start_pos) + { + if (file->size > file->end_pos) + file->data_end = file->end_pos - file->start_pos; + else + file->data_end = file->size - file->start_pos; + } + + /* Handle files ending before the region. */ + + else + file->data_end = 0; +} + + + +/* Initialise the given file structure. */ + +void file_init(file_t *file) +{ + file->memory = NULL; + file->ref = L4_INVALID_CAP; + file->start_pos = 0; + file->end_pos = 0; + file->data_end = 0; + file->data_current = 0; + file->can_mmap = 1; +} + + + +/* Release resources for the given file. */ + +void file_close(file_t *file) +{ + if (l4_is_valid_cap(file->ref)) + ipc_cap_free_um(file->ref); + + if (file->memory != NULL) + ipc_detach_dataspace(file->memory); + + file_init(file); +} + +/* Open a file using the given structure, indicating the filename and + filesystem server. The file_mmap function should be used to obtain access to + memory providing file data. This is a convenience function invoking + file_context and file_context_open. */ + +long file_open(file_t *file, const char *filename, flags_t flags, l4_cap_idx_t server) +{ + file_t context; + long err; + + err = file_context(&context, server); + if (err) + return err; + + if (!file_string_set(&context, filename, 0, NULL)) + return -L4_ENOMEM; + + err = file_context_open(file, flags, &context); + + /* Close the context, although a separate mechanism could permit contexts to + open several files. */ + + file_close(&context); + return err; +} + + + +/* Initialise a file structure for a context obtained from the given server + attaching memory to communicate filename information. */ + +long file_context(file_t *file, l4_cap_idx_t server) +{ + if (l4_is_invalid_cap(server)) + return -L4_EINVAL; + + client_Opener opener(server); + offset_t size; + flags_t flags; + long err; + + file_init(file); + + err = opener.context(&file->ref); + if (err) + return err; + + client_Dataspace context_ds(file->ref); + + err = context_ds.info(&size, &flags); + if (err) + return err; + + file->start_pos = 0; + file->end_pos = size; + + return ipc_attach_dataspace(file->ref, size, (void **) &file->memory); +} + +/* Open a file using the given structure and context. */ + +long file_context_open(file_t *file, flags_t flags, file_t *context) +{ + client_OpenerContext openercontext(context->ref); + file_init(file); + return openercontext.open(flags, &file->size, &file->ref); +} + + + +/* Flush populated data and obtain an updated file size and populated data + details. */ + +long file_flush(file_t *file) +{ + client_File _file(file->ref); + long err = _file.flush(file->data_current, &file->size); + + if (err) + return err; + + _update_extent(file); + + return L4_EOK; +} + +/* Map a region of the given file to a memory region, obtaining an updated file + size and populated data details. Unmap any previously mapped region. */ + +long file_mmap(file_t *file, offset_t position, offset_t length) +{ + char *memory = file->memory; + client_MappedFile mapped_file(file->ref); + long err = mapped_file.mmap(position, length, &file->start_pos, + &file->end_pos, &file->size); + + if (err) + return err; + + _update_extent(file); + + err = ipc_attach_dataspace(file->ref, file_span(file), (void **) &file->memory); + if (err) + return err; + + if (memory != NULL) + ipc_detach_dataspace(memory); + + return L4_EOK; +} + +/* Resize a file, obtaining updated file size and populated data details. */ + +long file_resize(file_t *file, offset_t size) +{ + client_File _file(file->ref); + offset_t file_size = size; + long err = _file.resize(&file_size); + + if (err) + return err; + + file->size = file_size; + _update_extent(file); + return L4_EOK; +} + + + +/* Return the amount of data in the mapped region for the given file. */ + +offset_t file_populated_span(file_t *file) +{ + offset_t size = file_span(file); + return (file->data_end < size) ? file->data_end : size; +} + +/* Return the size of the mapped region for the given file. */ + +offset_t file_span(file_t *file) +{ + return file->end_pos - file->start_pos; +} + + + +/* Get a pointer to any terminated string at the given offset or NULL if the + data from offset is not terminated. */ + +char *file_string_get(file_t *file, offset_t offset) +{ + offset_t limit = file_span(file) - offset; + + if (strnlen(file->memory + offset, limit) < limit) + return file->memory + offset; + else + return NULL; +} + +/* Copy a string to the mapped region at the given offset, returning 1 (true) + where all characters were copied, 0 (false) otherwise. The precise number of + characters copied, excluding the zero terminator is provided via the written + parameter if it is not specified as NULL. */ + +int file_string_set(file_t *file, const char *data, offset_t offset, + offset_t *written) +{ + offset_t i, pos, limit = file_span(file); + + /* Do not attempt to copy data with an invalid offset. */ + + if (offset >= limit) + { + if (written != NULL) + *written = 0; + return 0; + } + + /* Copy the data to the given offset, stopping at the end of the region. */ + + for (i = 0, pos = offset; pos < limit; i++, pos++) + { + file->memory[pos] = data[i]; + + /* Terminator written, can return immediately. */ + + if (!data[i]) + { + if (written != NULL) + *written = pos - offset; + return 1; + } + } + + /* Terminate the incomplete string at the end of the region. */ + + file->memory[limit - 1] = '\0'; + if (written != NULL) + *written = limit - 1 - offset; + return 0; +} + + + +/* Return the number of remaining populated bytes in the region. */ + +offset_t file_data_available(file_t *file) +{ + return file_populated_span(file) - file->data_current; +} + +/* Return the current data offset in the region. */ + +char *file_data_current(file_t *file) +{ + return file->memory + file->data_current; +} + +/* Return the current access position in the file. */ + +offset_t file_data_current_position(file_t *file) +{ + return file->start_pos + file->data_current; +} + +/* Return the position of the end of the populated bytes in the region. */ + +offset_t file_data_end_position(file_t *file) +{ + return file->start_pos + file->data_end; +} + +/* Return the amount of remaining space in the region. */ + +offset_t file_data_space(file_t *file) +{ + return file_span(file) - file->data_current; +} + + + +/* Copy data to the given buffer from the current data position, updating the + position. */ + +void file_data_read(file_t *file, char *buf, size_t to_transfer) +{ + memcpy(buf, file_data_current(file), to_transfer); + + /* Update position details. */ + + file->data_current += to_transfer; +} + +/* Copy data from the given buffer to the current data position, updating the + position and the extent of populated data if this was exceeded. */ + +void file_data_write(file_t *file, char *buf, size_t to_transfer) +{ + memcpy(file_data_current(file), buf, to_transfer); + + /* Update position details. */ + + file->data_current += to_transfer; + + if (file->data_current > file->data_end) + file->data_end = file->data_current; +} + + + +/* Open two pipe endpoints using the given pipe server. */ + +long pipe_open(offset_t size, file_t *reader, file_t *writer, l4_cap_idx_t server) +{ + if (l4_is_invalid_cap(server)) + return -L4_EINVAL; + + client_PipeOpener opener(server); + + file_init(reader); + file_init(writer); + + /* Pipes can usually only be accessed via region navigation. */ + + reader->can_mmap = 0; + writer->can_mmap = 0; + + long err = opener.pipe(size, &reader->ref, &writer->ref); + if (err) + return err; + + err = pipe_next(writer) || pipe_next(reader); + + if (err) + { + file_close(reader); + file_close(writer); + } + + return err; +} + +/* Access the current region for a pipe endpoint. */ + +long pipe_current(file_t *pipe) +{ + client_Pipe _pipe(pipe->ref); + long err = _pipe.current_region(&pipe->data_end, &pipe->size); + char *memory = pipe->memory; + + if (err) + return err; + + pipe->end_pos = pipe->size; + + err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory); + if (err) + return err; + + if (memory != NULL) + ipc_detach_dataspace(memory); + + return L4_EOK; +} + +/* Access the next region for a pipe endpoint, updating the eventual size of + the current region. */ + +long pipe_next(file_t *pipe) +{ + client_Pipe _pipe(pipe->ref); + long err = _pipe.next_region(&pipe->data_end, &pipe->size); + char *memory = pipe->memory; + + if (err) + return err; + + pipe->end_pos = pipe->size; + + err = ipc_attach_dataspace(pipe->ref, file_span(pipe), (void **) &pipe->memory); + if (err) + return err; + + if (memory != NULL) + ipc_detach_dataspace(memory); + + return L4_EOK; +} + +/* Set the size of the written region. */ + +long pipe_written(file_t *pipe, offset_t size) +{ + if (size <= pipe->size) + { + pipe->data_end = size; + return L4_EOK; + } + else + return -L4_EINVAL; +} + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/Control --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/Control Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,3 @@ +requires: libstdc++ libc libipc libmem +provides: libfsserver +maintainer: paul@boddie.org.uk diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,4 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../../.. + +include $(L4DIR)/mk/subdir.mk diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,7 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../../.. + +PKGNAME = libfsserver +CONTRIB_HEADERS = 1 + +include $(L4DIR)/mk/include.mk diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/access_map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/access_map.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,60 @@ +/* + * An access map providing memory corresponding to file regions. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include + +#include +#include + + + +/* Collection types. */ + +typedef std::map _AccessMap; +typedef std::pair _AccessMapEntry; + + + +/* A mapping from file positions to flexpages. */ + +class AccessMap +{ +protected: + _AccessMap _flexpages; + std::mutex _lock; + +public: + Flexpage *find(offset_t position); + + void insert(Flexpage *flexpage); + + bool remove(PageOwner *owner, Flexpage *flexpage); + + void purge(PageOwner *owner, Pages *pages); + + void flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/accessor.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,63 @@ +/* + * Generic accessor functionality. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* A file accessor, providing flexpages corresponding to file regions. */ + +class Accessor +{ +protected: + offset_t _size; + + /* Data transfer helper methods. */ + + virtual void fill_populated(Flexpage *flexpage); + + virtual void flush_populated(Flexpage *flexpage); + +public: + fileid_t fileid; + + explicit Accessor(fileid_t fileid, offset_t size=0); + + virtual ~Accessor(); + + virtual offset_t get_size(); + + virtual void set_size(offset_t size); + + virtual void close(); + + virtual void open(); + + /* Data transfer methods. */ + + virtual void fill(Flexpage *flexpage); + + virtual void flush(Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/block_file_accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/block_file_accessor.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,48 @@ +/* + * A file accessor employing a rewritable memory area. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* A block file accessor, providing flexpages corresponding to the regions of + loaded files. */ + +class BlockFileAccessor : public Accessor +{ +protected: + char *_data; + + /* Data transfer helper methods. */ + + virtual void fill_populated(Flexpage *flexpage); + + virtual void flush_populated(Flexpage *flexpage); + +public: + explicit BlockFileAccessor(const char *path, fileid_t fileid); + + virtual void set_size(offset_t size); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/block_file_opener.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/block_file_opener.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,44 @@ +/* + * An opener for a file employing a rewritable memory area. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* Support for providing access to files. */ + +class BlockFileOpener : public HostFileOpener +{ +protected: + /* Configurable methods. */ + + virtual Accessor *make_accessor(fileid_t fileid); + +public: + explicit BlockFileOpener(Pages *pages) + : HostFileOpener(pages) + { + } +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/file_pager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/file_pager.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,69 @@ +/* + * File-specific pager functionality. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include + + + +/* A pager abstraction for a file. */ + +class FilePager : public Pager, public MappedFileObject +{ +protected: + FilePaging *_paging; + +public: + fileid_t fileid; + + explicit FilePager(fileid_t fileid, PageMapper *mapper, flags_t flags, + FilePaging *paging); + + virtual void close(); + + /* Server details. */ + + int expected_items(); + + ipc_server_handler_type handler(); + + void *interface() + { return static_cast(this); } + + /* File methods. */ + + virtual long flush(offset_t populated_size, offset_t *size); + + virtual long resize(offset_t *size); + + /* Pager and mapped file methods. */ + + virtual long map(offset_t offset, address_t hot_spot, flags_t flags, + l4_snd_fpage_t *region); + + virtual long mmap(offset_t position, offset_t length, offset_t *start_pos, + offset_t *end_pos, offset_t *size); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/file_paging.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/file_paging.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,80 @@ +/* + * General functionality supporting file paging. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +#include +#include +#include + + + +/* Mapping type from accessors to page mappers. */ + +typedef std::map FileMapping; +typedef std::pair FileMappingEntry; + + + +/* A registry of mappers for accessors. */ + +class FilePaging +{ +protected: + Pages *_pages; + + FileMapping _mappers; + std::mutex _lock; + + /* Pager initialisation methods. */ + + PageMapper *get_mapper(fileid_t fileid); + + Pager *get_pager(fileid_t fileid, flags_t flags); + + /* Configurable methods. */ + + virtual fileid_t get_fileid(const char *path) = 0; + + virtual flags_t get_flags(flags_t flags); + + virtual Accessor *make_accessor(fileid_t fileid) = 0; + + /* Mapper registry access. */ + + PageMapper *get(fileid_t fileid); + + void set(fileid_t fileid, PageMapper *mapper); + +public: + explicit FilePaging(Pages *pages); + + virtual ~FilePaging(); + + /* Methods for the pager. */ + + void detach_pager(fileid_t fileid, PageMapper *mapper); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/host_file_accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/host_file_accessor.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,53 @@ +/* + * A file accessor employing a "host" file provided via the C library. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include + + + +/* A host filesystem file accessor, providing flexpages corresponding to file + regions. */ + +class HostFileAccessor : public Accessor +{ +protected: + const char *_path; + FILE *_fp; + + /* Data transfer helper methods. */ + + virtual void fill_populated(Flexpage *flexpage); + + virtual void flush_populated(Flexpage *flexpage); + +public: + explicit HostFileAccessor(const char *path, fileid_t fileid); + + virtual void close(); + + virtual void open(); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/host_file_opener.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/host_file_opener.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,57 @@ +/* + * An opener for a "host" file provided via the C library. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include + + + +/* Collection types. */ + +typedef std::map FilePaths; +typedef std::pair FilePathEntry; + + + +/* Support for providing access to files. */ + +class HostFileOpener : public OpenerResource +{ +protected: + FilePaths _paths; + + /* Configurable methods. */ + + virtual fileid_t get_fileid(const char *path); + + virtual Accessor *make_accessor(fileid_t fileid); + +public: + explicit HostFileOpener(Pages *pages) + : OpenerResource(pages) + { + } +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/ipc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/ipc.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,36 @@ +/* + * Interprocess communication utilities. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include + + + +long ipc_prepare_flexpage(Flexpage *flexpage, offset_t offset, + offset_t max_offset, address_t hot_spot, + flags_t flags, l4_snd_fpage_t *region); + +void ipc_unmap_flexpage(Flexpage *flexpage); + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/opener_context_resource.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/opener_context_resource.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,72 @@ +/* + * A context resource offering support for opening files. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + + + +/* Forward declaration. */ + +class OpenerResource; + + + +/* Support for indicating files to be opened. */ + +class OpenerContextResource : public SimplePager, public OpenerContextObject +{ +protected: + OpenerResource *_opener; + +public: + explicit OpenerContextResource(OpenerResource *opener, Memory *memory=NULL); + + /* Server details. */ + + int expected_items(); + + ipc_server_handler_type handler(); + + void *interface() + { return static_cast(this); } + + /* Data access methods. */ + + char *get_path(); + + /* Opener context interface methods. */ + + long open(flags_t flags, offset_t *size, l4_cap_idx_t *file); + + /* Pager/dataspace methods. */ + + long map(unsigned long offset, address_t hot_spot, flags_t flags, + l4_snd_fpage_t *region) + { return SimplePager::map(offset, hot_spot, flags, region); } + + long info(unsigned long *size, unsigned long *flags) + { return SimplePager::info(size, flags); } +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/opener_resource.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/opener_resource.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,59 @@ +/* + * A resource offering support for creating contexts and opening files. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include + + + +/* Support for providing access to files. */ + +class OpenerResource : public Resource, public FilePaging, public Opener +{ +public: + explicit OpenerResource(Pages *pages); + + /* Server details. */ + + int expected_items(); + + ipc_server_handler_type handler(); + + void *interface() + { return static_cast(this); } + + /* Direct access methods. */ + + Pager *open(const char *path, flags_t flags); + + /* Opener interface methods. */ + + long context(l4_cap_idx_t *context); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/page_mapper.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/page_mapper.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,87 @@ +/* + * A page mapper providing memory pages to satisfy file accesses. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include + +#include + + + +/* A file mapper, associating flexpages with file regions. */ + +class PageMapper : public PageOwner +{ +protected: + AccessMap _map; + Accessor *_accessor; + Pages *_pages; + unsigned int _attached; + + /* Serialisation of accesses. */ + + std::mutex _lock; + + /* Internal flexpage retrieval methods. */ + + Flexpage *find(offset_t offset); + + Flexpage *flexpage(offset_t offset); + +public: + explicit PageMapper(Accessor *accessor, Pages *pages); + + /* Accounting methods. */ + + void attach(); + + unsigned int detach(); + + Accessor *accessor() + { return _accessor; } + + /* Interface for the pager. */ + + Flexpage *get(offset_t offset, flags_t flags); + + void queue(Flexpage *flexpage); + + void flush_all(offset_t start, offset_t size); + + offset_t get_data_size(); + + void set_data_size(offset_t size); + + /* Data transfer methods, implementing PageOwner. */ + + void fill(Flexpage *flexpage); + + void flush(Flexpage *flexpage, bool purge); + + /* Interface for the page collection, implementing PageOwner. */ + + void remove(Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/page_owner.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/page_owner.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,53 @@ +/* + * A page owner abstraction, indicating the current user of a memory region. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* The owner of a flexpage. */ + +class PageOwner +{ +public: + virtual ~PageOwner() + { + } + + virtual void fill(Flexpage *flexpage) + { + (void) flexpage; + } + + virtual void flush(Flexpage *flexpage, bool purge) + { + (void) flexpage; (void) purge; + } + + virtual void remove(Flexpage *flexpage) + { + (void) flexpage; + } +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/page_queue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/page_queue.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,69 @@ +/* + * A page queue abstraction. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +#include +#include +#include + + + +/* Collection types. */ + +typedef struct { Flexpage *flexpage; PageOwner *owner; } QueueEntry; +typedef std::list Queue; + +typedef std::pair Position; +typedef std::map Positions; + + + +/* A queue of managed pages. */ + +class PageQueue +{ +protected: + + /* Helper methods. */ + + virtual void discard(Queue &queue, Memory *memory); + + virtual bool remove(Queue &queue, Positions &positions, PageOwner *owner, Flexpage *flexpage); + +public: + virtual ~PageQueue(); + + virtual void close(Memory *memory) = 0; + + virtual void pop(PageOwner **owner, Flexpage **flexpage) = 0; + + virtual void push(PageOwner *owner, Flexpage *flexpage) = 0; + + virtual void push_front(PageOwner *owner, Flexpage *flexpage) = 0; + + virtual bool remove(PageOwner *owner, Flexpage *flexpage) = 0; +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/page_queue_partitioned.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/page_queue_partitioned.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,56 @@ +/* + * A page queue retaining two internal collections of memory pages. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +#include + + + +/* Queues of issued and available pages. */ + +class PageQueuePartitioned : public PageQueue +{ +protected: + Queue _issued, _available; + Positions _positions; + + std::mutex _lock; + std::condition_variable _counter; + + virtual bool _pop(QueueEntry *entry); + +public: + virtual void close(Memory *memory); + + virtual void pop(PageOwner **owner, Flexpage **flexpage); + + virtual void push(PageOwner *owner, Flexpage *flexpage); + + virtual void push_front(PageOwner *owner, Flexpage *flexpage); + + virtual bool remove(PageOwner *owner, Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/page_queue_shared.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/page_queue_shared.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,56 @@ +/* + * A page queue whose users take turns to access pages. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +#include + + + +/* A queue of issued pages. */ + +class PageQueueShared : public PageQueue +{ +protected: + Queue _queue; + Positions _positions; + + std::mutex _lock; + std::condition_variable _counter; + + virtual bool _pop(QueueEntry *entry); + +public: + virtual void close(Memory *memory); + + virtual void pop(PageOwner **owner, Flexpage **flexpage); + + virtual void push(PageOwner *owner, Flexpage *flexpage); + + virtual void push_front(PageOwner *owner, Flexpage *flexpage); + + virtual bool remove(PageOwner *owner, Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/pager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/pager.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,66 @@ +/* + * Generic pager functionality. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include +#include + + + +/* A pager exposing a dataspace. */ + +class Pager : public Resource +{ +protected: + offset_t _start, _size; + PageMapper *_mapper; + flags_t _flags; + +public: + explicit Pager(PageMapper *mapper, flags_t flags); + + virtual void close(); + + /* Paging methods. */ + + virtual long map(offset_t offset, address_t hot_spot, flags_t flags, + l4_snd_fpage_t *region); + + /* Limit methods. */ + + offset_t get_data_size(); + + /* File methods. */ + + virtual long flush(offset_t populated_size, offset_t *size); + + virtual long resize(offset_t *size); + + /* Mapped file methods. */ + + virtual long mmap(offset_t position, offset_t length, offset_t *start_pos, + offset_t *end_pos, offset_t *size); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/pages.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/pages.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,55 @@ +/* + * A page collection abstraction providing pages from a queue to users. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include +#include + + + +/* A page collection. */ + +class Pages +{ +protected: + Memory *_memory; + PageQueue *_queue; + +public: + explicit Pages(Memory *memory, PageQueue *queue); + + virtual ~Pages(); + + virtual Flexpage *remove(); + + virtual bool reserve(PageOwner *owner, Flexpage *flexpage); + + virtual Flexpage *flexpage(); + + virtual void queue(PageOwner *owner, Flexpage *flexpage); + + virtual void release(Flexpage *flexpage); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/pipe_accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/pipe_accessor.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,48 @@ +/* + * A pipe accessor merely resetting allocated memory for use. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* A pipe accessor, providing flexpages for pipe sections. */ + +class PipeAccessor : public Accessor +{ +protected: + + /* Data transfer helper methods. */ + + virtual void fill_populated(Flexpage *flexpage); + + virtual void flush_populated(Flexpage *flexpage); + +public: + explicit PipeAccessor(); + + virtual void close(); + + virtual void open(); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/pipe_opener_resource.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/pipe_opener_resource.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,57 @@ +/* + * A pipe opener resource. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include +#include + + + +/* Support for providing access to pipes. */ + +class PipeOpenerResource : public Resource, public PipeOpener +{ +protected: + Memory *_memory; + + long open_endpoint(PipePaging *paging, bool writing, l4_cap_idx_t *endpoint); + +public: + explicit PipeOpenerResource(Memory *memory); + + /* Server details. */ + + int expected_items(); + + ipc_server_handler_type handler(); + + void *interface() + { return static_cast(this); } + + /* PipeOpener interface methods. */ + + long pipe(offset_t size, l4_cap_idx_t *reader, l4_cap_idx_t *writer); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/pipe_pager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/pipe_pager.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,70 @@ +/* + * A pipe pager providing access to pipe content and navigation support. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include +#include + + + +/* A pager abstraction for a pipe. */ + +class PipePager : public Pager, public PipeObject +{ +protected: + PipePaging *_paging; + bool _writing; + + /* Helper methods. */ + + virtual long next_region_for_reader(offset_t *populated_size, offset_t *size); + + virtual long next_region_for_writer(offset_t *populated_size, offset_t *size); + +public: + explicit PipePager(PipePaging *paging, bool writer); + + virtual void close(); + + /* Server details. */ + + int expected_items(); + + ipc_server_handler_type handler(); + + void *interface() + { return static_cast(this); } + + /* Pager methods. */ + + virtual long map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region); + + /* Pipe methods. */ + + virtual long current_region(offset_t *populated_size, offset_t *size); + + virtual long next_region(offset_t *populated_size, offset_t *size); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/pipe_paging.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/pipe_paging.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,74 @@ +/* + * A pipe paging coordinator, permitting memory sharing pipe endpoints. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include + + + +/* Pipe paging support, maintaining the sequence of active regions or sections + in a pipe. */ + +class PipePaging +{ +protected: + Memory *_memory; + Pages *_pages; + PageQueue *_queue; + + /* Regions acting as files with their own accessors. */ + + PageMapper *_regions[2]; + PipeAccessor _accessors[2]; + + /* The first region is initially exposed to both reader and writer. */ + + int _reading = 0, _writing = 0; + + /* Pipe section/region size. */ + + offset_t _size; + + /* Endpoint status. */ + + unsigned int _endpoints = 2; + +public: + explicit PipePaging(Memory *memory, offset_t size); + + virtual void detach(); + + virtual offset_t region_size() + { return _size; } + + /* Region management. */ + + virtual PageMapper *add_region(); + + virtual PageMapper *current_region(); + + virtual PageMapper *next_region(); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/resource.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/resource.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,56 @@ +/* + * Common resource classes and functions. + * + * Copyright (C) 2018, 2019, 2020 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* A generic class for an object potentially needing to be closed after use. */ + +class Resource +{ +public: + virtual ~Resource() + { + } + + /* Server details. */ + + virtual int expected_items() = 0; + + virtual ipc_server_handler_type handler() = 0; + + virtual void *interface() = 0; + + /* Deallocation of resources. */ + + virtual void close() + { + } + + /* Activation. */ + + virtual void activate() + { + } +}; diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/resource_server.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/resource_server.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,76 @@ +/* + * Common resource server functions. + * + * Copyright (C) 2018, 2019, 2020 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + + + +/* Convenience abstraction for blocking servers. */ + +class ResourceServer +{ +protected: + Resource *_resource; + ipc_server_config_type *_config; + +public: + explicit ResourceServer(Resource *resource) + : _resource(resource) + { + _config = new ipc_server_config_type; + ipc_server_init_config(_config); + } + + /* Access to configuration. */ + + ipc_server_config_type *config() + { return _config; } + + /* Server IPC gate allocation. */ + + long bind(const char *name); + + /* Server initiation. */ + + long start(); + + long start_thread(); +}; + + + +/* Server initialisation. */ + +void resource_init_config(ipc_server_config_type *config, Resource *resource); + +void resource_set_config_threaded(ipc_server_config_type *config, + l4_cap_idx_t thread, int new_thread); + +/* Server initiation. */ + +long resource_start_config(ipc_server_config_type *config, Resource *resource); + +/* Server finalisation. */ + +void resource_thread_finaliser(ipc_server_config_type *config); diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/simple_pager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/simple_pager.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,51 @@ +/* + * A simple pager exposing a single memory region. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include +#include + + + +/* A simple pager exposing a single memory region as a dataspace. */ + +class SimplePager : public Dataspace, public Resource +{ +protected: + Memory *_memory; + Region *_region; + +public: + explicit SimplePager(Memory *memory=NULL); + + void close(); + + /* Paging methods. */ + + long map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region); + + long info(offset_t *size, flags_t *flags); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/test_file_accessor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/test_file_accessor.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,44 @@ +/* + * A test accessor producing generated content. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* A file accessor, providing flexpages corresponding to file regions. */ + +class TestFileAccessor : public Accessor +{ +protected: + + /* Data transfer helper methods. */ + + virtual void fill_populated(Flexpage *flexpage); + + virtual void flush_populated(Flexpage *flexpage); + +public: + explicit TestFileAccessor(fileid_t fileid, offset_t size=0); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/include/fsserver/test_file_opener.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/include/fsserver/test_file_opener.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,45 @@ +/* + * An opener for a test file containing generated content. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* Support for providing access to files. */ + +class TestFileOpener : public OpenerResource +{ +protected: + offset_t _file_size; + + /* Configurable methods. */ + + virtual fileid_t get_fileid(const char *path); + + virtual Accessor *make_accessor(fileid_t fileid); + +public: + explicit TestFileOpener(Pages *pages, offset_t file_size=0); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,80 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../../.. + +TARGET = libfsserver.so libfsserver.a +PC_FILENAME = libfsserver + +# Locations for interface input and generated output. + +IDL_DIR = $(L4DIR)/pkg/libsystypes/idl +IDL_MK_DIR = $(L4DIR)/idl4re/mk +IDL_BUILD_DIR = . +IDL_EXPORT_DIR = $(OBJ_BASE)/include/contrib/$(CONTRIB_INCDIR)/fsserver + +include $(IDL_MK_DIR)/idl.mk + +# Compound interfaces. + +mapped_file_object_NAME = MappedFileObject +mapped_file_object_INTERFACES = dataspace file mapped_file + +opener_context_object_NAME = OpenerContextObject +opener_context_object_INTERFACES = dataspace opener_context + +pipe_object_NAME = PipeObject +pipe_object_INTERFACES = dataspace pipe + +COMP_INTERFACES_CC = mapped_file_object opener_context_object pipe_object + +# Individual interfaces. + +SERVER_INTERFACES_CC = opener pipe_opener $(call common_interfaces,$(COMP_INTERFACES_CC)) + +# Generated and plain source files. + +SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC) $(COMP_INTERFACES_CC)) + +PLAIN_SRC_CC = \ + files/block_file_accessor.cc \ + files/block_file_opener.cc \ + files/file_pager.cc \ + files/file_paging.cc \ + files/host_file_accessor.cc \ + files/host_file_opener.cc \ + files/opener_context_resource.cc \ + files/opener_resource.cc \ + files/test_file_accessor.cc \ + files/test_file_opener.cc \ + generic/accessor.cc \ + generic/pager.cc \ + generic/resource_server.cc \ + generic/simple_pager.cc \ + mapping/access_map.cc \ + mapping/ipc.cc \ + mapping/page_mapper.cc \ + pages/page_queue.cc \ + pages/page_queue_partitioned.cc \ + pages/page_queue_shared.cc \ + pages/pages.cc \ + pipes/pipe_accessor.cc \ + pipes/pipe_opener_resource.cc \ + pipes/pipe_pager.cc \ + pipes/pipe_paging.cc + +# Normal definitions. + +SRC_CC = \ + $(SERVER_INTERFACES_SRC_CC) \ + $(PLAIN_SRC_CC) + +REQUIRES_LIBS = l4re_c-util libmem libipc libstdc++ libsystypes + +PRIVATE_INCDIR = $(PKGDIR)/include $(PKGDIR)/include/fsserver \ + $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR) + +CONTRIB_INCDIR = libfsserver + +include $(L4DIR)/mk/lib.mk +include $(IDL_MK_DIR)/interface_rules.mk + +$(PLAIN_SRC_CC): $(SERVER_INTERFACES_SRC_CC) diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/block_file_accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/block_file_accessor.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,127 @@ +/* + * A file accessor employing a rewritable memory area. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include + +#include + +#include "block_file_accessor.h" + + + +BlockFileAccessor::BlockFileAccessor(const char *path, fileid_t fileid) +: Accessor(fileid) +{ + /* Obtain the size of the file. */ + + struct stat buf; + + if (stat(path, &buf)) + { + _size = 0; + return; + } + + /* Allocate memory. */ + + _size = buf.st_size; + _data = (char *) malloc(_size); + + if (_data == NULL) + return; + + /* Load the file into memory and initialise the size. */ + + FILE *fp = fopen(path, "r"); + + if (fp == NULL) + { + free(_data); + return; + } + + _size = fread(_data, sizeof(char), _size, fp); + + fclose(fp); +} + +/* Update the size of the file. */ + +void BlockFileAccessor::set_size(offset_t size) +{ + void *new_data = realloc(_data, size); + + if (new_data != NULL) + { + _data = (char *) new_data; + + if (size > _size) + memset(_data + _size, 0, size - _size); + + Accessor::set_size(size); + } +} + +/* Data transfer helper methods. */ + +/* Fill the populated portion of a flexpage. */ + +void BlockFileAccessor::fill_populated(Flexpage *flexpage) +{ + offset_t filepos = flexpage->base_offset; + offset_t addr = flexpage->base_addr; + offset_t populated_size = std::min(flexpage->size, _size - filepos); + + /* Tag the region with file state. */ + + flexpage->region->fill(fileid, filepos); + + /* Fill the region with file content. */ + + memcpy((void *) addr, _data + filepos, populated_size); + + /* Pad the flexpage with zero. */ + + if (populated_size < flexpage->size) + memset((void *) (addr + populated_size), 0, flexpage->size - populated_size); +} + +/* Flush the populated portion of a flexpage. */ + +void BlockFileAccessor::flush_populated(Flexpage *flexpage) +{ + offset_t filepos = flexpage->base_offset; + offset_t addr = flexpage->base_addr; + offset_t populated_size = std::min(flexpage->size, _size - filepos); + + /* Remove the file state tag from the region. */ + + flexpage->region->flush(); + + /* Copy the populated region to the block memory. */ + + memcpy((void *) (_data + filepos), (const void *) addr, populated_size); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/block_file_opener.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/block_file_opener.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,37 @@ +/* + * An opener for a file employing a rewritable memory area. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "block_file_accessor.h" +#include "block_file_opener.h" + +/* Return a new accessor for 'fileid'. */ + +Accessor *BlockFileOpener::make_accessor(fileid_t fileid) +{ + FilePaths::iterator found = _paths.find(fileid); + + if (found != _paths.end()) + return new BlockFileAccessor(found->second, fileid); + else + return NULL; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/file_pager.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/file_pager.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,87 @@ +/* + * File-specific pager functionality. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "file_pager.h" +#include "mapped_file_object_server.h" + + + +/* Initialise a pager for a file with a unique file identifier and shared page + mapper for moderating access to loaded pages. */ + +FilePager::FilePager(fileid_t fileid, PageMapper *mapper, flags_t flags, + FilePaging *paging) +: Pager(mapper, flags), _paging(paging), fileid(fileid) +{ +} + +int FilePager::expected_items() +{ + return MappedFileObject_expected_items; +} + +ipc_server_handler_type FilePager::handler() +{ + return (ipc_server_handler_type) handle_MappedFileObject; +} + + + +/* Close the pager, removing the mapper from the paging registry if + appropriate. */ + +void FilePager::close() +{ + _paging->detach_pager(fileid, _mapper); +} + + + +/* File-specific operations. */ + +long FilePager::flush(offset_t populated_size, offset_t *size) +{ + return Pager::flush(populated_size, size); +} + +long FilePager::resize(offset_t *size) +{ + return Pager::resize(size); +} + +long FilePager::mmap(offset_t position, offset_t length, offset_t *start_pos, + offset_t *end_pos, offset_t *size) +{ + /* Set the limits of the paged region. */ + + return Pager::mmap(position, length, start_pos, end_pos, size); +} + + + +/* Generic pager operations. */ + +long FilePager::map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region) +{ + return Pager::map(offset, hot_spot, flags, region); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/file_paging.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/file_paging.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,128 @@ +/* + * General functionality supporting file paging. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "file_pager.h" +#include "file_paging.h" + +#include + + + +FilePaging::FilePaging(Pages *pages) +: _pages(pages) +{ +} + +FilePaging::~FilePaging() +{ +} + + + +/* Return any registered page mapper for the given 'fileid' or NULL if no such + mapper is registered. */ + +PageMapper *FilePaging::get(fileid_t fileid) +{ + FileMapping::iterator entry = _mappers.find(fileid); + PageMapper *mapper; + + if (entry == _mappers.end()) + mapper = NULL; + else + mapper = entry->second; + + return mapper; +} + +/* Register a page 'mapper' for the given 'fileid'. */ + +void FilePaging::set(fileid_t fileid, PageMapper *mapper) +{ + FileMapping::iterator entry = _mappers.find(fileid); + + if (entry == _mappers.end()) + _mappers[fileid] = mapper; +} + + + +/* Convert opening flags to map-compatible paging flags. */ + +flags_t FilePaging::get_flags(flags_t flags) +{ + return flags & (O_WRONLY | O_RDWR) ? L4RE_DS_MAP_FLAG_RW : L4RE_DS_MAP_FLAG_RO; +} + + + +/* Obtain a page mapper for the 'fileid' or register a new one in the + paging object. */ + +PageMapper *FilePaging::get_mapper(fileid_t fileid) +{ + /* Obtain any registered page mapper. */ + + PageMapper *mapper = get(fileid); + + if (mapper != NULL) + return mapper; + + /* Make an accessor and page mapper, registering the mapper. */ + + Accessor *accessor = make_accessor(fileid); + mapper = new PageMapper(accessor, _pages); + + set(fileid, mapper); + + return mapper; +} + + + +/* Return a pager initialised with a page mapper. */ + +Pager *FilePaging::get_pager(fileid_t fileid, flags_t flags) +{ + std::lock_guard guard(_lock); + + /* Initialise the pager with the mapper and a reference to this object for + closing the mapper and accessor. */ + + PageMapper *mapper = get_mapper(fileid); + return new FilePager(fileid, mapper, flags, this); +} + +/* Detach a pager, potentially removing its resources. */ + +void FilePaging::detach_pager(fileid_t fileid, PageMapper *mapper) +{ + std::lock_guard guard(_lock); + + if (!mapper->detach()) + { + _mappers.erase(fileid); + delete mapper->accessor(); + delete mapper; + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/host_file_accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/host_file_accessor.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,85 @@ +/* + * A file accessor employing a "host" file provided via the C library. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include + +#include "host_file_accessor.h" + +HostFileAccessor::HostFileAccessor(const char *path, fileid_t fileid) +: Accessor(fileid), _path(path) +{ + /* Initialise the size of the file. */ + + struct stat buf; + + if (!stat(_path, &buf)) + _size = buf.st_size; + else + _size = 0; +} + +/* Perform any closing operation on the file. */ + +void HostFileAccessor::close() +{ + fclose(_fp); +} + +/* Perform any opening operation on the file. */ + +void HostFileAccessor::open() +{ + _fp = fopen(_path, "r"); +} + +/* Data transfer helper methods. */ + +void HostFileAccessor::fill_populated(Flexpage *flexpage) +{ + offset_t filepos = flexpage->base_offset; + offset_t addr = flexpage->base_addr; + + /* Seek to the offset in the file. */ + + fseek(_fp, filepos, SEEK_SET); + + /* Tag the region with file state. */ + + flexpage->region->fill(fileid, filepos); + + /* Fill the region with file content. */ + + size_t nread = fread((void *) addr, sizeof(char), flexpage->size, _fp); + + /* Pad the flexpage with zero. */ + + memset((void *) (addr + nread), 0, flexpage->size - nread); +} + +void HostFileAccessor::flush_populated(Flexpage *flexpage) +{ + flexpage->region->flush(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/host_file_opener.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/host_file_opener.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,55 @@ +/* + * An opener for a "host" file provided via the C library. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include "host_file_accessor.h" +#include "host_file_opener.h" + +/* Return a file identifier for the given 'path'. */ + +fileid_t HostFileOpener::get_fileid(const char *path) +{ + struct stat statbuf; + + /* Obtain the inode number. + NOTE: This does not handle errors! */ + + stat(path, &statbuf); + + _paths.insert(FilePathEntry(statbuf.st_ino, path)); + + return statbuf.st_ino; +} + +/* Return a new accessor for 'fileid'. */ + +Accessor *HostFileOpener::make_accessor(fileid_t fileid) +{ + FilePaths::iterator found = _paths.find(fileid); + + if (found != _paths.end()) + return new HostFileAccessor(found->second, fileid); + else + return NULL; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/opener_context_resource.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/opener_context_resource.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,96 @@ +/* + * A context resource offering support for opening files. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "opener_context_resource.h" +#include "opener_context_object_server.h" +#include "opener_resource.h" +#include "resource_server.h" + +#include + + + +/* Support for providing access to files. */ + +OpenerContextResource::OpenerContextResource(OpenerResource *opener, Memory *memory) +: SimplePager(memory), _opener(opener) +{ +} + +int OpenerContextResource::expected_items() +{ + return OpenerContextObject_expected_items; +} + +ipc_server_handler_type OpenerContextResource::handler() +{ + return (ipc_server_handler_type) handle_OpenerContextObject; +} + + + +/* Data access methods. */ + +char *OpenerContextResource::get_path() +{ + char *buffer = _region->read(); + offset_t size = _region->size(); + + /* Confine the path to the limit of the buffer. */ + + if ((buffer != NULL) && (strnlen(buffer, size) < size)) + return buffer; + else + return NULL; +} + + + +/* Opener context interface methods. */ + +long OpenerContextResource::open(flags_t flags, offset_t *size, l4_cap_idx_t *file) +{ + char *path = get_path(); + + if (path == NULL) + return -L4_EINVAL; + + Pager *pager = _opener->open(path, flags); + + /* Complete the initialisation and start a server in a new thread. + If the thread does not start, the resource should be finalised. */ + + ResourceServer server(pager); + long err = server.start_thread(); + + if (!err) + { + /* Return the file size. */ + /* Return the server capability to the caller. */ + + *size = pager->get_data_size(); + *file = server.config()->server; + } + + return err; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/opener_resource.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/opener_resource.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,79 @@ +/* + * A resource offering support for creating contexts and opening files. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "opener_server.h" +#include "opener_resource.h" +#include "resource_server.h" + +/* Support for providing access to files. */ + +OpenerResource::OpenerResource(Pages *pages) +: FilePaging(pages) +{ +} + +int OpenerResource::expected_items() +{ + return Opener_expected_items; +} + +ipc_server_handler_type OpenerResource::handler() +{ + return (ipc_server_handler_type) handle_Opener; +} + + + +/* Return a pager object for the given path and flags. */ + +Pager *OpenerResource::open(const char *path, flags_t flags) +{ + fileid_t fileid = get_fileid(path); + + if (fileid == FILEID_INVALID) + return NULL; + + return get_pager(fileid, get_flags(flags)); +} + + + +/* Opener interface methods. */ + +long OpenerResource::context(l4_cap_idx_t *context) +{ + OpenerContextResource *resource = new OpenerContextResource(this); + + /* Complete the initialisation and start a server in a new thread. + If the thread does not start, the resource should be finalised. */ + + ResourceServer server(resource); + long err = server.start_thread(); + + /* Return the server capability to the caller. */ + + if (!err) + *context = server.config()->server; + + return err; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/test_file_accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/test_file_accessor.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,72 @@ +/* + * A test accessor producing generated content. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "test_file_accessor.h" + +TestFileAccessor::TestFileAccessor(fileid_t fileid, offset_t size) +: Accessor(fileid, size) +{ +} + +/* Data transfer helper methods. */ + +void TestFileAccessor::fill_populated(Flexpage *flexpage) +{ + Region *region = flexpage->region; + offset_t filepos = flexpage->base_offset; + + /* Tag the region with file state. */ + + region->fill(fileid, filepos); + + /* Write some data to each page of the flexpage in each region. This + allows each page to be tested regardless of how large each flexpage + or region is. */ + + offset_t addr = flexpage->base_addr; + offset_t limit = addr + flexpage->size; + + while (addr < limit) + { + /* Overwrite enough of any previous data to make the new data + readable. */ + + char tag[32]; + + sprintf(tag, "%ld:%ld", fileid, filepos); + + memset((void *) addr, 0, strlen(tag) + 1); + strcpy((char *) addr, tag); + + filepos += PAGE_SIZE; + addr += PAGE_SIZE; + } +} + +void TestFileAccessor::flush_populated(Flexpage *flexpage) +{ + flexpage->region->flush(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/files/test_file_opener.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/files/test_file_opener.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,50 @@ +/* + * An opener for a test file containing generated content. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "test_file_accessor.h" +#include "test_file_opener.h" + +#include + +/* Support for providing access to files. */ + +TestFileOpener::TestFileOpener(Pages *pages, offset_t file_size) +: OpenerResource(pages), _file_size(file_size) +{ +} + +/* Return a file identifier for the given 'path'. */ + +fileid_t TestFileOpener::get_fileid(const char *path) +{ + /* NOTE: Just convert the path to a number. */ + + return atol(path); +} + +/* Return a new accessor for 'fileid'. */ + +Accessor *TestFileOpener::make_accessor(fileid_t fileid) +{ + return new TestFileAccessor(fileid, _file_size); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/generic/accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/generic/accessor.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,98 @@ +/* + * Generic accessor functionality. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "accessor.h" + +#include + + + +Accessor::Accessor(fileid_t fileid, offset_t size) +: _size(size), fileid(fileid) +{ +} + +Accessor::~Accessor() +{ +} + +/* Return the size of the file. */ + +offset_t Accessor::get_size() +{ + return _size; +} + +/* Update the size of the file. */ + +void Accessor::set_size(offset_t size) +{ + _size = size; +} + +/* Perform any closing operation on the file. */ + +void Accessor::close() +{ +} + +/* Perform any opening operation on the file. */ + +void Accessor::open() +{ +} + +/* Data transfer methods. */ + +void Accessor::fill(Flexpage *flexpage) +{ + /* Filling completely beyond the end of file should produce an empty + flexpage. This could potentially be a shared read-only flexpage that + would be replaced by an independent writable flexpage if ever written. */ + + if (flexpage->base_offset < _size) + fill_populated(flexpage); + else + memset((void *) flexpage->base_addr, 0, flexpage->size); +} + +void Accessor::flush(Flexpage *flexpage) +{ + /* Flushing completely beyond the end of file should discard the + flexpage. */ + + if (flexpage->base_offset < _size) + flush_populated(flexpage); +} + +/* Data transfer helper methods. */ + +void Accessor::fill_populated(Flexpage *flexpage) +{ + (void) flexpage; +} + +void Accessor::flush_populated(Flexpage *flexpage) +{ + (void) flexpage; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/generic/pager.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/generic/pager.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,128 @@ +/* + * Generic pager functionality. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "dataspace_server.h" +#include "ipc.h" +#include "pager.h" + + + +/* Initialise the pager with a page mapper and the given flags controlling + access to a file. */ + +Pager::Pager(PageMapper *mapper, flags_t flags) +: _start(0), _size(0), _mapper(mapper), _flags(flags) +{ + /* Some pagers may not be initialised with a mapper. */ + + if (_mapper != NULL) + _mapper->attach(); +} + +/* Close the pager. */ + +void Pager::close() +{ + if (_mapper != NULL) + _mapper->detach(); +} + +/* Flush data to the file. */ + +long Pager::flush(offset_t populated_size, offset_t *size) +{ + _mapper->flush_all(_start, populated_size); + + *size = _mapper->get_data_size(); + return L4_EOK; +} + +/* Resize the underlying file. */ + +long Pager::resize(offset_t *size) +{ + _mapper->set_data_size(*size); + + *size = _mapper->get_data_size(); + return L4_EOK; +} + +/* Expose a region of the file. */ + +long Pager::mmap(offset_t position, offset_t length, offset_t *start_pos, + offset_t *end_pos, offset_t *size) +{ + /* Define region characteristics. */ + + _start = trunc(position, PAGE_SIZE); + _size = round(position + length, PAGE_SIZE) - _start; + + /* Return the start and end positions plus populated extent. */ + + *start_pos = _start; + *end_pos = _start + _size; + *size = _mapper->get_data_size(); + + return L4_EOK; +} + +/* Map a flexpage corresponding to the dataspace 'offset' involving a 'hot_spot' + (flexpage offset). */ + +long Pager::map(offset_t offset, address_t hot_spot, flags_t flags, + l4_snd_fpage_t *region) +{ + offset_t file_offset = _start + offset; + offset_t max_offset = _start + _size; + + /* Prevent access beyond that defined by the pager. */ + + if (flags & ~_flags) + return -L4_EACCESS; + + Flexpage *flexpage = _mapper->get(file_offset, flags); + + /* Issue the flexpage via the IPC system. */ + + long err = ipc_prepare_flexpage(flexpage, file_offset, max_offset, hot_spot, + flags, region); + + if (!err) + err = complete_Dataspace_map(*region); + + /* After the flexpage is issued, it is queued for future reuse. */ + + _mapper->queue(flexpage); + + if (err) + return err; + + return IPC_MESSAGE_SENT; +} + +/* Return the total size of the data. */ + +offset_t Pager::get_data_size() +{ + return _mapper->get_data_size(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/generic/resource_server.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/generic/resource_server.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,131 @@ +/* + * Resource server functionality. + * + * Copyright (C) 2018, 2019, 2020, 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include +#include + +#include "resource_server.h" + + + +/* Convenience server methods. */ + +/* Bind to a named IPC gate capability. */ + +long ResourceServer::bind(const char *name) +{ + return ipc_server_bind(name, (l4_umword_t) _resource, &_config->server); +} + +/* Start in the same thread with no deletion notifications or finalisation. */ + +long ResourceServer::start() +{ + resource_init_config(_config, _resource); + _config->thread = pthread_l4_cap(pthread_self()); + return resource_start_config(_config, _resource); +} + +/* Start a new thread with deletion notifications and finalisation. */ + +long ResourceServer::start_thread() +{ + pthread_t thread; + pthread_attr_t attr; + long err; + + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + resource_init_config(_config, _resource); + + err = pthread_create(&thread, &attr, ipc_server_start_mainloop, _config); + if (err) + return err; + + resource_set_config_threaded(_config, pthread_l4_cap(thread), 1); + + return resource_start_config(_config, _resource); +} + + + +/* Initialise a server configuration for a resource. */ + +void resource_init_config(ipc_server_config_type *config, Resource *resource) +{ + config->handler_obj = resource->interface(); + config->finaliser_obj = resource; + config->expected_items = resource->expected_items(); + config->handler = resource->handler(); +} + +/* Set a configuration to be threaded. */ + +void resource_set_config_threaded(ipc_server_config_type *config, + l4_cap_idx_t thread, int new_thread) +{ + config->finaliser = resource_thread_finaliser; + config->new_thread = new_thread; + config->thread = thread; + config->notifications = 1; +} + +/* Activate a resource and start a server for it. */ + +long resource_start_config(ipc_server_config_type *config, Resource *resource) +{ + resource->activate(); + long err = ipc_server_start_config(config); + + /* Discard any server resources if starting it failed. */ + + if (err) + { + ipc_server_finalise_config(config); + ipc_server_discard_thread(config); + } + + return err; +} + + + +/* A finaliser for exposed resources. */ + +void resource_thread_finaliser(ipc_server_config_type *config) +{ + Resource *resource = reinterpret_cast(config->finaliser_obj); + + /* Close and delete the resource. */ + + resource->close(); + delete resource; + + /* Release the capabilities. */ + + ipc_server_finalise_config(config); + delete config; +} + +// vim: tabstop=2 expandtab shiftwidth=2 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/generic/simple_pager.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/generic/simple_pager.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,85 @@ +/* + * A simple pager exposing a single memory region. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include + +#include "dataspace_server.h" +#include "ipc.h" +#include "simple_pager.h" + + + +SimplePager::SimplePager(Memory *memory) +{ + if (memory == NULL) + _memory = new MemoryIncremental(); + else + _memory = memory; + + _region = _memory->region(); +} + +void SimplePager::close() +{ + if (_region != NULL) + { + _memory->release(_region); + _region = NULL; + } +} + +/* Map a flexpage corresponding to the dataspace 'offset' involving a 'hot_spot' + (flexpage offset). */ + +long SimplePager::map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region) +{ + Flexpage flexpage(_region); + + flexpage.reset(offset); + flexpage.upgrade(flags); + + /* Send the flexpage explicitly. */ + + long err = ipc_prepare_flexpage(&flexpage, offset, _region->size(), + hot_spot, flags, region); + + if (err) + return err; + + err = complete_Dataspace_map(*region); + + if (err) + return err; + + return IPC_MESSAGE_SENT; +} + +long SimplePager::info(offset_t *size, flags_t *flags) +{ + *size = _region->size(); + *flags = L4_FPAGE_RW; + + return L4_EOK; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/mapping/access_map.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/mapping/access_map.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,155 @@ +/* + * An access map providing memory corresponding to file regions. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "access_map.h" + +/* Return the flexpage supporting 'position'. */ + +Flexpage *AccessMap::find(offset_t position) +{ + std::lock_guard guard(_lock); + + _AccessMap::iterator it = _flexpages.upper_bound(position); + + if ((_flexpages.size() > 0) && (it != _flexpages.begin())) + { + it--; + + if (it->second->supports_position(position)) + return it->second; + } + + return NULL; +} + +/* Insert a mapping for 'flexpage'. */ + +void AccessMap::insert(Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + _flexpages.insert(_AccessMapEntry(flexpage->base_offset, flexpage)); +} + +/* Remove the mapping supported by 'flexpage'. + + The flexpage may have obtained by another mapper before being purged from + this object's mapping and before being purged from the queue (and thus + disassociated from this mapper), leaving an opportunity for another mapper to + now be removing it here. In such a situation, flushing has already occurred + and will not be performed again. */ + +bool AccessMap::remove(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + _AccessMap::iterator it = _flexpages.find(flexpage->base_offset); + + if (it != _flexpages.end()) + { + owner->flush(flexpage, true); + _flexpages.erase(flexpage->base_offset); + return true; + } + + return false; +} + +/* Purge all flexpages, using the 'owner' to flush their contents and + 'pages' to make the flexpages available to other accessors. */ + +void AccessMap::purge(PageOwner *owner, Pages *pages) +{ + std::lock_guard guard(_lock); + + _AccessMap::iterator it = _flexpages.begin(), entry; + + while (it != _flexpages.end()) + { + entry = it; + it++; + + Flexpage *flexpage = entry->second; + + /* Some flexpages may be unavailable in the queue. Only those + that can be reserved should be flushed and made available + again. */ + + if (pages->reserve(owner, flexpage)) + { + owner->flush(flexpage, true); + pages->release(flexpage); + _flexpages.erase(entry); + } + } +} + +/* Flush flexpages in the given range from 'start' with 'size', using 'owner' + and 'pages'. */ + +void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages) +{ + offset_t end = start + size; + + std::lock_guard guard(_lock); + + /* The start may be within an existing flexpage where the flexpage size is a + page multiple. */ + + _AccessMap::iterator it = _flexpages.upper_bound(start), entry; + + if ((_flexpages.size() > 0) && (it != _flexpages.begin())) + it--; + + /* Inspect flexpages at or after start until end. */ + + while (it != _flexpages.end()) + { + entry = it; + it++; + + Flexpage *flexpage = entry->second; + + if (flexpage->base_offset >= end) + break; + + /* Attempt to flush each flexpage, releasing ones that are no longer + needed. */ + + if (pages->reserve(owner, flexpage)) + { + owner->flush(flexpage, false); + + /* Where no users of the flexpage persist, release the flexpage for + reuse and remove this entry. */ + + if (!flexpage->valid()) + { + pages->release(flexpage); + _flexpages.erase(entry); + } + else + pages->queue(owner, flexpage); + } + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/mapping/ipc.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/mapping/ipc.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,68 @@ +/* + * Interprocess communication utilities. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include + +#include "ipc.h" + + +/* Make an L4 representation of the given flexpage. */ + +static l4_fpage_t ipc_get_fpage(SendFlexpage *send_flexpage) +{ + return l4_fpage(send_flexpage->base_addr, send_flexpage->order, + (send_flexpage->flags & L4RE_DS_MAP_FLAG_RW) ? L4_FPAGE_RW : L4_FPAGE_RO); +} + +/* Make a representation of a flexpage for the IPC system. */ + +long ipc_prepare_flexpage(Flexpage *flexpage, offset_t offset, + offset_t max_offset, address_t hot_spot, + flags_t flags, l4_snd_fpage_t *region) +{ + SendFlexpage send_flexpage = flexpage->to_send(offset, hot_spot, flags, + max_offset); + + /* NOTE: Consider l4_fpage_invalid() as the fpage here. */ + + if (!send_flexpage.order) + return -L4_ERANGE; + + region->fpage = ipc_get_fpage(&send_flexpage); + region->snd_base = hot_spot; + + return L4_EOK; +} + +/* Unmap the given flexpage. */ + +void ipc_unmap_flexpage(Flexpage *flexpage) +{ + SendFlexpage send_flexpage = flexpage->to_unmap(); + + l4_task_unmap(L4RE_THIS_TASK_CAP, ipc_get_fpage(&send_flexpage), L4_FP_OTHER_SPACES); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/mapping/page_mapper.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/mapping/page_mapper.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,196 @@ +/* + * A page mapper providing memory pages to satisfy file accesses. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "ipc.h" +#include "page_mapper.h" + + + +PageMapper::PageMapper(Accessor *accessor, Pages *pages) +: _accessor(accessor), _pages(pages), _attached(0) +{ +} + +/* Accounting methods. */ + +/* Attach a pager, opening the accessor if required. */ + +void PageMapper::attach() +{ + std::lock_guard guard(_lock); + + if (!_attached) + _accessor->open(); + + _attached += 1; +} + +/* Detach a pager, purging active pages and closing the accessor if no more + pagers are attached. Return whether any pagers are still attached. */ + +unsigned int PageMapper::detach() +{ + std::lock_guard guard(_lock); + + if (_attached) + { + _attached -= 1; + + if (!_attached) + { + _map.purge(this, _pages); + _accessor->close(); + } + } + + return _attached; +} + +/* Interface for the pager. */ + +/* Return a flexpage providing access to the indicated file 'offset'. + + The returned flexpage will either be an existing, compatible flexpage or a + completely new flexpage. + + This method locks the mapper to prevent concurrent queries with the same + details, with the lock held until the queue operation releases the lock. */ + +Flexpage *PageMapper::get(offset_t offset, flags_t flags) +{ + _lock.lock(); + + Flexpage *f = find(offset); + + if (f == NULL) + f = flexpage(offset); + + /* Record a new user of the flexpage and upgrade the access flags. */ + + f->increment(); + f->upgrade(flags); + return f; +} + +/* Queue the given 'flexpage' in the page collection, making it available for + eventual reuse. + + This method unlocks the mapper. */ + +void PageMapper::queue(Flexpage *flexpage) +{ + _pages->queue(this, flexpage); + + _lock.unlock(); +} + +/* Flush pages in the given range from 'start' with 'size'. */ + +void PageMapper::flush_all(offset_t start, offset_t size) +{ + std::lock_guard guard(_lock); + + _map.flush_all(start, size, this, _pages); +} + +/* Return the maximum extent of the mapped resource. */ + +offset_t PageMapper::get_data_size() +{ + return _accessor->get_size(); +} + +/* Set the maximum extent of the mapped resource. */ + +void PageMapper::set_data_size(offset_t size) +{ + _accessor->set_size(size); +} + +/* Internal flexpage retrieval methods. */ + +/* Find an existing flexpage for 'offset'. Where the accessor has registered a + compatible flexpage, an attempt is made to reserve it in the page collection; + if this succeeds, the flexpage is returned. Otherwise, NULL is returned. */ + +Flexpage *PageMapper::find(offset_t offset) +{ + Flexpage *flexpage = _map.find(offset); + + /* Between finding and reserving a flexpage, there is a possibility that + another accessor might acquire the flexpage, issue it, and even purge + it. */ + + if ((flexpage != NULL) && _pages->reserve(this, flexpage)) + return flexpage; + else + return NULL; +} + +/* Obtain a new flexpage for the file 'offset'. If the page collection is unable + to obtain a completely new flexpage, an existing flexpage is requested from + the page collection and recycled. + + The obtained flexpage is filled with content. */ + +Flexpage *PageMapper::flexpage(offset_t offset) +{ + Flexpage *flexpage = _pages->flexpage(); + + /* Obtain an existing flexpage and reuse it. */ + + if (flexpage == NULL) + flexpage = _pages->remove(); + + flexpage->reset(offset); + + fill(flexpage); + _map.insert(flexpage); + return flexpage; +} + +/* Interface for the page collection. */ + +/* Remove the record of 'flexpage' in this accessor, flushing its content. */ + +void PageMapper::remove(Flexpage *flexpage) +{ + _map.remove(this, flexpage); +} + +/* Data transfer methods. */ + +void PageMapper::fill(Flexpage *flexpage) +{ + _accessor->fill(flexpage); +} + +void PageMapper::flush(Flexpage *flexpage, bool purge) +{ + if (flexpage->decrement() || purge) + { + _accessor->flush(flexpage); + ipc_unmap_flexpage(flexpage); + flexpage->invalidate(); + } +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/pages/page_queue.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/pages/page_queue.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,66 @@ +/* + * A page queue abstraction. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "page_queue.h" + + + +PageQueue::~PageQueue() +{ +} + + + +void PageQueue::discard(Queue &queue, Memory *memory) +{ + while (!queue.empty()) + { + Flexpage *flexpage = queue.front().flexpage; + + queue.pop_front(); + memory->release(flexpage->region); + delete flexpage; + } +} + +bool PageQueue::remove(Queue &queue, Positions &positions, PageOwner *owner, Flexpage *flexpage) +{ + Positions::iterator position = positions.find(flexpage); + + if (position == positions.end()) + return false; + + /* The found owner may be different from the requesting owner or even NULL + if another owner has acquired and then purged its pages. Such a purged + flexpage is not immediately usable, however. */ + + Queue::iterator entry = position->second; + + if ((entry->owner == NULL) || (entry->owner != owner)) + return false; + + queue.erase(entry); + positions.erase(position); + + return true; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/pages/page_queue_partitioned.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/pages/page_queue_partitioned.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,133 @@ +/* + * A page queue retaining two internal collections of memory pages. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "page_queue_partitioned.h" + + + +/* Discard all queued flexpages. */ + +void PageQueuePartitioned::close(Memory *memory) +{ + discard(_available, memory); + discard(_issued, memory); +} + +/* Keep waiting for a potential queue non-empty condition. + Then, attempt to pop an entry from the queue. */ + +void PageQueuePartitioned::pop(PageOwner **owner, Flexpage **flexpage) +{ + std::unique_lock guard(_lock); + QueueEntry entry; + + while (1) + { + if (_pop(&entry)) + { + *owner = entry.owner; + *flexpage = entry.flexpage; + return; + } + else + _counter.wait(guard); + } +} + +/* Check the available pages queue for entries, returning false if no entries + are available, returning true and providing the details if an entry can be + removed from the front of the queue. */ + +bool PageQueuePartitioned::_pop(QueueEntry *entry) +{ + if (_available.empty()) + return false; + + *entry = _available.front(); + _available.pop_front(); + + return true; +} + +/* Push an entry for the given owner and flexpage to the appropriate queue. */ + +void PageQueuePartitioned::push(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + /* Record the entry and a position reference for the flexpage. */ + + Queue *queue; + Positions *positions = NULL; + + if (owner == NULL) + queue = &_available; + else + { + queue = &_issued; + positions = &_positions; + } + + queue->push_back((QueueEntry) {flexpage, owner}); + + if (positions != NULL) + { + Queue::iterator last = queue->end(); + last--; + positions->insert(Position(flexpage, last)); + } + + _counter.notify_one(); +} + +/* Push an entry to the front of the appropriate queue. */ + +void PageQueuePartitioned::push_front(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + Queue *queue; + Positions *positions = NULL; + + if (owner == NULL) + queue = &_available; + else + { + queue = &_issued; + positions = &_positions; + } + + queue->push_back((QueueEntry) {flexpage, owner}); + + if (positions != NULL) + positions->insert(Position(flexpage, queue->begin())); + + _counter.notify_one(); +} + +/* Remove an entry for the given owner and flexpage from the queue. */ + +bool PageQueuePartitioned::remove(PageOwner *owner, Flexpage *flexpage) +{ + return PageQueue::remove(_issued, _positions, owner, flexpage); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/pages/page_queue_shared.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/pages/page_queue_shared.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,112 @@ +/* + * A page queue whose users take turns to access pages. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "page_queue_shared.h" + + + +/* Discard all queued flexpages. */ + +void PageQueueShared::close(Memory *memory) +{ + discard(_queue, memory); +} + +/* Keep waiting for a potential queue non-empty condition. + Then, attempt to pop an entry from the queue. */ + +void PageQueueShared::pop(PageOwner **owner, Flexpage **flexpage) +{ + std::unique_lock guard(_lock); + QueueEntry entry; + + while (1) + { + if (_pop(&entry)) + { + *owner = entry.owner; + *flexpage = entry.flexpage; + return; + } + else + _counter.wait(guard); + } +} + +/* Check the queue for entries, returning false if no entries are available, + returning true and providing the details if an entry can be removed from the + front of the queue. */ + +bool PageQueueShared::_pop(QueueEntry *entry) +{ + if (_queue.empty()) + return false; + + *entry = _queue.front(); + _queue.pop_front(); + + /* Remove any position reference for the flexpage. */ + + Positions::iterator position = _positions.find(entry->flexpage); + + if (position != _positions.end()) + _positions.erase(position); + + return true; +} + +/* Push an entry for the given owner and flexpage to the queue. */ + +void PageQueueShared::push(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + /* Record the entry and a position reference for the flexpage. */ + + _queue.push_back((QueueEntry) {flexpage, owner}); + + Queue::iterator last = _queue.end(); + last--; + _positions.insert(Position(flexpage, last)); + + _counter.notify_one(); +} + +/* Push an entry to the front of the queue. */ + +void PageQueueShared::push_front(PageOwner *owner, Flexpage *flexpage) +{ + std::lock_guard guard(_lock); + + _queue.push_back((QueueEntry) {flexpage, owner}); + _positions.insert(Position(flexpage, _queue.begin())); + + _counter.notify_one(); +} + +/* Remove an entry for the given owner and flexpage from the queue. */ + +bool PageQueueShared::remove(PageOwner *owner, Flexpage *flexpage) +{ + return PageQueue::remove(_queue, _positions, owner, flexpage); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/pages/pages.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/pages/pages.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,89 @@ +/* + * A page collection abstraction providing pages from a queue to users. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include "pages.h" + + + +Pages::Pages(Memory *memory, PageQueue *queue) +: _memory(memory), _queue(queue) +{ +} + +Pages::~Pages() +{ + _queue->close(_memory); +} + +/* Remove the first flexpage in the queue. If its owner exists, remove it from + the owner (retiring the content). Return the flexpage for reuse. */ + +Flexpage *Pages::remove() +{ + PageOwner *owner; + Flexpage *flexpage; + + _queue->pop(&owner, &flexpage); + + if (owner != NULL) + owner->remove(flexpage); + + return flexpage; +} + +/* Reserve 'flexpage' by removing it from this collection. */ + +bool Pages::reserve(PageOwner *owner, Flexpage *flexpage) +{ + return _queue->remove(owner, flexpage); +} + +/* Obtain a new flexpage. Return the flexpage or None if no new flexpage could + be created. */ + +Flexpage *Pages::flexpage() +{ + Region *region = _memory->region(); + + if (region != NULL) + return new Flexpage(region); + else + return NULL; +} + +/* Queue an entry associating the given 'owner' and 'flexpage'. */ + +void Pages::queue(PageOwner *owner, Flexpage *flexpage) +{ + _queue->push(owner, flexpage); +} + +/* Push an entry for 'flexpage' without owner association for immediate + reuse. */ + +void Pages::release(Flexpage *flexpage) +{ + _queue->push_front(NULL, flexpage); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/pipes/pipe_accessor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/pipes/pipe_accessor.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,64 @@ +/* + * A pipe accessor merely resetting allocated memory for use. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "pipe_accessor.h" + +#include + +PipeAccessor::PipeAccessor() +: Accessor(0) +{ +} + +/* Perform any closing operation on the file. */ + +void PipeAccessor::close() +{ +} + +/* Perform any opening operation on the file. */ + +void PipeAccessor::open() +{ +} + +/* Data transfer helper methods. */ + +void PipeAccessor::fill_populated(Flexpage *flexpage) +{ + offset_t filepos = flexpage->base_offset; + offset_t addr = flexpage->base_addr; + + /* Tag the region with file state. */ + + flexpage->region->fill(fileid, filepos); + + /* File the flexpage with zero. */ + + memset((void *) addr, 0, flexpage->size); +} + +void PipeAccessor::flush_populated(Flexpage *flexpage) +{ + flexpage->region->flush(); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/pipes/pipe_opener_resource.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/pipes/pipe_opener_resource.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,85 @@ +/* + * A pipe opener resource. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include "pipe_opener_resource.h" +#include "pipe_opener_server.h" +#include "pipe_pager.h" +#include "resource_server.h" + + + +/* Support for providing access to pipes. */ + +PipeOpenerResource::PipeOpenerResource(Memory *memory) +: _memory(memory) +{ +} + +int PipeOpenerResource::expected_items() +{ + return PipeOpener_expected_items; +} + +ipc_server_handler_type PipeOpenerResource::handler() +{ + return (ipc_server_handler_type) handle_PipeOpener; +} + + + +/* Pipe opener interface methods. */ + +long PipeOpenerResource::pipe(offset_t size, l4_cap_idx_t *reader, l4_cap_idx_t *writer) +{ + /* Both endpoints will employ a common paging coordinator. */ + + PipePaging *paging = new PipePaging(_memory, size); + + /* Each endpoint will have its own pager. */ + + /* NOTE: Failure to open an endpoint should invalidate both, plus the + paging object. Also, any active server thread would need to be + cancelled. */ + + return open_endpoint(paging, false, reader) || open_endpoint(paging, true, writer); +} + +long PipeOpenerResource::open_endpoint(PipePaging *paging, bool writing, l4_cap_idx_t *endpoint) +{ + PipePager *pager = new PipePager(paging, writing); + + /* Start the endpoint server in a new thread. + If the thread does not start, the resource should be finalised. */ + + ResourceServer server(pager); + long err = server.start_thread(); + + /* Return the server capability to the caller. */ + + if (!err) + *endpoint = server.config()->server; + + return err; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/pipes/pipe_pager.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/pipes/pipe_pager.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,126 @@ +/* + * A pipe pager providing access to pipe content and navigation support. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "pipe_pager.h" +#include "pipe_object_server.h" + + + +/* Initialise a pager for a pipe with a shared page mapper for moderating + access to loaded pages. At first, no mapper will be configured: this must be + done by requesting a region. */ + +PipePager::PipePager(PipePaging *paging, bool writing) +: Pager(NULL, writing ? L4RE_DS_MAP_FLAG_RW : L4RE_DS_MAP_FLAG_RO), + _paging(paging), _writing(writing) +{ + /* Initialise the size of the paged region. */ + + _size = _paging->region_size(); +} + +int PipePager::expected_items() +{ + return PipeObject_expected_items; +} + +ipc_server_handler_type PipePager::handler() +{ + return (ipc_server_handler_type) handle_PipeObject; +} + + + +/* Close the pager, releasing the paging coordinator for the pipe. This will + release all active page mappers. */ + +void PipePager::close() +{ + _paging->detach(); +} + +/* Support paging. */ + +long PipePager::map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region) +{ + return Pager::map(offset, hot_spot, flags, region); +} + + + +/* Return details of the current region. */ + +long PipePager::current_region(offset_t *populated_size, offset_t *size) +{ + if (_mapper != NULL) + { + *populated_size = _mapper->get_data_size(); + *size = _size; + return L4_EOK; + } + else + return -L4_EIO; +} + +/* Obtain the next region and its details. */ + +long PipePager::next_region(offset_t *populated_size, offset_t *size) +{ + /* Obtain a new region if writing. */ + + if (_writing) + return next_region_for_writer(populated_size, size); + else + return next_region_for_reader(populated_size, size); +} + +long PipePager::next_region_for_reader(offset_t *populated_size, offset_t *size) +{ + PageMapper *mapper = _paging->next_region(); + + if (mapper == NULL) + return -L4_EIO; + + _mapper = mapper; + + return current_region(populated_size, size); +} + +long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size) +{ + /* Set the populated size before moving on. */ + + if (_mapper != NULL) + _mapper->set_data_size(*populated_size); + + /* Obtain the page mapper for the region. */ + + PageMapper *mapper = _paging->add_region(); + + if (mapper == NULL) + return -L4_EIO; + + _mapper = mapper; + + return current_region(populated_size, size); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libfsserver/lib/pipes/pipe_paging.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libfsserver/lib/pipes/pipe_paging.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,140 @@ +/* + * A pipe paging coordinator, permitting memory sharing pipe endpoints. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "page_queue_partitioned.h" +#include "pipe_paging.h" + + + +PipePaging::PipePaging(Memory *memory, offset_t size) +: _memory(NULL), _size(size) +{ + /* Reserve space for two pipe regions. */ + + _memory = new MemoryPreallocated(memory, round(size, memory->region_size()) * 2); + _queue = new PageQueuePartitioned(); + _pages = new Pages(_memory, _queue); + + for (unsigned int i = 0; i < 2; i++) + _regions[i] = NULL; +} + +/* Detach one endpoint. */ + +void PipePaging::detach() +{ + if (!_endpoints) + return; + else + _endpoints--; + + /* Return if the other endpoint is attached. */ + + if (_endpoints) + return; + + /* Discard all regions from the pipe. */ + + for (unsigned int i = 0; i < 2; i++) + { + PageMapper *mapper = _regions[i]; + + if (mapper != NULL) + { + mapper->detach(); + _regions[i] = NULL; + delete mapper; + } + } + + /* Delete the page collection and related objects. */ + + delete _pages; + delete _queue; + delete _memory; +} + +/* Add a region to the sequence. */ + +PageMapper *PipePaging::add_region() +{ + /* If the writer already accesses a different region to the reader, no new + region is added. */ + + if (_writing != _reading) + return NULL; + + /* Select the other region of the pair being maintained. */ + + _writing = 1 - _writing; + + /* Make a new mapper for the region. */ + + PageMapper *mapper = new PageMapper(&_accessors[_writing], _pages); + + /* Initialise and record the mapper. */ + + mapper->attach(); + mapper->set_data_size(0); + + _regions[_writing] = mapper; + return mapper; +} + +/* Return the current region for reading. */ + +PageMapper *PipePaging::current_region() +{ + return _regions[_reading]; +} + +/* Return the next region for the reader if the writer is using a different one. + Otherwise, return NULL. */ + +PageMapper *PipePaging::next_region() +{ + /* If the reader already accesses the same region to the writer, no next + region can be obtained. */ + + if (_reading == _writing) + return NULL; + + /* Detach and discard the current page mapper. */ + + PageMapper *mapper = _regions[_reading]; + + if (mapper != NULL) + { + mapper->detach(); + _regions[_reading] = NULL; + delete mapper; + } + + /* Return the next region. */ + + _reading = 1 - _reading; + return _regions[_reading]; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/Control --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/Control Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,3 @@ +requires: libstdc++ libc libsystypes +provides: libmem +maintainer: paul@boddie.org.uk diff -r bf981cb9a709 -r b6dab1e89e3c libmem/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,4 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../../.. + +include $(L4DIR)/mk/subdir.mk diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,7 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../../.. + +PKGNAME = libmem +CONTRIB_HEADERS = 1 + +include $(L4DIR)/mk/include.mk diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/mem/flexpage.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/mem/flexpage.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,76 @@ +/* + * A flexpage abstraction. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include +#include + + + +/* A flexpage abstraction. */ + +class Flexpage +{ +protected: + unsigned int _counter; + flags_t _flags; + +public: + Region *region; + + /* General flexpage characteristics. */ + + offset_t base_addr, size; + offset_t base_offset; + + /* Transient debugging information. */ + + offset_t page_addr, page_offset; + + /* Associate a flexpage with a memory 'region'. */ + + explicit Flexpage(Region *region) : region(region) + { + } + + void reset(offset_t offset); + + bool decrement(); + + void increment(); + + void invalidate(); + + bool valid(); + + bool supports_position(offset_t position); + + void upgrade(flags_t flags); + + SendFlexpage to_send(offset_t offset, offset_t hot_spot, flags_t flags, + offset_t max_offset=0); + + SendFlexpage to_unmap(); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/mem/memory.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/mem/memory.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,44 @@ +/* + * A generic memory pool abstraction. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* A memory pool interface. */ + +class Memory +{ +public: + virtual ~Memory() + { + } + + virtual Region *region() = 0; + + virtual offset_t region_size() = 0; + + virtual void release(Region *region) = 0; +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/mem/memory_incremental.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/mem/memory_incremental.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,61 @@ +/* + * A memory pool allocating a region at a time from the system. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include + +#include +#include + + + +/* A memory pool abstraction. */ + +class MemoryIncremental : public Memory +{ +protected: + std::mutex _lock; + + unsigned int _limit; + offset_t _region_size; + bool _limited; + + Region *allocate(offset_t size); + +public: + explicit MemoryIncremental(unsigned int limit, offset_t region_size=PAGE_SIZE); + + explicit MemoryIncremental(); + + virtual Region *region(offset_t size); + + virtual Region *region(); + + virtual offset_t region_size() + { return _region_size; } + + virtual void release(Region *region); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/mem/memory_preallocated.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/mem/memory_preallocated.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,59 @@ +/* + * A memory pool providing regions from a preallocated amount of memory. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include +#include + +#include + + + +/* A memory pool abstraction. */ + +class MemoryPreallocated : public Memory +{ +protected: + std::mutex _lock; + std::list _regions; + + Memory *_memory; + offset_t _amount; + +public: + explicit MemoryPreallocated(Memory *memory, offset_t amount); + + explicit MemoryPreallocated(); + + virtual ~MemoryPreallocated(); + + virtual Region *region(); + + virtual offset_t region_size() + { return _memory->region_size(); } + + virtual void release(Region *region); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/mem/memory_utils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/mem/memory_utils.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,46 @@ +/* + * Memory quantity calculation utilities. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#define PAGE_SIZE 4096 + + + +/* Address arithmetic. */ + +offset_t page(unsigned int n); + +unsigned int page_order(offset_t size); + +offset_t round(offset_t value, offset_t increment); + +offset_t round_multiple(offset_t value, offset_t increment); + +offset_t trunc(offset_t value, offset_t increment); + +offset_t trunc_multiple(offset_t value, offset_t increment); + +offset_t max_multiple(offset_t start, offset_t end, offset_t increment); + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/mem/region.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/mem/region.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,80 @@ +/* + * Memory region abstractions. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + +#include "types.h" + + + +/* Region-related state information. */ + +class RegionState +{ +public: + unsigned long size; + fileid_t fileid; + offset_t filepos; + + explicit RegionState(unsigned long size=0, fileid_t fileid=0, offset_t filepos=0); + + void fill(fileid_t fileid, offset_t filepos); + + bool valid() { return size != 0; } +}; + + + +/* A memory region abstraction. */ + +class Region +{ +public: + offset_t start, end; + + /* Debugging information. */ + + RegionState state; + + /* Methods. */ + + explicit Region(offset_t start, offset_t end); + + virtual ~Region(); + + offset_t size(); + + int compare(Region *other); + + void fill(fileid_t fileid, offset_t filepos); + + void flush(); + + /* Simulation methods. */ + + char *read(offset_t offset=0); + + void write(const char *data, offset_t offset=0); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/mem/send_flexpage.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/mem/send_flexpage.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,44 @@ +/* + * A "send" flexpage abstraction for communicating memory mappings. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include + + + +/* A "send" flexpage abstraction. */ + +class SendFlexpage +{ +public: + offset_t base_addr; + unsigned int order; + flags_t flags; + + explicit SendFlexpage(offset_t base_addr, unsigned int order, + flags_t flags) + : base_addr(base_addr), order(order), flags(flags) + { + } +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/include/mem/types.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/include/mem/types.h Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,32 @@ +/* + * Miscellaneous types. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + + + +/* File identification. */ + +typedef unsigned long fileid_t; + +#define FILEID_INVALID (~0UL) + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/lib/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/lib/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,4 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../../.. + +include $(L4DIR)/mk/subdir.mk diff -r bf981cb9a709 -r b6dab1e89e3c libmem/lib/src/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/lib/src/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,16 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../../.. + +TARGET = libmem.so libmem.a +PC_FILENAME = libmem + +SRC_CC = \ + flexpage.cc memory_incremental.cc memory_preallocated.cc \ + memory_utils.cc region.cc + +REQUIRES_LIBS = l4re_c-util libstdc++ libsystypes + +PRIVATE_INCDIR = $(PKGDIR)/include $(PKGDIR)/include/mem +CONTRIB_INCDIR = libmem + +include $(L4DIR)/mk/lib.mk diff -r bf981cb9a709 -r b6dab1e89e3c libmem/lib/src/flexpage.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/lib/src/flexpage.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,163 @@ +/* + * A flexpage abstraction. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include + +#include "flexpage.h" + + + +/* Reset the flexpage using 'offset', being the file offset. */ + +void Flexpage::reset(offset_t offset) +{ + _counter = 0; + + /* By definition (see "Flexible-Sized Page Objects - Object-Orientation + in Operation Systems"), flexpages are aligned to multiples of their + size. + + The size of the flexpage depends on the amount of space around the + accessed page. It cannot exceed the size of the memory region. */ + + size = max_multiple(region->start, region->end, PAGE_SIZE); + + /* The base address of the flexpage is computed from the region start + and flexpage size. It will be no lower than the region start. + + Sent flexpages may use higher bases due to receive window constraints, + these being communicated by the "hot spot". */ + + base_addr = round(region->start, size); + + /* Get the file offset for the base of the flexpage. This will be a + multiple of the flexpage size for alignment purposes. */ + + base_offset = trunc(offset, size); + + /* The page being accessed is relative to the base. + (This is transient information recording the initialising access + details.) */ + + page_offset = trunc(offset - base_offset, PAGE_SIZE); + page_addr = base_addr + page_offset; +} + +bool Flexpage::decrement() +{ + if (_counter) + { + _counter--; + return _counter == 0; + } + else + return 0; +} + +void Flexpage::increment() +{ + _counter++; +} + +void Flexpage::invalidate() +{ + _counter = 0; +} + +bool Flexpage::valid() +{ + return _counter != 0; +} + +/* Return whether the flexpage supports the given file 'position'. */ + +bool Flexpage::supports_position(offset_t position) +{ + return (base_offset <= position) && (position < (base_offset + size)); +} + +/* Upgrade the flags involved with this flexpage. This is used to track the + maximal flags employed by the different pagers, with the result being used in + unmap operations. */ + +void Flexpage::upgrade(flags_t flags) +{ + if (flags && (flags != _flags)) + _flags |= flags; +} + +/* Return a "send" flexpage for an access to 'offset' by positioning it relative + to 'hot_spot' for the receive flexpage window. */ + +SendFlexpage Flexpage::to_send(offset_t offset, offset_t hot_spot, + flags_t flags, offset_t max_offset) +{ + /* The dataspace offset of the flexpage base is a multiple of the flexpage + size. */ + + offset_t receive_base_offset = trunc(offset, size); + + /* The offset of the accessed page within the flexpage is constrained by the + current flexpage size. */ + + offset_t page_offset = trunc(offset - receive_base_offset, PAGE_SIZE); + + /* The receive flexpage offset (hot spot) must be constrained to the + flexpage, both the size and the start. */ + + offset_t receive_size; + + if (max_offset) + { + receive_size = trunc_multiple(max_offset - receive_base_offset, PAGE_SIZE); + receive_size = std::min(size, receive_size); + } + else + receive_size = size; + + if (!receive_size) + return SendFlexpage(base_addr, page_order(0), flags); + + offset_t receive_page_offset = hot_spot % receive_size; + + while ((receive_size > PAGE_SIZE) && (receive_page_offset != page_offset)) + { + receive_size /= 2; + receive_page_offset = hot_spot % receive_size; + } + + /* The flexpage base address is adjusted using the difference in page + offsets. Where the receive flexpage offset is constained further, the + base address will be raised to become closer to the accessed page. */ + + offset_t adjustment = page_offset - receive_page_offset; + + return SendFlexpage(base_addr + adjustment, page_order(receive_size), flags); +} + +/* Return a representation of the flexpage for unmapping. */ + +SendFlexpage Flexpage::to_unmap() +{ + return SendFlexpage(base_addr, page_order(size), _flags); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/lib/src/memory_incremental.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/lib/src/memory_incremental.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,110 @@ +/* + * A memory pool allocating a region at a time from the system. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "memory_incremental.h" + +#include + +/* Initialise the memory pool with an optional 'limit' in pages. */ + +MemoryIncremental::MemoryIncremental(unsigned int limit, offset_t region_size) +: _limit(limit), _region_size(region_size) +{ + _limited = true; +} + +MemoryIncremental::MemoryIncremental() +: _region_size(PAGE_SIZE) +{ + _limited = false; +} + +/* Allocate a block of the given 'size'. */ + +Region *MemoryIncremental::allocate(offset_t size) +{ + /* Attempt to allocate aligned memory. */ + + void *current; + + /* Make the size appropriate for the invocation. */ + + size = round_multiple(size, PAGE_SIZE); + + if (posix_memalign(¤t, size, size)) + return NULL; + + return new Region((offset_t) current, (offset_t) current + size); +} + +/* Allocate a new region of the given 'size' rounded to the nearest page. */ + +Region *MemoryIncremental::region(offset_t size) +{ + std::lock_guard guard(_lock); + + offset_t rounded = round(size, PAGE_SIZE); + offset_t pages = rounded / PAGE_SIZE; + + /* Check for sufficient pages. */ + + if (!_limited || (_limit >= pages)) + { + /* Attempt to allocate aligned memory. */ + + Region *region = allocate(rounded); + + if (region == NULL) + return NULL; + + if (_limited) + _limit -= pages; + + return region; + } + + /* Return no region without sufficient pages. */ + + else + return NULL; +} + +Region *MemoryIncremental::region() +{ + return region(_region_size); +} + +/* Release the allocated 'region'. */ + +void MemoryIncremental::release(Region *region) +{ + std::lock_guard guard(_lock); + + offset_t rounded = round(region->size(), PAGE_SIZE); + offset_t pages = rounded / PAGE_SIZE; + + if (_limited) + _limit += pages; + + delete region; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/lib/src/memory_preallocated.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/lib/src/memory_preallocated.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,80 @@ +/* + * A memory pool providing regions from a preallocated amount of memory. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "memory_preallocated.h" + + + +/* Initialise the memory pool with the given amount in bytes. */ + +MemoryPreallocated::MemoryPreallocated(Memory *memory, offset_t amount) +: _memory(memory), _amount(amount) +{ + // NOTE: Handle allocation failure. + + offset_t remaining = amount; + + while (remaining) + { + _regions.push_back(memory->region()); + + if (memory->region_size() >= remaining) + break; + + remaining -= memory->region_size(); + } +} + +/* Discard all unused regions. */ + +MemoryPreallocated::~MemoryPreallocated() +{ + while (!_regions.empty()) + { + Region *region = _regions.front(); + + _regions.pop_front(); + _memory->release(region); + } +} + +/* Obtain an allocated region. */ + +Region *MemoryPreallocated::region() +{ + std::lock_guard guard(_lock); + + Region *region = _regions.front(); + + _regions.pop_front(); + return region; +} + +/* Release the allocated 'region'. */ + +void MemoryPreallocated::release(Region *region) +{ + std::lock_guard guard(_lock); + + _regions.push_back(region); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/lib/src/memory_utils.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/lib/src/memory_utils.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,132 @@ +/* + * Memory quantity calculation utilities. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include "memory_utils.h" + + + +/* Return page 'n' for the configured page size. */ + +offset_t page(unsigned int n) +{ + return PAGE_SIZE * n; +} + +/* Return the order of 'size', where 2 ** order yields the size. */ + +unsigned int page_order(offset_t size) +{ + /* Count zeros from the left, stopping at the first set bit, using the width + of the size value (in bits, starting with the width in bytes) to + calculate the position of this bit and thus the order of the value. */ + + return sizeof(unsigned long) * 8 - 1 - __builtin_clzl(size); +} + +/* Return 'value' rounded up to the nearest 'increment'. */ + +offset_t round(offset_t value, offset_t increment) +{ + return trunc(value + increment - 1, increment); +} + +/* Return 'value' rounded up to the nearest multiple of 'increment'. */ + +offset_t round_multiple(offset_t value, offset_t increment) +{ + offset_t last = increment; + + while (1) + { + if (value < increment) + return round(value, last); + + last = increment; + increment *= 2; + } +} + +/* Return 'value' rounded down (or truncated) to the nearest 'increment'. */ + +offset_t trunc(offset_t value, offset_t increment) +{ + return (value / increment) * increment; +} + +/* Return 'value' rounded down (or truncated) to the nearest multiple of + 'increment'. */ + +offset_t trunc_multiple(offset_t value, offset_t increment) +{ + offset_t last = increment; + + while (1) + { + if (value < increment) + return trunc(value, last); + + last = increment; + increment *= 2; + } +} + +/* Find the maximum size aligned region within the region from 'start' to (but + not including) 'end', with the given initial 'increment'. */ + +offset_t max_multiple(offset_t start, offset_t end, offset_t increment) +{ + /* The largest possible aligned region is derived from the region size. */ + + offset_t size = trunc_multiple(end - start, increment); + + /* Apply the alignment to the start. */ + + offset_t aligned = round(start, size); + + /* If the region is aligned, return the size. */ + + if (aligned == start) + return size; + + /* If the region is not aligned to the current size, recalculate the aligned + size. */ + + offset_t aligned_size; + + do + { + aligned_size = trunc_multiple(end - aligned, increment); + size /= 2; + + /* Determine whether a smaller alignment could yield a larger aligned + size. */ + + if (aligned_size >= size) + return aligned_size; + + aligned = round(start, size); + } + while (aligned > start); + + return aligned_size; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c libmem/lib/src/region.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libmem/lib/src/region.cc Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,104 @@ +/* + * Memory region abstractions. + * + * Copyright (C) 2021 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "region.h" + + + +/* Initialise region state, indicating the size, file and position. */ + +RegionState::RegionState(unsigned long size, fileid_t fileid, offset_t filepos) +: size(size), fileid(fileid), filepos(filepos) +{ +} + +void RegionState::fill(fileid_t fileid, offset_t filepos) +{ + this->fileid = fileid; + this->filepos = filepos; +} + + + +/* Initialise a region having the given 'start' and 'end' addresses, with the + 'end' being one location beyond the last address in the region. */ + +Region::Region(offset_t start, offset_t end) +: start(start), end(end), state(end - start) +{ + /* Content state. */ + + memset((void *) start, 0, end - start); +} + +Region::~Region() +{ + free((void *) start); +} + +offset_t Region::size() +{ + return end - start; +} + +/* Debugging methods. */ + +int Region::compare(Region *other) +{ + if (start < other->start) + return -1; + else if (start > other->start) + return 1; + else + return 0; +} + +void Region::fill(fileid_t fileid, offset_t filepos) +{ + state.fill(fileid, filepos); +} + +void Region::flush() +{ +} + +/* Simulation methods. */ + +char *Region::read(offset_t offset) +{ + if (offset < size()) + return (char *) start + offset; + else + return NULL; +} + +void Region::write(const char *data, offset_t offset) +{ + size_t length = strlen(data); + + if (offset + length < size()) + memcpy((void *) (start + offset), data, length + 1); +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/access_map.cc --- a/mapping/access_map.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -/* - * An access map providing memory corresponding to file regions. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "access_map.h" - -/* Return the flexpage supporting 'position'. */ - -Flexpage *AccessMap::find(offset_t position) -{ - std::lock_guard guard(_lock); - - _AccessMap::iterator it = _flexpages.upper_bound(position); - - if ((_flexpages.size() > 0) && (it != _flexpages.begin())) - { - it--; - - if (it->second->supports_position(position)) - return it->second; - } - - return NULL; -} - -/* Insert a mapping for 'flexpage'. */ - -void AccessMap::insert(Flexpage *flexpage) -{ - std::lock_guard guard(_lock); - - _flexpages.insert(_AccessMapEntry(flexpage->base_offset, flexpage)); -} - -/* Remove the mapping supported by 'flexpage'. - - The flexpage may have obtained by another mapper before being purged from - this object's mapping and before being purged from the queue (and thus - disassociated from this mapper), leaving an opportunity for another mapper to - now be removing it here. In such a situation, flushing has already occurred - and will not be performed again. */ - -bool AccessMap::remove(PageOwner *owner, Flexpage *flexpage) -{ - std::lock_guard guard(_lock); - - _AccessMap::iterator it = _flexpages.find(flexpage->base_offset); - - if (it != _flexpages.end()) - { - owner->flush(flexpage, true); - _flexpages.erase(flexpage->base_offset); - return true; - } - - return false; -} - -/* Purge all flexpages, using the 'owner' to flush their contents and - 'pages' to make the flexpages available to other accessors. */ - -void AccessMap::purge(PageOwner *owner, Pages *pages) -{ - std::lock_guard guard(_lock); - - _AccessMap::iterator it = _flexpages.begin(), entry; - - while (it != _flexpages.end()) - { - entry = it; - it++; - - Flexpage *flexpage = entry->second; - - /* Some flexpages may be unavailable in the queue. Only those - that can be reserved should be flushed and made available - again. */ - - if (pages->reserve(owner, flexpage)) - { - owner->flush(flexpage, true); - pages->release(flexpage); - _flexpages.erase(entry); - } - } -} - -/* Flush flexpages in the given range from 'start' with 'size', using 'owner' - and 'pages'. */ - -void AccessMap::flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages) -{ - offset_t end = start + size; - - std::lock_guard guard(_lock); - - /* The start may be within an existing flexpage where the flexpage size is a - page multiple. */ - - _AccessMap::iterator it = _flexpages.upper_bound(start), entry; - - if ((_flexpages.size() > 0) && (it != _flexpages.begin())) - it--; - - /* Inspect flexpages at or after start until end. */ - - while (it != _flexpages.end()) - { - entry = it; - it++; - - Flexpage *flexpage = entry->second; - - if (flexpage->base_offset >= end) - break; - - /* Attempt to flush each flexpage, releasing ones that are no longer - needed. */ - - if (pages->reserve(owner, flexpage)) - { - owner->flush(flexpage, false); - - /* Where no users of the flexpage persist, release the flexpage for - reuse and remove this entry. */ - - if (!flexpage->valid()) - { - pages->release(flexpage); - _flexpages.erase(entry); - } - else - pages->queue(owner, flexpage); - } - } -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/access_map.h --- a/mapping/access_map.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * An access map providing memory corresponding to file regions. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "flexpage.h" -#include "page_owner.h" -#include "pages.h" - -#include -#include - - - -/* Collection types. */ - -typedef std::map _AccessMap; -typedef std::pair _AccessMapEntry; - - - -/* A mapping from file positions to flexpages. */ - -class AccessMap -{ -protected: - _AccessMap _flexpages; - std::mutex _lock; - -public: - Flexpage *find(offset_t position); - - void insert(Flexpage *flexpage); - - bool remove(PageOwner *owner, Flexpage *flexpage); - - void purge(PageOwner *owner, Pages *pages); - - void flush_all(offset_t start, offset_t size, PageOwner *owner, Pages *pages); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/flexpage.cc --- a/mapping/flexpage.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -/* - * A flexpage abstraction. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include - -#include "flexpage.h" - - - -/* Reset the flexpage using 'offset', being the file offset. */ - -void Flexpage::reset(offset_t offset) -{ - _counter = 0; - - /* By definition (see "Flexible-Sized Page Objects - Object-Orientation - in Operation Systems"), flexpages are aligned to multiples of their - size. - - The size of the flexpage depends on the amount of space around the - accessed page. It cannot exceed the size of the memory region. */ - - size = max_multiple(region->start, region->end, PAGE_SIZE); - - /* The base address of the flexpage is computed from the region start - and flexpage size. It will be no lower than the region start. - - Sent flexpages may use higher bases due to receive window constraints, - these being communicated by the "hot spot". */ - - base_addr = round(region->start, size); - - /* Get the file offset for the base of the flexpage. This will be a - multiple of the flexpage size for alignment purposes. */ - - base_offset = trunc(offset, size); - - /* The page being accessed is relative to the base. - (This is transient information recording the initialising access - details.) */ - - page_offset = trunc(offset - base_offset, PAGE_SIZE); - page_addr = base_addr + page_offset; -} - -bool Flexpage::decrement() -{ - if (_counter) - { - _counter--; - return _counter == 0; - } - else - return 0; -} - -void Flexpage::increment() -{ - _counter++; -} - -void Flexpage::invalidate() -{ - _counter = 0; -} - -bool Flexpage::valid() -{ - return _counter != 0; -} - -/* Return whether the flexpage supports the given file 'position'. */ - -bool Flexpage::supports_position(offset_t position) -{ - return (base_offset <= position) && (position < (base_offset + size)); -} - -/* Upgrade the flags involved with this flexpage. This is used to track the - maximal flags employed by the different pagers, with the result being used in - unmap operations. */ - -void Flexpage::upgrade(flags_t flags) -{ - if (flags && (flags != _flags)) - _flags |= flags; -} - -/* Return a "send" flexpage for an access to 'offset' by positioning it relative - to 'hot_spot' for the receive flexpage window. */ - -SendFlexpage Flexpage::to_send(offset_t offset, offset_t hot_spot, - flags_t flags, offset_t max_offset) -{ - /* The dataspace offset of the flexpage base is a multiple of the flexpage - size. */ - - offset_t receive_base_offset = trunc(offset, size); - - /* The offset of the accessed page within the flexpage is constrained by the - current flexpage size. */ - - offset_t page_offset = trunc(offset - receive_base_offset, PAGE_SIZE); - - /* The receive flexpage offset (hot spot) must be constrained to the - flexpage, both the size and the start. */ - - offset_t receive_size; - - if (max_offset) - { - receive_size = trunc_multiple(max_offset - receive_base_offset, PAGE_SIZE); - receive_size = std::min(size, receive_size); - } - else - receive_size = size; - - if (!receive_size) - return SendFlexpage(base_addr, page_order(0), flags); - - offset_t receive_page_offset = hot_spot % receive_size; - - while ((receive_size > PAGE_SIZE) && (receive_page_offset != page_offset)) - { - receive_size /= 2; - receive_page_offset = hot_spot % receive_size; - } - - /* The flexpage base address is adjusted using the difference in page - offsets. Where the receive flexpage offset is constained further, the - base address will be raised to become closer to the accessed page. */ - - offset_t adjustment = page_offset - receive_page_offset; - - return SendFlexpage(base_addr + adjustment, page_order(receive_size), flags); -} - -/* Return a representation of the flexpage for unmapping. */ - -SendFlexpage Flexpage::to_unmap() -{ - return SendFlexpage(base_addr, page_order(size), _flags); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/flexpage.h --- a/mapping/flexpage.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * A flexpage abstraction. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "memory_utils.h" -#include "region.h" -#include "send_flexpage.h" - - - -/* A flexpage abstraction. */ - -class Flexpage -{ -protected: - unsigned int _counter; - flags_t _flags; - -public: - Region *region; - - /* General flexpage characteristics. */ - - offset_t base_addr, size; - offset_t base_offset; - - /* Transient debugging information. */ - - offset_t page_addr, page_offset; - - /* Associate a flexpage with a memory 'region'. */ - - explicit Flexpage(Region *region) : region(region) - { - } - - void reset(offset_t offset); - - bool decrement(); - - void increment(); - - void invalidate(); - - bool valid(); - - bool supports_position(offset_t position); - - void upgrade(flags_t flags); - - SendFlexpage to_send(offset_t offset, offset_t hot_spot, flags_t flags, - offset_t max_offset=0); - - SendFlexpage to_unmap(); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/ipc.cc --- a/mapping/ipc.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -/* - * Interprocess communication utilities. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include -#include -#include - -#include "ipc.h" -#include "send_flexpage.h" - - - -/* Make an L4 representation of the given flexpage. */ - -static l4_fpage_t ipc_get_fpage(SendFlexpage *send_flexpage) -{ - return l4_fpage(send_flexpage->base_addr, send_flexpage->order, - (send_flexpage->flags & L4RE_DS_MAP_FLAG_RW) ? L4_FPAGE_RW : L4_FPAGE_RO); -} - -/* Make a representation of a flexpage for the IPC system. */ - -long ipc_prepare_flexpage(Flexpage *flexpage, offset_t offset, - offset_t max_offset, address_t hot_spot, - flags_t flags, l4_snd_fpage_t *region) -{ - SendFlexpage send_flexpage = flexpage->to_send(offset, hot_spot, flags, - max_offset); - - /* NOTE: Consider l4_fpage_invalid() as the fpage here. */ - - if (!send_flexpage.order) - return -L4_ERANGE; - - region->fpage = ipc_get_fpage(&send_flexpage); - region->snd_base = hot_spot; - - return L4_EOK; -} - -/* Unmap the given flexpage. */ - -void ipc_unmap_flexpage(Flexpage *flexpage) -{ - SendFlexpage send_flexpage = flexpage->to_unmap(); - - l4_task_unmap(L4RE_THIS_TASK_CAP, ipc_get_fpage(&send_flexpage), L4_FP_OTHER_SPACES); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/ipc.h --- a/mapping/ipc.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Interprocess communication utilities. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#include "flexpage.h" - - - -long ipc_prepare_flexpage(Flexpage *flexpage, offset_t offset, - offset_t max_offset, address_t hot_spot, - flags_t flags, l4_snd_fpage_t *region); - -void ipc_unmap_flexpage(Flexpage *flexpage); - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/page_mapper.cc --- a/mapping/page_mapper.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,196 +0,0 @@ -/* - * A page mapper providing memory pages to satisfy file accesses. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "ipc.h" -#include "page_mapper.h" - - - -PageMapper::PageMapper(Accessor *accessor, Pages *pages) -: _accessor(accessor), _pages(pages), _attached(0) -{ -} - -/* Accounting methods. */ - -/* Attach a pager, opening the accessor if required. */ - -void PageMapper::attach() -{ - std::lock_guard guard(_lock); - - if (!_attached) - _accessor->open(); - - _attached += 1; -} - -/* Detach a pager, purging active pages and closing the accessor if no more - pagers are attached. Return whether any pagers are still attached. */ - -unsigned int PageMapper::detach() -{ - std::lock_guard guard(_lock); - - if (_attached) - { - _attached -= 1; - - if (!_attached) - { - _map.purge(this, _pages); - _accessor->close(); - } - } - - return _attached; -} - -/* Interface for the pager. */ - -/* Return a flexpage providing access to the indicated file 'offset'. - - The returned flexpage will either be an existing, compatible flexpage or a - completely new flexpage. - - This method locks the mapper to prevent concurrent queries with the same - details, with the lock held until the queue operation releases the lock. */ - -Flexpage *PageMapper::get(offset_t offset, flags_t flags) -{ - _lock.lock(); - - Flexpage *f = find(offset); - - if (f == NULL) - f = flexpage(offset); - - /* Record a new user of the flexpage and upgrade the access flags. */ - - f->increment(); - f->upgrade(flags); - return f; -} - -/* Queue the given 'flexpage' in the page collection, making it available for - eventual reuse. - - This method unlocks the mapper. */ - -void PageMapper::queue(Flexpage *flexpage) -{ - _pages->queue(this, flexpage); - - _lock.unlock(); -} - -/* Flush pages in the given range from 'start' with 'size'. */ - -void PageMapper::flush_all(offset_t start, offset_t size) -{ - std::lock_guard guard(_lock); - - _map.flush_all(start, size, this, _pages); -} - -/* Return the maximum extent of the mapped resource. */ - -offset_t PageMapper::get_data_size() -{ - return _accessor->get_size(); -} - -/* Set the maximum extent of the mapped resource. */ - -void PageMapper::set_data_size(offset_t size) -{ - _accessor->set_size(size); -} - -/* Internal flexpage retrieval methods. */ - -/* Find an existing flexpage for 'offset'. Where the accessor has registered a - compatible flexpage, an attempt is made to reserve it in the page collection; - if this succeeds, the flexpage is returned. Otherwise, NULL is returned. */ - -Flexpage *PageMapper::find(offset_t offset) -{ - Flexpage *flexpage = _map.find(offset); - - /* Between finding and reserving a flexpage, there is a possibility that - another accessor might acquire the flexpage, issue it, and even purge - it. */ - - if ((flexpage != NULL) && _pages->reserve(this, flexpage)) - return flexpage; - else - return NULL; -} - -/* Obtain a new flexpage for the file 'offset'. If the page collection is unable - to obtain a completely new flexpage, an existing flexpage is requested from - the page collection and recycled. - - The obtained flexpage is filled with content. */ - -Flexpage *PageMapper::flexpage(offset_t offset) -{ - Flexpage *flexpage = _pages->flexpage(); - - /* Obtain an existing flexpage and reuse it. */ - - if (flexpage == NULL) - flexpage = _pages->remove(); - - flexpage->reset(offset); - - fill(flexpage); - _map.insert(flexpage); - return flexpage; -} - -/* Interface for the page collection. */ - -/* Remove the record of 'flexpage' in this accessor, flushing its content. */ - -void PageMapper::remove(Flexpage *flexpage) -{ - _map.remove(this, flexpage); -} - -/* Data transfer methods. */ - -void PageMapper::fill(Flexpage *flexpage) -{ - _accessor->fill(flexpage); -} - -void PageMapper::flush(Flexpage *flexpage, bool purge) -{ - if (flexpage->decrement() || purge) - { - _accessor->flush(flexpage); - ipc_unmap_flexpage(flexpage); - flexpage->invalidate(); - } -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/page_mapper.h --- a/mapping/page_mapper.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/* - * A page mapper providing memory pages to satisfy file accesses. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "access_map.h" -#include "accessor.h" -#include "page_owner.h" - -#include - - - -/* A file mapper, associating flexpages with file regions. */ - -class PageMapper : public PageOwner -{ -protected: - AccessMap _map; - Accessor *_accessor; - Pages *_pages; - unsigned int _attached; - - /* Serialisation of accesses. */ - - std::mutex _lock; - - /* Internal flexpage retrieval methods. */ - - Flexpage *find(offset_t offset); - - Flexpage *flexpage(offset_t offset); - -public: - explicit PageMapper(Accessor *accessor, Pages *pages); - - /* Accounting methods. */ - - void attach(); - - unsigned int detach(); - - Accessor *accessor() - { return _accessor; } - - /* Interface for the pager. */ - - Flexpage *get(offset_t offset, flags_t flags); - - void queue(Flexpage *flexpage); - - void flush_all(offset_t start, offset_t size); - - offset_t get_data_size(); - - void set_data_size(offset_t size); - - /* Data transfer methods, implementing PageOwner. */ - - void fill(Flexpage *flexpage); - - void flush(Flexpage *flexpage, bool purge); - - /* Interface for the page collection, implementing PageOwner. */ - - void remove(Flexpage *flexpage); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/page_owner.h --- a/mapping/page_owner.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * A page owner abstraction, indicating the current user of a memory region. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "flexpage.h" - - - -/* The owner of a flexpage. */ - -class PageOwner -{ -public: - virtual ~PageOwner() - { - } - - virtual void fill(Flexpage *flexpage) - { - (void) flexpage; - } - - virtual void flush(Flexpage *flexpage, bool purge) - { - (void) flexpage; (void) purge; - } - - virtual void remove(Flexpage *flexpage) - { - (void) flexpage; - } -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c mapping/send_flexpage.h --- a/mapping/send_flexpage.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * A "send" flexpage abstraction for communicating memory mappings. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "types.h" - - - -/* A "send" flexpage abstraction. */ - -class SendFlexpage -{ -public: - offset_t base_addr; - unsigned int order; - flags_t flags; - - explicit SendFlexpage(offset_t base_addr, unsigned int order, - flags_t flags) - : base_addr(base_addr), order(order), flags(flags) - { - } -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/memory.h --- a/memory/memory.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * A generic memory pool abstraction. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "region.h" - - - -/* A memory pool interface. */ - -class Memory -{ -public: - virtual ~Memory() - { - } - - virtual Region *region() = 0; - - virtual offset_t region_size() = 0; - - virtual void release(Region *region) = 0; -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/memory_incremental.cc --- a/memory/memory_incremental.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * A memory pool allocating a region at a time from the system. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "memory_incremental.h" - -#include - -/* Initialise the memory pool with an optional 'limit' in pages. */ - -MemoryIncremental::MemoryIncremental(unsigned int limit, offset_t region_size) -: _limit(limit), _region_size(region_size) -{ - _limited = true; -} - -MemoryIncremental::MemoryIncremental() -: _region_size(PAGE_SIZE) -{ - _limited = false; -} - -/* Allocate a block of the given 'size'. */ - -Region *MemoryIncremental::allocate(offset_t size) -{ - /* Attempt to allocate aligned memory. */ - - void *current; - - /* Make the size appropriate for the invocation. */ - - size = round_multiple(size, PAGE_SIZE); - - if (posix_memalign(¤t, size, size)) - return NULL; - - return new Region((offset_t) current, (offset_t) current + size); -} - -/* Allocate a new region of the given 'size' rounded to the nearest page. */ - -Region *MemoryIncremental::region(offset_t size) -{ - std::lock_guard guard(_lock); - - offset_t rounded = round(size, PAGE_SIZE); - offset_t pages = rounded / PAGE_SIZE; - - /* Check for sufficient pages. */ - - if (!_limited || (_limit >= pages)) - { - /* Attempt to allocate aligned memory. */ - - Region *region = allocate(rounded); - - if (region == NULL) - return NULL; - - if (_limited) - _limit -= pages; - - return region; - } - - /* Return no region without sufficient pages. */ - - else - return NULL; -} - -Region *MemoryIncremental::region() -{ - return region(_region_size); -} - -/* Release the allocated 'region'. */ - -void MemoryIncremental::release(Region *region) -{ - std::lock_guard guard(_lock); - - offset_t rounded = round(region->size(), PAGE_SIZE); - offset_t pages = rounded / PAGE_SIZE; - - if (_limited) - _limit += pages; - - delete region; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/memory_incremental.h --- a/memory/memory_incremental.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * A memory pool allocating a region at a time from the system. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#include - -#include "memory.h" -#include "memory_utils.h" - - - -/* A memory pool abstraction. */ - -class MemoryIncremental : public Memory -{ -protected: - std::mutex _lock; - - unsigned int _limit; - offset_t _region_size; - bool _limited; - - Region *allocate(offset_t size); - -public: - explicit MemoryIncremental(unsigned int limit, offset_t region_size=PAGE_SIZE); - - explicit MemoryIncremental(); - - virtual Region *region(offset_t size); - - virtual Region *region(); - - virtual offset_t region_size() - { return _region_size; } - - virtual void release(Region *region); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/memory_preallocated.cc --- a/memory/memory_preallocated.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * A memory pool providing regions from a preallocated amount of memory. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "memory_preallocated.h" - - - -/* Initialise the memory pool with the given amount in bytes. */ - -MemoryPreallocated::MemoryPreallocated(Memory *memory, offset_t amount) -: _memory(memory), _amount(amount) -{ - // NOTE: Handle allocation failure. - - offset_t remaining = amount; - - while (remaining) - { - _regions.push_back(memory->region()); - - if (memory->region_size() >= remaining) - break; - - remaining -= memory->region_size(); - } -} - -/* Discard all unused regions. */ - -MemoryPreallocated::~MemoryPreallocated() -{ - while (!_regions.empty()) - { - Region *region = _regions.front(); - - _regions.pop_front(); - _memory->release(region); - } -} - -/* Obtain an allocated region. */ - -Region *MemoryPreallocated::region() -{ - std::lock_guard guard(_lock); - - Region *region = _regions.front(); - - _regions.pop_front(); - return region; -} - -/* Release the allocated 'region'. */ - -void MemoryPreallocated::release(Region *region) -{ - std::lock_guard guard(_lock); - - _regions.push_back(region); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/memory_preallocated.h --- a/memory/memory_preallocated.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * A memory pool providing regions from a preallocated amount of memory. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#include -#include - -#include "memory.h" - - - -/* A memory pool abstraction. */ - -class MemoryPreallocated : public Memory -{ -protected: - std::mutex _lock; - std::list _regions; - - Memory *_memory; - offset_t _amount; - -public: - explicit MemoryPreallocated(Memory *memory, offset_t amount); - - explicit MemoryPreallocated(); - - virtual ~MemoryPreallocated(); - - virtual Region *region(); - - virtual offset_t region_size() - { return _memory->region_size(); } - - virtual void release(Region *region); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/memory_utils.cc --- a/memory/memory_utils.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,132 +0,0 @@ -/* - * Memory quantity calculation utilities. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "memory_utils.h" - - - -/* Return page 'n' for the configured page size. */ - -offset_t page(unsigned int n) -{ - return PAGE_SIZE * n; -} - -/* Return the order of 'size', where 2 ** order yields the size. */ - -unsigned int page_order(offset_t size) -{ - /* Count zeros from the left, stopping at the first set bit, using the width - of the size value (in bits, starting with the width in bytes) to - calculate the position of this bit and thus the order of the value. */ - - return sizeof(unsigned long) * 8 - 1 - __builtin_clzl(size); -} - -/* Return 'value' rounded up to the nearest 'increment'. */ - -offset_t round(offset_t value, offset_t increment) -{ - return trunc(value + increment - 1, increment); -} - -/* Return 'value' rounded up to the nearest multiple of 'increment'. */ - -offset_t round_multiple(offset_t value, offset_t increment) -{ - offset_t last = increment; - - while (1) - { - if (value < increment) - return round(value, last); - - last = increment; - increment *= 2; - } -} - -/* Return 'value' rounded down (or truncated) to the nearest 'increment'. */ - -offset_t trunc(offset_t value, offset_t increment) -{ - return (value / increment) * increment; -} - -/* Return 'value' rounded down (or truncated) to the nearest multiple of - 'increment'. */ - -offset_t trunc_multiple(offset_t value, offset_t increment) -{ - offset_t last = increment; - - while (1) - { - if (value < increment) - return trunc(value, last); - - last = increment; - increment *= 2; - } -} - -/* Find the maximum size aligned region within the region from 'start' to (but - not including) 'end', with the given initial 'increment'. */ - -offset_t max_multiple(offset_t start, offset_t end, offset_t increment) -{ - /* The largest possible aligned region is derived from the region size. */ - - offset_t size = trunc_multiple(end - start, increment); - - /* Apply the alignment to the start. */ - - offset_t aligned = round(start, size); - - /* If the region is aligned, return the size. */ - - if (aligned == start) - return size; - - /* If the region is not aligned to the current size, recalculate the aligned - size. */ - - offset_t aligned_size; - - do - { - aligned_size = trunc_multiple(end - aligned, increment); - size /= 2; - - /* Determine whether a smaller alignment could yield a larger aligned - size. */ - - if (aligned_size >= size) - return aligned_size; - - aligned = round(start, size); - } - while (aligned > start); - - return aligned_size; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/memory_utils.h --- a/memory/memory_utils.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,46 +0,0 @@ -/* - * Memory quantity calculation utilities. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#define PAGE_SIZE 4096 - - - -/* Address arithmetic. */ - -offset_t page(unsigned int n); - -unsigned int page_order(offset_t size); - -offset_t round(offset_t value, offset_t increment); - -offset_t round_multiple(offset_t value, offset_t increment); - -offset_t trunc(offset_t value, offset_t increment); - -offset_t trunc_multiple(offset_t value, offset_t increment); - -offset_t max_multiple(offset_t start, offset_t end, offset_t increment); - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/region.cc --- a/memory/region.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -/* - * Memory region abstractions. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include -#include - -#include "region.h" - - - -/* Initialise region state, indicating the size, file and position. */ - -RegionState::RegionState(unsigned long size, fileid_t fileid, offset_t filepos) -: size(size), fileid(fileid), filepos(filepos) -{ -} - -void RegionState::fill(fileid_t fileid, offset_t filepos) -{ - this->fileid = fileid; - this->filepos = filepos; -} - - - -/* Initialise a region having the given 'start' and 'end' addresses, with the - 'end' being one location beyond the last address in the region. */ - -Region::Region(offset_t start, offset_t end) -: start(start), end(end), state(end - start) -{ - /* Content state. */ - - memset((void *) start, 0, end - start); -} - -Region::~Region() -{ - free((void *) start); -} - -offset_t Region::size() -{ - return end - start; -} - -/* Debugging methods. */ - -int Region::compare(Region *other) -{ - if (start < other->start) - return -1; - else if (start > other->start) - return 1; - else - return 0; -} - -void Region::fill(fileid_t fileid, offset_t filepos) -{ - state.fill(fileid, filepos); -} - -void Region::flush() -{ -} - -/* Simulation methods. */ - -char *Region::read(offset_t offset) -{ - if (offset < size()) - return (char *) start + offset; - else - return NULL; -} - -void Region::write(const char *data, offset_t offset) -{ - size_t length = strlen(data); - - if (offset + length < size()) - memcpy((void *) (start + offset), data, length + 1); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c memory/region.h --- a/memory/region.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/* - * Memory region abstractions. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include - -#include "types.h" - - - -/* Region-related state information. */ - -class RegionState -{ -public: - unsigned long size; - fileid_t fileid; - offset_t filepos; - - explicit RegionState(unsigned long size=0, fileid_t fileid=0, offset_t filepos=0); - - void fill(fileid_t fileid, offset_t filepos); - - bool valid() { return size != 0; } -}; - - - -/* A memory region abstraction. */ - -class Region -{ -public: - offset_t start, end; - - /* Debugging information. */ - - RegionState state; - - /* Methods. */ - - explicit Region(offset_t start, offset_t end); - - virtual ~Region(); - - offset_t size(); - - int compare(Region *other); - - void fill(fileid_t fileid, offset_t filepos); - - void flush(); - - /* Simulation methods. */ - - char *read(offset_t offset=0); - - void write(const char *data, offset_t offset=0); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pages/page_queue.cc --- a/pages/page_queue.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * A page queue abstraction. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "page_queue.h" - - - -void PageQueue::discard(Queue &queue, Memory *memory) -{ - while (!queue.empty()) - { - Flexpage *flexpage = queue.front().flexpage; - - queue.pop_front(); - memory->release(flexpage->region); - delete flexpage; - } -} - -bool PageQueue::remove(Queue &queue, Positions &positions, PageOwner *owner, Flexpage *flexpage) -{ - Positions::iterator position = positions.find(flexpage); - - if (position == positions.end()) - return false; - - /* The found owner may be different from the requesting owner or even NULL - if another owner has acquired and then purged its pages. Such a purged - flexpage is not immediately usable, however. */ - - Queue::iterator entry = position->second; - - if ((entry->owner == NULL) || (entry->owner != owner)) - return false; - - queue.erase(entry); - positions.erase(position); - - return true; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pages/page_queue.h --- a/pages/page_queue.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * A page queue abstraction. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include -#include - -#include "flexpage.h" -#include "memory.h" -#include "page_owner.h" - - - -/* Collection types. */ - -typedef struct { Flexpage *flexpage; PageOwner *owner; } QueueEntry; -typedef std::list Queue; - -typedef std::pair Position; -typedef std::map Positions; - - - -/* A queue of managed pages. */ - -class PageQueue -{ -protected: - - /* Helper methods. */ - - virtual void discard(Queue &queue, Memory *memory); - - virtual bool remove(Queue &queue, Positions &positions, PageOwner *owner, Flexpage *flexpage); - -public: - virtual ~PageQueue() - { - } - - virtual void close(Memory *memory) = 0; - - virtual void pop(PageOwner **owner, Flexpage **flexpage) = 0; - - virtual void push(PageOwner *owner, Flexpage *flexpage) = 0; - - virtual void push_front(PageOwner *owner, Flexpage *flexpage) = 0; - - virtual bool remove(PageOwner *owner, Flexpage *flexpage) = 0; -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pages/page_queue_partitioned.cc --- a/pages/page_queue_partitioned.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * A page queue retaining two internal collections of memory pages. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "page_queue_partitioned.h" - - - -/* Discard all queued flexpages. */ - -void PageQueuePartitioned::close(Memory *memory) -{ - discard(_available, memory); - discard(_issued, memory); -} - -/* Keep waiting for a potential queue non-empty condition. - Then, attempt to pop an entry from the queue. */ - -void PageQueuePartitioned::pop(PageOwner **owner, Flexpage **flexpage) -{ - std::unique_lock guard(_lock); - QueueEntry entry; - - while (1) - { - if (_pop(&entry)) - { - *owner = entry.owner; - *flexpage = entry.flexpage; - return; - } - else - _counter.wait(guard); - } -} - -/* Check the available pages queue for entries, returning false if no entries - are available, returning true and providing the details if an entry can be - removed from the front of the queue. */ - -bool PageQueuePartitioned::_pop(QueueEntry *entry) -{ - if (_available.empty()) - return false; - - *entry = _available.front(); - _available.pop_front(); - - return true; -} - -/* Push an entry for the given owner and flexpage to the appropriate queue. */ - -void PageQueuePartitioned::push(PageOwner *owner, Flexpage *flexpage) -{ - std::lock_guard guard(_lock); - - /* Record the entry and a position reference for the flexpage. */ - - Queue *queue; - Positions *positions = NULL; - - if (owner == NULL) - queue = &_available; - else - { - queue = &_issued; - positions = &_positions; - } - - queue->push_back((QueueEntry) {flexpage, owner}); - - if (positions != NULL) - { - Queue::iterator last = queue->end(); - last--; - positions->insert(Position(flexpage, last)); - } - - _counter.notify_one(); -} - -/* Push an entry to the front of the appropriate queue. */ - -void PageQueuePartitioned::push_front(PageOwner *owner, Flexpage *flexpage) -{ - std::lock_guard guard(_lock); - - Queue *queue; - Positions *positions = NULL; - - if (owner == NULL) - queue = &_available; - else - { - queue = &_issued; - positions = &_positions; - } - - queue->push_back((QueueEntry) {flexpage, owner}); - - if (positions != NULL) - positions->insert(Position(flexpage, queue->begin())); - - _counter.notify_one(); -} - -/* Remove an entry for the given owner and flexpage from the queue. */ - -bool PageQueuePartitioned::remove(PageOwner *owner, Flexpage *flexpage) -{ - return PageQueue::remove(_issued, _positions, owner, flexpage); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pages/page_queue_partitioned.h --- a/pages/page_queue_partitioned.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * A page queue retaining two internal collections of memory pages. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include -#include - -#include "page_queue.h" - - - -/* Queues of issued and available pages. */ - -class PageQueuePartitioned : public PageQueue -{ -protected: - Queue _issued, _available; - Positions _positions; - - std::mutex _lock; - std::condition_variable _counter; - - virtual bool _pop(QueueEntry *entry); - -public: - virtual void close(Memory *memory); - - virtual void pop(PageOwner **owner, Flexpage **flexpage); - - virtual void push(PageOwner *owner, Flexpage *flexpage); - - virtual void push_front(PageOwner *owner, Flexpage *flexpage); - - virtual bool remove(PageOwner *owner, Flexpage *flexpage); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pages/page_queue_shared.cc --- a/pages/page_queue_shared.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -/* - * A page queue whose users take turns to access pages. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "page_queue_shared.h" - - - -/* Discard all queued flexpages. */ - -void PageQueueShared::close(Memory *memory) -{ - discard(_queue, memory); -} - -/* Keep waiting for a potential queue non-empty condition. - Then, attempt to pop an entry from the queue. */ - -void PageQueueShared::pop(PageOwner **owner, Flexpage **flexpage) -{ - std::unique_lock guard(_lock); - QueueEntry entry; - - while (1) - { - if (_pop(&entry)) - { - *owner = entry.owner; - *flexpage = entry.flexpage; - return; - } - else - _counter.wait(guard); - } -} - -/* Check the queue for entries, returning false if no entries are available, - returning true and providing the details if an entry can be removed from the - front of the queue. */ - -bool PageQueueShared::_pop(QueueEntry *entry) -{ - if (_queue.empty()) - return false; - - *entry = _queue.front(); - _queue.pop_front(); - - /* Remove any position reference for the flexpage. */ - - Positions::iterator position = _positions.find(entry->flexpage); - - if (position != _positions.end()) - _positions.erase(position); - - return true; -} - -/* Push an entry for the given owner and flexpage to the queue. */ - -void PageQueueShared::push(PageOwner *owner, Flexpage *flexpage) -{ - std::lock_guard guard(_lock); - - /* Record the entry and a position reference for the flexpage. */ - - _queue.push_back((QueueEntry) {flexpage, owner}); - - Queue::iterator last = _queue.end(); - last--; - _positions.insert(Position(flexpage, last)); - - _counter.notify_one(); -} - -/* Push an entry to the front of the queue. */ - -void PageQueueShared::push_front(PageOwner *owner, Flexpage *flexpage) -{ - std::lock_guard guard(_lock); - - _queue.push_back((QueueEntry) {flexpage, owner}); - _positions.insert(Position(flexpage, _queue.begin())); - - _counter.notify_one(); -} - -/* Remove an entry for the given owner and flexpage from the queue. */ - -bool PageQueueShared::remove(PageOwner *owner, Flexpage *flexpage) -{ - return PageQueue::remove(_queue, _positions, owner, flexpage); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pages/page_queue_shared.h --- a/pages/page_queue_shared.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * A page queue whose users take turns to access pages. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include -#include - -#include "page_queue.h" - - - -/* A queue of issued pages. */ - -class PageQueueShared : public PageQueue -{ -protected: - Queue _queue; - Positions _positions; - - std::mutex _lock; - std::condition_variable _counter; - - virtual bool _pop(QueueEntry *entry); - -public: - virtual void close(Memory *memory); - - virtual void pop(PageOwner **owner, Flexpage **flexpage); - - virtual void push(PageOwner *owner, Flexpage *flexpage); - - virtual void push_front(PageOwner *owner, Flexpage *flexpage); - - virtual bool remove(PageOwner *owner, Flexpage *flexpage); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pages/pages.cc --- a/pages/pages.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -/* - * A page collection abstraction providing pages from a queue to users. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "memory_incremental.h" -#include "pages.h" - - - -Pages::Pages(Memory *memory, PageQueue *queue) -: _memory(memory), _queue(queue) -{ -} - -Pages::~Pages() -{ - _queue->close(_memory); -} - -/* Remove the first flexpage in the queue. If its owner exists, remove it from - the owner (retiring the content). Return the flexpage for reuse. */ - -Flexpage *Pages::remove() -{ - PageOwner *owner; - Flexpage *flexpage; - - _queue->pop(&owner, &flexpage); - - if (owner != NULL) - owner->remove(flexpage); - - return flexpage; -} - -/* Reserve 'flexpage' by removing it from this collection. */ - -bool Pages::reserve(PageOwner *owner, Flexpage *flexpage) -{ - return _queue->remove(owner, flexpage); -} - -/* Obtain a new flexpage. Return the flexpage or None if no new flexpage could - be created. */ - -Flexpage *Pages::flexpage() -{ - Region *region = _memory->region(); - - if (region != NULL) - return new Flexpage(region); - else - return NULL; -} - -/* Queue an entry associating the given 'owner' and 'flexpage'. */ - -void Pages::queue(PageOwner *owner, Flexpage *flexpage) -{ - _queue->push(owner, flexpage); -} - -/* Push an entry for 'flexpage' without owner association for immediate - reuse. */ - -void Pages::release(Flexpage *flexpage) -{ - _queue->push_front(NULL, flexpage); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pages/pages.h --- a/pages/pages.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * A page collection abstraction providing pages from a queue to users. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "flexpage.h" -#include "memory.h" -#include "page_owner.h" -#include "page_queue.h" - - - -/* A page collection. */ - -class Pages -{ -protected: - Memory *_memory; - PageQueue *_queue; - -public: - explicit Pages(Memory *memory, PageQueue *queue); - - virtual ~Pages(); - - virtual Flexpage *remove(); - - virtual bool reserve(PageOwner *owner, Flexpage *flexpage); - - virtual Flexpage *flexpage(); - - virtual void queue(PageOwner *owner, Flexpage *flexpage); - - virtual void release(Flexpage *flexpage); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pipes/pipe_accessor.cc --- a/pipes/pipe_accessor.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,64 +0,0 @@ -/* - * A pipe accessor merely resetting allocated memory for use. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "pipe_accessor.h" - -#include - -PipeAccessor::PipeAccessor() -: Accessor(0) -{ -} - -/* Perform any closing operation on the file. */ - -void PipeAccessor::close() -{ -} - -/* Perform any opening operation on the file. */ - -void PipeAccessor::open() -{ -} - -/* Data transfer helper methods. */ - -void PipeAccessor::fill_populated(Flexpage *flexpage) -{ - offset_t filepos = flexpage->base_offset; - offset_t addr = flexpage->base_addr; - - /* Tag the region with file state. */ - - flexpage->region->fill(fileid, filepos); - - /* File the flexpage with zero. */ - - memset((void *) addr, 0, flexpage->size); -} - -void PipeAccessor::flush_populated(Flexpage *flexpage) -{ - flexpage->region->flush(); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pipes/pipe_accessor.h --- a/pipes/pipe_accessor.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * A pipe accessor merely resetting allocated memory for use. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "accessor.h" - - - -/* A pipe accessor, providing flexpages for pipe sections. */ - -class PipeAccessor : public Accessor -{ -protected: - - /* Data transfer helper methods. */ - - virtual void fill_populated(Flexpage *flexpage); - - virtual void flush_populated(Flexpage *flexpage); - -public: - explicit PipeAccessor(); - - virtual void close(); - - virtual void open(); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pipes/pipe_opener_resource.cc --- a/pipes/pipe_opener_resource.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ -/* - * A pipe opener resource. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "memory_incremental.h" -#include "pipe_opener_resource.h" -#include "pipe_opener_server.h" -#include "pipe_pager.h" -#include "resource_server.h" - - - -/* Support for providing access to pipes. */ - -PipeOpenerResource::PipeOpenerResource(Memory *memory) -: _memory(memory) -{ -} - -int PipeOpenerResource::expected_items() -{ - return PipeOpener_expected_items; -} - -ipc_server_handler_type PipeOpenerResource::handler() -{ - return (ipc_server_handler_type) handle_PipeOpener; -} - - - -/* Pipe opener interface methods. */ - -long PipeOpenerResource::pipe(offset_t size, l4_cap_idx_t *reader, l4_cap_idx_t *writer) -{ - /* Both endpoints will employ a common paging coordinator. */ - - PipePaging *paging = new PipePaging(_memory, size); - - /* Each endpoint will have its own pager. */ - - /* NOTE: Failure to open an endpoint should invalidate both, plus the - paging object. Also, any active server thread would need to be - cancelled. */ - - return open_endpoint(paging, false, reader) || open_endpoint(paging, true, writer); -} - -long PipeOpenerResource::open_endpoint(PipePaging *paging, bool writing, l4_cap_idx_t *endpoint) -{ - PipePager *pager = new PipePager(paging, writing); - - /* Start the endpoint server in a new thread. - If the thread does not start, the resource should be finalised. */ - - ResourceServer server(pager); - long err = server.start_thread(); - - /* Return the server capability to the caller. */ - - if (!err) - *endpoint = server.config()->server; - - return err; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pipes/pipe_opener_resource.h --- a/pipes/pipe_opener_resource.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * A pipe opener resource. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "memory.h" -#include "pipe_opener_interface.h" -#include "pipe_paging.h" -#include "resource.h" - - - -/* Support for providing access to pipes. */ - -class PipeOpenerResource : public Resource, public PipeOpener -{ -protected: - Memory *_memory; - - long open_endpoint(PipePaging *paging, bool writing, l4_cap_idx_t *endpoint); - -public: - explicit PipeOpenerResource(Memory *memory); - - /* Server details. */ - - int expected_items(); - - ipc_server_handler_type handler(); - - void *interface() - { return static_cast(this); } - - /* PipeOpener interface methods. */ - - long pipe(offset_t size, l4_cap_idx_t *reader, l4_cap_idx_t *writer); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pipes/pipe_pager.cc --- a/pipes/pipe_pager.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * A pipe pager providing access to pipe content and navigation support. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "pipe_pager.h" -#include "pipe_object_server.h" - - - -/* Initialise a pager for a pipe with a shared page mapper for moderating - access to loaded pages. At first, no mapper will be configured: this must be - done by requesting a region. */ - -PipePager::PipePager(PipePaging *paging, bool writing) -: Pager(NULL, writing ? L4RE_DS_MAP_FLAG_RW : L4RE_DS_MAP_FLAG_RO), - _paging(paging), _writing(writing) -{ - /* Initialise the size of the paged region. */ - - _size = _paging->region_size(); -} - -int PipePager::expected_items() -{ - return PipeObject_expected_items; -} - -ipc_server_handler_type PipePager::handler() -{ - return (ipc_server_handler_type) handle_PipeObject; -} - - - -/* Close the pager, releasing the paging coordinator for the pipe. This will - release all active page mappers. */ - -void PipePager::close() -{ - _paging->detach(); -} - -/* Support paging. */ - -long PipePager::map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region) -{ - return Pager::map(offset, hot_spot, flags, region); -} - - - -/* Return details of the current region. */ - -long PipePager::current_region(offset_t *populated_size, offset_t *size) -{ - if (_mapper != NULL) - { - *populated_size = _mapper->get_data_size(); - *size = _size; - return L4_EOK; - } - else - return -L4_EIO; -} - -/* Obtain the next region and its details. */ - -long PipePager::next_region(offset_t *populated_size, offset_t *size) -{ - /* Obtain a new region if writing. */ - - if (_writing) - return next_region_for_writer(populated_size, size); - else - return next_region_for_reader(populated_size, size); -} - -long PipePager::next_region_for_reader(offset_t *populated_size, offset_t *size) -{ - PageMapper *mapper = _paging->next_region(); - - if (mapper == NULL) - return -L4_EIO; - - _mapper = mapper; - - return current_region(populated_size, size); -} - -long PipePager::next_region_for_writer(offset_t *populated_size, offset_t *size) -{ - /* Set the populated size before moving on. */ - - if (_mapper != NULL) - _mapper->set_data_size(*populated_size); - - /* Obtain the page mapper for the region. */ - - PageMapper *mapper = _paging->add_region(); - - if (mapper == NULL) - return -L4_EIO; - - _mapper = mapper; - - return current_region(populated_size, size); -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pipes/pipe_pager.h --- a/pipes/pipe_pager.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * A pipe pager providing access to pipe content and navigation support. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "pipe_accessor.h" -#include "pipe_object_interface.h" -#include "pipe_paging.h" -#include "pager.h" - - - -/* A pager abstraction for a pipe. */ - -class PipePager : public Pager, public PipeObject -{ -protected: - PipePaging *_paging; - bool _writing; - - /* Helper methods. */ - - virtual long next_region_for_reader(offset_t *populated_size, offset_t *size); - - virtual long next_region_for_writer(offset_t *populated_size, offset_t *size); - -public: - explicit PipePager(PipePaging *paging, bool writer); - - virtual void close(); - - /* Server details. */ - - int expected_items(); - - ipc_server_handler_type handler(); - - void *interface() - { return static_cast(this); } - - /* Pager methods. */ - - virtual long map(offset_t offset, address_t hot_spot, flags_t flags, l4_snd_fpage_t *region); - - /* Pipe methods. */ - - virtual long current_region(offset_t *populated_size, offset_t *size); - - virtual long next_region(offset_t *populated_size, offset_t *size); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pipes/pipe_paging.cc --- a/pipes/pipe_paging.cc Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -/* - * A pipe paging coordinator, permitting memory sharing pipe endpoints. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#include "memory_incremental.h" -#include "memory_preallocated.h" -#include "page_queue_partitioned.h" -#include "pipe_paging.h" - - - -PipePaging::PipePaging(Memory *memory, offset_t size) -: _memory(NULL), _size(size) -{ - /* Reserve space for two pipe regions. */ - - _memory = new MemoryPreallocated(memory, round(size, memory->region_size()) * 2); - _queue = new PageQueuePartitioned(); - _pages = new Pages(_memory, _queue); - - for (unsigned int i = 0; i < 2; i++) - _regions[i] = NULL; -} - -/* Detach one endpoint. */ - -void PipePaging::detach() -{ - if (!_endpoints) - return; - else - _endpoints--; - - /* Return if the other endpoint is attached. */ - - if (_endpoints) - return; - - /* Discard all regions from the pipe. */ - - for (unsigned int i = 0; i < 2; i++) - { - PageMapper *mapper = _regions[i]; - - if (mapper != NULL) - { - mapper->detach(); - _regions[i] = NULL; - delete mapper; - } - } - - /* Delete the page collection and related objects. */ - - delete _pages; - delete _queue; - delete _memory; -} - -/* Add a region to the sequence. */ - -PageMapper *PipePaging::add_region() -{ - /* If the writer already accesses a different region to the reader, no new - region is added. */ - - if (_writing != _reading) - return NULL; - - /* Select the other region of the pair being maintained. */ - - _writing = 1 - _writing; - - /* Make a new mapper for the region. */ - - PageMapper *mapper = new PageMapper(&_accessors[_writing], _pages); - - /* Initialise and record the mapper. */ - - mapper->attach(); - mapper->set_data_size(0); - - _regions[_writing] = mapper; - return mapper; -} - -/* Return the current region for reading. */ - -PageMapper *PipePaging::current_region() -{ - return _regions[_reading]; -} - -/* Return the next region for the reader if the writer is using a different one. - Otherwise, return NULL. */ - -PageMapper *PipePaging::next_region() -{ - /* If the reader already accesses the same region to the writer, no next - region can be obtained. */ - - if (_reading == _writing) - return NULL; - - /* Detach and discard the current page mapper. */ - - PageMapper *mapper = _regions[_reading]; - - if (mapper != NULL) - { - mapper->detach(); - _regions[_reading] = NULL; - delete mapper; - } - - /* Return the next region. */ - - _reading = 1 - _reading; - return _regions[_reading]; -} - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c pipes/pipe_paging.h --- a/pipes/pipe_paging.h Tue Apr 13 00:03:18 2021 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * A pipe paging coordinator, permitting memory sharing pipe endpoints. - * - * Copyright (C) 2021 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 - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA - */ - -#pragma once - -#include "page_mapper.h" -#include "pages.h" -#include "pipe_accessor.h" - - - -/* Pipe paging support, maintaining the sequence of active regions or sections - in a pipe. */ - -class PipePaging -{ -protected: - Memory *_memory; - Pages *_pages; - PageQueue *_queue; - - /* Regions acting as files with their own accessors. */ - - PageMapper *_regions[2]; - PipeAccessor _accessors[2]; - - /* The first region is initially exposed to both reader and writer. */ - - int _reading = 0, _writing = 0; - - /* Pipe section/region size. */ - - offset_t _size; - - /* Endpoint status. */ - - unsigned int _endpoints = 2; - -public: - explicit PipePaging(Memory *memory, offset_t size); - - virtual void detach(); - - virtual offset_t region_size() - { return _size; } - - /* Region management. */ - - virtual PageMapper *add_region(); - - virtual PageMapper *current_region(); - - virtual PageMapper *next_region(); -}; - -// vim: tabstop=4 expandtab shiftwidth=4 diff -r bf981cb9a709 -r b6dab1e89e3c servers/Control --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servers/Control Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,3 @@ +requires: libstdc++ libc libipc libfsserver libmem +provides: fsservers +maintainer: paul@boddie.org.uk diff -r bf981cb9a709 -r b6dab1e89e3c servers/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/servers/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,22 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../../.. + +TARGET = \ + dstest_block_server \ + dstest_host_server \ + dstest_pipe_server \ + dstest_test_server + +MODE = static + +SRC_CC_dstest_block_server = block_file_server.cc + +SRC_CC_dstest_host_server = host_file_server.cc + +SRC_CC_dstest_pipe_server = pipe_server.cc + +SRC_CC_dstest_test_server = test_file_server.cc + +REQUIRES_LIBS = l4re_c-util libmem libfsserver libipc libstdc++ libsystypes + +include $(L4DIR)/mk/prog.mk diff -r bf981cb9a709 -r b6dab1e89e3c servers/block_file_server.cc --- a/servers/block_file_server.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/servers/block_file_server.cc Thu Apr 15 23:15:17 2021 +0200 @@ -28,12 +28,12 @@ #include #include -#include "memory_incremental.h" -#include "memory_utils.h" -#include "page_queue_shared.h" -#include "pages.h" -#include "resource_server.h" -#include "block_file_opener.h" +#include +#include +#include +#include +#include +#include diff -r bf981cb9a709 -r b6dab1e89e3c servers/host_file_server.cc --- a/servers/host_file_server.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/servers/host_file_server.cc Thu Apr 15 23:15:17 2021 +0200 @@ -28,12 +28,12 @@ #include #include -#include "memory_incremental.h" -#include "memory_utils.h" -#include "page_queue_shared.h" -#include "pages.h" -#include "resource_server.h" -#include "host_file_opener.h" +#include +#include +#include +#include +#include +#include diff -r bf981cb9a709 -r b6dab1e89e3c servers/pipe_server.cc --- a/servers/pipe_server.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/servers/pipe_server.cc Thu Apr 15 23:15:17 2021 +0200 @@ -26,9 +26,9 @@ #include #include -#include "memory_incremental.h" -#include "pipe_opener_resource.h" -#include "resource_server.h" +#include +#include +#include diff -r bf981cb9a709 -r b6dab1e89e3c servers/test_file_server.cc --- a/servers/test_file_server.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/servers/test_file_server.cc Thu Apr 15 23:15:17 2021 +0200 @@ -28,12 +28,12 @@ #include #include -#include "memory_incremental.h" -#include "memory_utils.h" -#include "page_queue_shared.h" -#include "pages.h" -#include "resource_server.h" -#include "test_file_opener.h" +#include +#include +#include +#include +#include +#include diff -r bf981cb9a709 -r b6dab1e89e3c tests/Control --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/Control Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,3 @@ +requires: libstdc++ libc libipc libfsclient libmem +provides: fstests +maintainer: paul@boddie.org.uk diff -r bf981cb9a709 -r b6dab1e89e3c tests/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/Makefile Thu Apr 15 23:15:17 2021 +0200 @@ -0,0 +1,24 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../../.. + +TARGET = \ + dstest_block_client dstest_block_client_simple \ + dstest_host_client \ + dstest_pipe_client \ + dstest_test_client \ + +MODE = static + +SRC_CC_dstest_block_client = dstest_block_client.cc + +SRC_CC_dstest_block_client_simple = dstest_block_client_simple.cc + +SRC_CC_dstest_host_client = dstest_host_client.cc + +SRC_CC_dstest_pipe_client = dstest_pipe_client.cc + +SRC_CC_dstest_test_client = dstest_test_client.cc + +REQUIRES_LIBS = l4re_c-util libfsclient libmem libipc libstdc++ libsystypes + +include $(L4DIR)/mk/prog.mk diff -r bf981cb9a709 -r b6dab1e89e3c tests/dstest_block_client.cc --- a/tests/dstest_block_client.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/tests/dstest_block_client.cc Thu Apr 15 23:15:17 2021 +0200 @@ -28,8 +28,8 @@ #include #include -#include "file.h" -#include "memory_utils.h" +#include +#include diff -r bf981cb9a709 -r b6dab1e89e3c tests/dstest_block_client_simple.cc --- a/tests/dstest_block_client_simple.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/tests/dstest_block_client_simple.cc Thu Apr 15 23:15:17 2021 +0200 @@ -23,7 +23,7 @@ #include -#include "client.h" +#include diff -r bf981cb9a709 -r b6dab1e89e3c tests/dstest_host_client.cc --- a/tests/dstest_host_client.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/tests/dstest_host_client.cc Thu Apr 15 23:15:17 2021 +0200 @@ -28,8 +28,8 @@ #include #include -#include "file.h" -#include "memory_utils.h" +#include +#include diff -r bf981cb9a709 -r b6dab1e89e3c tests/dstest_pipe_client.cc --- a/tests/dstest_pipe_client.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/tests/dstest_pipe_client.cc Thu Apr 15 23:15:17 2021 +0200 @@ -26,8 +26,8 @@ #include #include -#include "file.h" -#include "memory_utils.h" +#include +#include diff -r bf981cb9a709 -r b6dab1e89e3c tests/dstest_test_client.cc --- a/tests/dstest_test_client.cc Tue Apr 13 00:03:18 2021 +0200 +++ b/tests/dstest_test_client.cc Thu Apr 15 23:15:17 2021 +0200 @@ -34,8 +34,8 @@ #include -#include "file.h" -#include "memory_utils.h" +#include +#include