aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2022-05-29 21:48:00 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2022-05-29 21:48:00 +0300
commit6295648f04d1d5d7e8b99d3fdaa8d497406eadf9 (patch)
treed2bbe97ae40213356f9e2611285a78f7bac04bca
parent1f7f2251faaef84cd441088f02a66440fa7b59cc (diff)
downloadkmi-6295648f04d1d5d7e8b99d3fdaa8d497406eadf9.tar.gz
kmi-6295648f04d1d5d7e8b99d3fdaa8d497406eadf9.zip
continue documentation
-rw-r--r--include/apos/mem.h6
-rw-r--r--include/apos/mem_regions.h208
-rw-r--r--include/apos/nodes.h53
3 files changed, 262 insertions, 5 deletions
diff --git a/include/apos/mem.h b/include/apos/mem.h
index a0f32f5..20293db 100644
--- a/include/apos/mem.h
+++ b/include/apos/mem.h
@@ -159,6 +159,8 @@
*/
#define order_bit(idx) ((idx) & (MM_OINFO_WIDTH - 1))
+/** @todo Get rid of slightly ugly __* syntax, as these aren't static. */
+
/**
* Convert physical address to virtual address in direct mapping.
*
@@ -178,7 +180,7 @@
/**
* Get page number of physical address.
*
- * @todo Isn't this the same as \ref pnum_to_pm()?
+ * @todo Isn't this the same as \ref pm_to_pnum()?
*
* @param x Physical address.
* @return Corresponding page number.
@@ -214,7 +216,7 @@
#define MR_OWNED (1 << 10)
/** Copy on write. */
#define MR_COW (1 << 11)
-/** Don't free memory on flush. */
+/** Don't free memory on clear. */
#define MR_KEEP (1 << 12)
/** @} */
diff --git a/include/apos/mem_regions.h b/include/apos/mem_regions.h
index 38629f2..2eaef8c 100644
--- a/include/apos/mem_regions.h
+++ b/include/apos/mem_regions.h
@@ -8,47 +8,200 @@
*/
#include <apos/mem.h>
+#include <arch/vmem.h>
#include <apos/types.h>
#include <apos/sp_tree.h>
-#include <arch/vmem.h>
+/**
+ * Get \ref mem_region container of \c ptr.
+ *
+ * @param ptr Pointer to \c sp_n member in \ref mem_region.
+ * @return Parent \ref mem_region.
+ */
#define mem_container(ptr) container_of(ptr, struct mem_region, sp_n)
+
+/**
+ * Check if memory region is used.
+ *
+ * @param r Memory region to check.
+ * @return \c 0 if not used, non-zero otherwise.
+ */
#define is_region_used(r) is_set(r->flags, MR_USED)
+
+/**
+ * Check if region is owned.
+ *
+ * @param r Memory region to check.
+ * @return \c 0 if not owned, non-zero otherwise.
+ */
#define is_region_owned(r) is_set(r->flags, MR_OWNED)
+
+/**
+ * Check if region is shared.
+ *
+ * @param r Memory region to check.
+ * @return \c 0 if not shared, non-zero otherwise.
+ */
#define is_region_shared(r) is_set(r->flags, MR_SHARED)
+
+/**
+ * Check if region should be kept during clear.
+ *
+ * @param r Memory region to check.
+ * @return \c 0 if not kept, non-zero otherwise.
+ */
#define is_region_kept(r) is_set(r->flags, MR_KEEP)
+/** Root of memory region. */
struct mem_region_root {
+ /** Sp-tree of free regions. */
struct sp_root free_regions;
+
+ /** Sp-tree of used region. */
struct sp_root used_regions;
};
+/**
+ * Memory region.
+ * Regions can have two states, used or free. There are two sp-trees, which keep
+ * track of free and used regions, respectively. All regions are chained
+ * together with a doubly linked list, so that the next region's start address
+ * should be the current region's end address.
+ */
struct mem_region {
+ /** Sp-tree node slot. */
struct sp_node sp_n;
+ /** Next memory region by start address. */
struct mem_region *next;
+
+ /** Previous memory region by end address. */
struct mem_region *prev;
+ /** Memory region flags, both access as well as metadata. \see MR_USED,
+ * MR_SHARED, MR_OWNED, MR_COW, MR_KEEP. */
vmflags_t flags;
+ /** End address of memory region. */
vm_t end;
+
+ /** Start address of memory region. */
vm_t start;
};
+/**
+ * Initialize memory region subsystem instance.
+ *
+ * @param r Memory region root to initialize.
+ * @param start Start of memory arena.
+ * @param arena_size Size of memory arena.
+ * @return \ref OK on success.
+ * @todo Document error codes when I actually implement them properly.
+ */
stat_t init_region(struct mem_region_root *r, vm_t start, size_t arena_size);
+
+/**
+ * Destroy memory region subsystem instance.
+ *
+ * @param r Memory region root to destroy.
+ * @return \ref OK on success.
+ */
stat_t destroy_region(struct mem_region_root *r);
+/**
+ * Allocate memory region.
+ * Will allocate region of at least \c size bytes, with best possible location.
+ *
+ * @param r Memory region root.
+ * @param size Size of region to allocate.
+ * @param actual_size Size of region that was allocated.
+ * @param flags Memory flags.
+ * @return Address of allocated region on success, otherwise \c NULL.
+ */
vm_t alloc_region(struct mem_region_root *r, size_t size, size_t *actual_size,
vmflags_t flags);
+
+/**
+ * Allocate fixed memory region.
+ * Will allocate region that is at least \c size bytes, and includes \c start.
+ * \note The address returned might not be the address requested, and the caller
+ * must keep track of which address it was given, so it can cleanly give it to
+ * \ref free_region() when finished with the allocation.
+ *
+ * @param r Memory region root.
+ * @param start Address that must be within region to allocate.
+ * @param size Size of region to allocate.
+ * @param actual_size Size of region that was allocated.
+ * @param flags Memory flags.
+ * @return Address of allocated region on success, otherwise \c NULL.
+ */
vm_t alloc_fixed_region(struct mem_region_root *r, vm_t start, size_t size,
size_t *actual_size, vmflags_t flags);
+
+/**
+ * Free memory region.
+ *
+ * @param r Memory region root.
+ * @param start Address of region to free.
+ * @return \ref OK on success, \ref ERR_ALIGN if \c start is misaligned and \ref
+ * ERR_NF if the memory region is not found.
+ */
stat_t free_region(struct mem_region_root *r, vm_t start);
+
+/**
+ * Free memory region through a direct pointer to the memory region.
+ * Mainly useful if you look up a region beforehand, do something with it and
+ * then free it. Skips looking up the start address.
+ *
+ * @param r Memory region root.
+ * @param m Memory region to free.
+ * @return \ref OK.
+ * @todo Improve error checking.
+ */
stat_t free_known_region(struct mem_region_root *r, struct mem_region *m);
+/**
+ * Find the memory region with lowest starting address.
+ * This region will also be the first node in the linked list.
+ * Useful when you need to iterate over all regions.
+ *
+ * @param r Memory region root.
+ * @return First memory region when succesful, otherwise \c NULL.
+ */
struct mem_region *find_first_region(struct mem_region_root *r);
+
+/**
+ * Find used memory region at address \c start.
+ *
+ * @param r Memory region root.
+ * @param start Address at which a used region should exist.
+ * @return Pointer to requested memory region when succesful, \c NULL otherwise.
+ */
struct mem_region *find_used_region(struct mem_region_root *r, vm_t start);
+
+/**
+ * Find used memory region closest to \c start.
+ * Useful when you don't necessarily need the exact region, just something close
+ * by.
+ *
+ * @param r Memory region root.
+ * @param start Address region should be closest to.
+ * @return Pointer to memory region closest to \c start when succesful, \c NULL
+ * otherwise.
+ */
struct mem_region *find_closest_used_region(struct mem_region_root *r,
vm_t start);
+
+/**
+ * Find best region that fulfills requested parameters.
+ *
+ * @param r Memory region root.
+ * @param size Size of free region.
+ * @param align Recommended offset into this region from where the allocation
+ * should be carved.
+ * @return Pointer to suitable \c memory_region when succesful, \c NULL
+ * otherwise.
+ */
struct mem_region *find_free_region(struct mem_region_root *r, size_t size,
size_t *align);
@@ -71,10 +224,61 @@ typedef stat_t region_callback_t(struct vmem *vmem, pm_t *offset, vm_t vaddr,
vmflags_t flags, enum mm_order order,
void *data);
+/**
+ * Query flags of region that contains \c va.
+ *
+ * @param r Memory region root.
+ * @param va Address that is within memory region.
+ * @param flags Memory region flags.
+ * @return \ref OK when succesful.
+ * @todo Implement.
+ */
stat_t stat_region(struct mem_region_root *r, vm_t va, vmflags_t *flags);
+
+/**
+ * Modify flags of region that contains \c va.
+ *
+ * @param r Memory region root.
+ * @param va Address that is within memory region.
+ * @param flags New flags of region.
+ * @return \ref OK when succesful.
+ * @todo Implement.
+ */
stat_t mod_region(struct mem_region_root *r, vm_t va, vmflags_t flags);
-vm_t map_fill_region(struct vmem *b, region_callback_t *mem_handler,
+/**
+ * Conversion function between abstract memory region and actual page mappings.
+ * Assumes that pages of some order are mappable at multiples of their size, and
+ * tries to fit as many and as high order pages as it can into the region.
+ * Heavily utilizes \c mem_handler, to which it gives a suggestion for how to
+ * map a page. If this suggestion is accepted and succesfully executed, \c mem_handler
+ * returns \ref OK. If the suggestion is not possible, for example no higher
+ * order pages are available, \c mem_handler returns \ref INFO_TRGN to tell \c
+ * map_fill_region() to give it some other suggestion. Any error value stops the
+ * conversion.
+ *
+ * This 'algorithm' also works quite nicely for freeing a region, but in
+ * reverse, i.e. it is given a suggestion and checks if that suggestion was
+ * executed when the region was mapped. If the suggestion was executed, then the
+ * same suggestion is freed, else \ref INFO_TRGN is returned and a new
+ * suggestion is requested until all pages have been freed.
+ *
+ * There are some more technicalities, for example currently \c
+ * map_fill_region() gives up trying to map higher order pages as soon as its
+ * first suggestion is rejected, which gives us quick conversion times but
+ * probably less than ideal mappings.
+ *
+ * @param vmem Virtual memory inside which to map the region.
+ * @param mem_handler Worker handler callback.
+ * @param offset Offset at which the physical memory availability map should
+ * start searching.
+ * @param start Start address of memory region.
+ * @param bytes Size of memory region.
+ * @param flags Memory flags.
+ * @param data User-specified data.
+ * @return \c start when succesful, \c 0 otherwise.
+ */
+vm_t map_fill_region(struct vmem *vmem, region_callback_t *mem_handler,
pm_t offset, vm_t start, size_t bytes, vmflags_t flags,
void *data);
diff --git a/include/apos/nodes.h b/include/apos/nodes.h
index 3fefc4c..6cec21c 100644
--- a/include/apos/nodes.h
+++ b/include/apos/nodes.h
@@ -9,32 +9,83 @@
#include <apos/types.h>
-enum node_status { FREE = 0, USED = 1 };
+/** Node slot status. */
+enum node_status {
+ /** Free. */
+ FREE = 0,
+
+ /** Used. */
+ USED = 1
+};
+
+/** Header for a region in memory with node slots. */
struct node_region {
+ /** Number of used slots in this region.
+ * \note Total number of slots is calculated on an instance basis. */
size_t used_nodes;
+ /** Next node region in free list. */
struct node_region *av_next;
+
+ /** Previous node region in free list. */
struct node_region *av_prev;
+ /** Next node slot region. */
struct node_region *next;
+
+ /** Previous slot node region. */
struct node_region *prev;
};
+/** Node subsystem instance. */
struct node_root {
+ /** Size of each node. */
size_t node_size;
+ /** Maximum number of node slots in one region. */
size_t max_nodes;
+ /** Offset of node slot state bitmap from start of region. */
ptrdiff_t bitmap;
+
+ /** Offset of first node from start of region. */
ptrdiff_t first_node;
+ /** List of all node regions. */
struct node_region *head;
+
+ /** List of node regions with free slots. */
struct node_region *av_head;
};
+/**
+ * Initialize node subsystem instance.
+ *
+ * @param r Node region root.
+ * @param node_size Size of one node.
+ */
void init_nodes(struct node_root *r, size_t node_size);
+
+/**
+ * Destroy node subsystem instance.
+ *
+ * @param r Node region root.
+ */
void destroy_nodes(struct node_root *r);
+/**
+ * Allocate a new node.
+ *
+ * @param r Node region root.
+ * @return Pointer to allocated node when succesful, \c 0 otherwise.
+ */
void *get_node(struct node_root *r);
+
+/**
+ * Free a node.
+ *
+ * @param r Node region root.
+ * @param p Pointer to node to free.
+ */
void free_node(struct node_root *r, void *p);
#endif /* APOS_NODES_H */