# HG changeset patch # User Paul Boddie # Date 1611103032 -3600 # Node ID c9bcca9486351d6f7d15014032fab9ff70ffd9c2 # Parent b257d5a9ff5913ab674110582896aa8e40d7a35a Test usage of a simple pager. diff -r b257d5a9ff59 -r c9bcca948635 Makefile --- a/Makefile Tue Jan 19 23:26:49 2021 +0100 +++ b/Makefile Wed Jan 20 01:37:12 2021 +0100 @@ -21,7 +21,10 @@ SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC)) -PLAIN_SRC_CC = dstest_server.cc flexpage.cc memory_utils.cc region.cc +PLAIN_SRC_CC = \ + dstest_server.cc flexpage.cc \ + memory.cc memory_map.cc memory_utils.cc \ + region.cc resource.cc simple_pager.cc # Normal definitions. diff -r b257d5a9ff59 -r c9bcca948635 dstest_server.cc --- a/dstest_server.cc Tue Jan 19 23:26:49 2021 +0100 +++ b/dstest_server.cc Wed Jan 20 01:37:12 2021 +0100 @@ -1,7 +1,7 @@ /* * Test dataspace operations. * - * Copyright (C) 2020 Paul Boddie + * Copyright (C) 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 @@ -29,58 +29,19 @@ #include #include "dataspace_server.h" -#include "flexpage.h" +#include "simple_pager.h" /* Component interface. */ -class DataspaceServer : public Dataspace +class DataspaceServer : public SimplePager { -protected: - Region *_region; - offset_t _start, _size; - public: - explicit DataspaceServer(char *addr, offset_t size) - { - _region = new Region((offset_t) addr, (offset_t) addr + size); - _start = 0; - _size = size; - - offset_t i; - int j; - - for (i = 0, j = 0; i < size; i += PAGE_SIZE, j++) - memset((void *) (addr + i), (int) 'a' + j, PAGE_SIZE); - } - - virtual long map(unsigned long offset, l4_addr_t hot_spot, unsigned long flags, l4_snd_fpage_t *region) + explicit DataspaceServer(Memory *memory) + : SimplePager(memory) { - Flexpage flexpage(_region); - offset_t max_offset = _start + _size; - - printf("map(%ld, %lx, %lx, ...)\n", offset, hot_spot, flags); - - flexpage.reset(_start + offset); - - SendFlexpage send_flexpage = flexpage.to_send(offset, hot_spot, max_offset); - - printf("send %lx -> %lx -> {%lx, %d}\n", _region->start, flexpage.base_addr, send_flexpage.base_addr, send_flexpage.order); - - /* Send the flexpage explicitly. */ - - region->fpage = l4_fpage(send_flexpage.base_addr, send_flexpage.order, - (flags & L4RE_DS_MAP_FLAG_RW) ? L4_FPAGE_RW - : L4_FPAGE_RO); - region->snd_base = hot_spot; - - long err = complete_Dataspace_map(*region); - - if (err) - return err; - - return IPC_MESSAGE_SENT; + memset((void *) _region->start, (int) 'a', PAGE_SIZE); } }; @@ -90,17 +51,11 @@ { /* Some memory. */ - char *memory; - - if (posix_memalign((void **) &memory, 40960, 40960)) - { - printf("Could not allocate memory.\n"); - return 1; - } + Memory memory(10); /* Dataspace encapsulation. */ - DataspaceServer obj(memory, 40960); + DataspaceServer obj(&memory); /* Server capability. */ diff -r b257d5a9ff59 -r c9bcca948635 memory.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory.cc Wed Jan 20 01:37:12 2021 +0100 @@ -0,0 +1,80 @@ +#include "memory.h" +#include "memory_map.h" + + + +/* Global memory allocator. */ + +extern Allocator allocator; + + + +/* Initialise the memory pool with an optional 'limit' in pages. */ + +Memory::Memory(unsigned int limit, offset_t region_size) +: _limit(limit), _region_size(region_size) +{ + _limited = true; +} + +Memory::Memory() +: _region_size(PAGE_SIZE) +{ + _limited = false; +} + +/* Allocate a new region of the given 'size' rounded to the nearest page. */ + +Region *Memory::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 = allocator.region(rounded); + + if (region == NULL) + return NULL; + + if (_limited) + _limit -= pages; + + return region; + } + + /* Return no region without sufficient pages. */ + + else + return NULL; +} + +Region *Memory::region() +{ + return region(_region_size); +} + +/* Release the allocated 'region'. */ + +void Memory::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; + + allocator.remove(region); + + delete region; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r b257d5a9ff59 -r c9bcca948635 memory.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory.h Wed Jan 20 01:37:12 2021 +0100 @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include "memory_utils.h" +#include "region.h" +#include "types.h" + + + +/* A memory pool abstraction. */ + +class Memory +{ +protected: + std::mutex _lock; + + unsigned int _limit; + offset_t _region_size; + bool _limited; + +public: + explicit Memory(unsigned int limit, offset_t region_size=PAGE_SIZE); + + explicit Memory(); + + Region *region(offset_t size); + + Region *region(); + + void release(Region *region); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r b257d5a9ff59 -r c9bcca948635 memory_map.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory_map.cc Wed Jan 20 01:37:12 2021 +0100 @@ -0,0 +1,83 @@ +#include + +#include "memory_map.h" +#include "memory_utils.h" + + + +/* Global memory allocator. */ + +Allocator allocator; + + + +/* Region management. */ + +void MemoryMap::insert(Region *region) +{ + std::lock_guard guard(_lock); + + _regions.insert(_MemoryMapEntry(region->start, region)); +} + +void MemoryMap::remove(Region *region) +{ + std::lock_guard guard(_lock); + + _MemoryMap::iterator entry = _regions.find(region->start); + + if (entry != _regions.end()) + _regions.erase(entry); +} + +/* Show the memory state. */ + +void MemoryMap::show(std::ostringstream &buffer) +{ + std::lock_guard guard(_lock); + + _MemoryMap::iterator it; + + buffer << "Mem: "; + + for (it = _regions.begin(); it != _regions.end(); it++) + { + it->second->state.show(buffer); + buffer << " "; + } + + buffer << std::endl; +} + + + +/* Allocate a block of the given 'size'. */ + +Region *Allocator::region(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; + + Region *region = new Region((offset_t) current, (offset_t) current + size); + + insert(region); + return region; +} + +/* Release the allocated 'region'. */ + +void Allocator::release(Region *region) +{ + remove(region); + delete region; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r b257d5a9ff59 -r c9bcca948635 memory_map.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/memory_map.h Wed Jan 20 01:37:12 2021 +0100 @@ -0,0 +1,51 @@ +#pragma once + +#include +#include +#include + +#include "region.h" +#include "types.h" + + + +/* Memory map entry. */ + +typedef std::map _MemoryMap; +typedef std::pair _MemoryMapEntry; + + + +/* Memory organised as a collection of regions. */ + +class MemoryMap +{ +protected: + std::mutex _lock; + _MemoryMap _regions; + +public: + /* Region maintenance. */ + + void insert(Region *region); + + void remove(Region *region); + + /* Debugging methods. */ + + void show(std::ostringstream &buffer); +}; + + + +/* An allocator abstraction. */ + +class Allocator : public MemoryMap +{ +public: + Region *region(offset_t size); + + void release(Region *region); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r b257d5a9ff59 -r c9bcca948635 resource.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resource.cc Wed Jan 20 01:37:12 2021 +0100 @@ -0,0 +1,12 @@ +#include "resource.h" + + +Resource::~Resource() +{ +} + +void Resource::close() +{ +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r b257d5a9ff59 -r c9bcca948635 resource.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/resource.h Wed Jan 20 01:37:12 2021 +0100 @@ -0,0 +1,15 @@ +#pragma once + + + +/* A resource interface. */ + +class Resource +{ +public: + virtual ~Resource(); + + virtual void close(); +}; + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r b257d5a9ff59 -r c9bcca948635 simple_pager.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/simple_pager.cc Wed Jan 20 01:37:12 2021 +0100 @@ -0,0 +1,55 @@ +#include + +#include "dataspace_server.h" +#include "simple_pager.h" + + + +SimplePager::SimplePager(Memory *memory) +{ + if (memory == NULL) + _memory = new Memory(); + 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(unsigned long offset, l4_addr_t hot_spot, unsigned long flags, l4_snd_fpage_t *region) +{ + Flexpage flexpage(_region); + + flexpage.reset(offset); + + /* Issue the flexpage via the IPC system. */ + + SendFlexpage send_flexpage = flexpage.to_send(offset, hot_spot); + + /* Send the flexpage explicitly. */ + + region->fpage = l4_fpage(send_flexpage.base_addr, send_flexpage.order, + (flags & L4RE_DS_MAP_FLAG_RW) ? L4_FPAGE_RW + : L4_FPAGE_RO); + region->snd_base = hot_spot; + + long err = complete_Dataspace_map(*region); + + if (err) + return err; + + return IPC_MESSAGE_SENT; +} + +// vim: tabstop=4 expandtab shiftwidth=4 diff -r b257d5a9ff59 -r c9bcca948635 simple_pager.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/simple_pager.h Wed Jan 20 01:37:12 2021 +0100 @@ -0,0 +1,28 @@ +#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(unsigned long offset, l4_addr_t hot_spot, unsigned long flags, l4_snd_fpage_t *region); +}; + +// vim: tabstop=4 expandtab shiftwidth=4