diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/apos/bits.h | 72 | ||||
| -rw-r--r-- | include/apos/mem.h | 153 | ||||
| -rw-r--r-- | include/apos/pmem.h | 14 |
3 files changed, 116 insertions, 123 deletions
diff --git a/include/apos/bits.h b/include/apos/bits.h index ce3aba1..adb8e85 100644 --- a/include/apos/bits.h +++ b/include/apos/bits.h @@ -14,6 +14,17 @@ /** @name Arithmetic integer bit manipulation. */ /** @{ */ +/** + * Find first set bit in \c int. + * + * @param v Integer to find first set bit in. + * @return Index of least significant bit + 1 or 0 if \p v is 0. + */ +#if __has_builtin(__builtin_ffs) +#define ffs(v) __builtin_ffs(v) +#else +int ffs(int v); +#endif /** * Check if bits are set. @@ -134,6 +145,67 @@ static inline void bitmap_clear(void *bmap, size_t n) clear_nbit(bitmap[i], r); } +/** + * Find first bit, either set or unset, in bitmap. + * + * @param bmap Bitmap. + * @param n Size of bitmap in bits. + * @param set Wether to seek for set or unset bits. + * @return Index of found bit + 1 or \p n + 1 if no bit was found. + */ +static inline size_t bitmap_find_first(void *bmap, size_t n, bool set) +{ + size_t i = n / (sizeof(int) * 8); + + size_t c = 0; + int *imap = (int *)bmap; + + int target = set ? 0 : -1; + for (; c < i; ++c) + if (imap[c] != target) + break; + + size_t b = c * sizeof(int) * 8; + int check = set ? imap[c] : ~imap[c]; + if (c != i) + return b + ffs(check) - 1; + + size_t r = n - (i * sizeof(int) * 8); + if (!r) + return n + 1; + + bool comp = set ? true : false; + for (size_t a = 0; a < r; ++a) + if (bitmap_is_set(bmap, b + a) == comp) + return b + a; + + return n + 1; +} + +/** + * Convenience wrapper around bitmap_find_first(). + * + * @param bmap \see bitmap_find_first(). + * @param n \see bitmap_find_first(). + * @return \see bitmap_find_first(). + */ +static inline size_t bitmap_find_first_unset(void *bmap, size_t n) +{ + return bitmap_find_first(bmap, n, false); +} + +/** + * Convenience wrapper around bitmap_find_first(). + * + * @param bmap \see bitmap_find_first(). + * @param n \see bitmap_find_first(). + * @return \see bitmap_find_first(). + */ +static inline size_t bitmap_find_first_set(void *bmap, size_t n) +{ + return bitmap_find_first(bmap, n, true); +} + /** @} */ /** diff --git a/include/apos/mem.h b/include/apos/mem.h index 0eed025..da88edb 100644 --- a/include/apos/mem.h +++ b/include/apos/mem.h @@ -12,99 +12,15 @@ #include <apos/utils.h> #include <apos/types.h> -/** Helper macro for getting bit width of \ref mm_info_t. */ -#define MM_OINFO_WIDTH (sizeof(mm_info_t) * 8) - -/** - * Extract index of page order \c order from base page index \c pnum. - * - * @param pnum Base page order index. - * @param order Order page index to convert to. - * @return Index of page order \c order. - */ -#define pnum_to_index(pnum, order) \ - (((pnum) >> order_offset(order)) & (order_width(order) - 1)) - /** * Convert physical memory address \c paddr to index of page order \c order. * - * @param paddr Physical memory address. + * @param p Physical memory address. * @param order Order page index to convert to. * @return Index of page order \c order. */ -#define pm_to_index(paddr, order) \ - (pnum_to_index(pm_to_pnum(paddr), (order))) - -/** - * Convert physical memory address \c paddr to corresponding page number. - * - * @param paddr Physical memory address. - * @return Corresponding page number. - */ -#define pm_to_pnum(paddr) ((paddr) >> __mm_page_shift) - -/** - * Convert page number to physical address. - * Note that since a page number is the base page an address lies in, - * @code pnum_to_pm(pm_to_pnum(p)) != p @endcode - * - * @param pnum Page number. - * @return Corresponding physical address. - */ -#define pnum_to_pm(pnum) ((pnum) << __mm_page_shift) - -/** - * Add \c num to \c var and return value before addition. - * - * @param var Variable to add \c num to. - * @param num Number to add to \c var. - * @return Value of \c var before addition. - */ -#define move_forward(var, num) (((var) += (num)) - (num)) - -/** - * Helper for calculating highest index of elements in order info map. - * Since the number of entries is stored with the granularity of \c MM_OINFO_WIDTH, - * the highest index element is \c num rounded up to the nearest index multiple - * of \c MM_OINFO_WIDTH. This is due to some data access optimizations over in - * common/pmem.c. - * - * @param num Number of entries in map. - * @return Highest index of element in map. - */ -#define num_elems(num) \ - (((num) + MM_OINFO_WIDTH - 1) / MM_OINFO_WIDTH) -/** - * Helper for calculating starting index of element. - * - * @param num Number of starting entry. - * @return Index of starting element in which entry resides. - */ -#define num_indexes(num) ((num) / MM_OINFO_WIDTH) - -/** - * Helper for calculating index of element from entry number. - * - * @param num Entry number. - * @return Index of element in which entry resides. - */ -#define index_elems(num) ((num) / MM_OINFO_WIDTH) - -/** - * Helper for calculating size of state for storing elements in. - * - * @param num Number of entries. - * @return Size of element state buffer. - */ -#define state_elems(num) (sizeof(mm_info_t) * (num_elems(num))) - -/** - * Helper for calculating size of pointer buffer. - * - * @param num Number of entries. - * @return Size of pointer buffer. - */ -#define next_elems(num) (sizeof(void *) * (num)) +#define pm_to_index(p, order) \ + ((p >> order_shift(order)) & (order_width(order) - 1)) /** * Get highest possible index in an order. @@ -120,7 +36,7 @@ * @param order Order to query. * @return Starting offset of order bits. */ -#define order_offset(order) (__mm_shifts[order]) +#define order_shift(order) (__mm_shifts[order]) /** * Get number of order bits in an address. @@ -139,6 +55,20 @@ #define order_size(order) (__mm_sizes[order]) /** + * Get highest order supported by the current configuration. + * + * @return Max supported order. + */ +#define max_order() (__mm_max_order) + +/** + * Get base page shift. + * + * @return Page shift. + */ +#define page_shift() (__mm_page_shift) + +/** * Get number of elements needed to represent this order. * * @param order Order to query. @@ -154,14 +84,6 @@ */ #define order_container(idx) ((idx) / MM_OINFO_WIDTH) -/** - * Entry index within the element that contains it. - * - * @param idx Index of entry. - * @return Index of entry within its containing element. - */ -#define order_bit(idx) ((idx) & (MM_OINFO_WIDTH - 1)) - /** \todo Get rid of slightly ugly __* syntax, as these aren't static. */ /** @@ -183,8 +105,6 @@ /** * Get page number of physical address. * - * \todo Isn't this the same as \ref pm_to_pnum()? - * * @param x Physical address. * @return Corresponding page number. */ @@ -225,23 +145,11 @@ /** Maximum number of page orders allowed. Likely massively overkill. */ #define NUM_ORDERS 10 -/** Gives access to global page order shift information. \global */ -extern size_t __mm_shifts[NUM_ORDERS]; - -/** Gives access to global page order width information. \global */ -extern size_t __mm_widths[NUM_ORDERS]; - -/** Gives access to global page order size information. \global */ -extern size_t __mm_sizes[NUM_ORDERS]; - -/** Gives access to global base page shift. \global */ -extern size_t __mm_page_shift; - -/** Gives access to global maximum order size. \global */ -extern size_t __mm_max_order; - /** Give names to page orders. */ enum mm_order { + /** NULL marker. */ + MM_MIN = -1, + /** Base order. */ MM_O0 = 0, @@ -271,10 +179,25 @@ enum mm_order { /** Order 9. */ MM_O9 = 9, + + /** Number of orders */ + MM_NUM, }; -/** Page number. */ -typedef ssize_t pnum_t; +/** Gives access to global page order shift information. \global */ +extern size_t __mm_shifts[NUM_ORDERS]; + +/** Gives access to global page order width information. \global */ +extern size_t __mm_widths[NUM_ORDERS]; + +/** Gives access to global page order size information. \global */ +extern size_t __mm_sizes[NUM_ORDERS]; + +/** Gives access to global base page shift. \global */ +extern size_t __mm_page_shift; + +/** Gives access to global maximum order size. \global */ +extern enum mm_order __mm_max_order; /** * Initialize memory subsystem data. Populates __mm_* with data given. diff --git a/include/apos/pmem.h b/include/apos/pmem.h index fe03242..6278b57 100644 --- a/include/apos/pmem.h +++ b/include/apos/pmem.h @@ -17,17 +17,17 @@ * Free physical page. * * @param order Order of page to free. - * @param paddr Physical address of page. + * @param addr Physical address of page. */ -void free_page(enum mm_order order, pm_t paddr); +void free_page(enum mm_order order, pm_t addr); /** * Mark page used. * * @param order Order of page to mark. - * @param paddr Physical address of page. + * @param addr Physical address of page. */ -void mark_used(enum mm_order order, pm_t paddr); +void mark_used(enum mm_order order, pm_t addr); /** * Allocate physical page. @@ -36,10 +36,9 @@ void mark_used(enum mm_order order, pm_t paddr); * allows us to skip already checked pages when allocating a second page. * * @param order Order of page to allocate. - * @param offset Hint as to which address to start looking from. * @return pm_t Physical address of page when succesful, else \c NULL. */ -pm_t alloc_page(enum mm_order order, pm_t offset); +pm_t alloc_page(enum mm_order order); /** * Populate physical RAM usage map. @@ -56,12 +55,11 @@ pm_t populate_pmap(pm_t ram_base, size_t ram_size, pm_t cont); /** * Probe size of RAM usage map. * - * @param ram_base Base physical address of RAM. * @param ram_size Size of physical RAM. * @return Size of physical map. Check that it matches with \ref * populate_pmap(). */ -pm_t probe_pmap(pm_t ram_base, size_t ram_size); +pm_t probe_pmap(size_t ram_size); /** * Initialize physical memory subsystem. |
