Browse Source

Removed macros, use inlines and consts

main
Titouan Rigoudy 11 years ago
parent
commit
6f79c4a8ef
2 changed files with 51 additions and 42 deletions
  1. +46
    -20
      ya_block.c
  2. +5
    -22
      ya_block.h

+ 46
- 20
ya_block.c View File

@ -20,6 +20,17 @@
#include "ya_debug.h" #include "ya_debug.h"
#include "ya_block.h" #include "ya_block.h"
/*-----------*/
/* Constants */
/*-----------*/
/* big enough to hold a pointer */
static const size_t WORD_SIZE = sizeof(intptr_t);
/* request memory 8k by 8k from OS */
static const size_t CHUNK_SIZE = 8192;
/* smallest block: dword-aligned with two boundary tags */
static const size_t MIN_BLOCK_SIZE = 4;
/*---------*/ /*---------*/
/* Globals */ /* Globals */
/*---------*/ /*---------*/
@ -27,6 +38,20 @@
intptr_t *heap_start = NULL; // with space for 2 words before intptr_t *heap_start = NULL; // with space for 2 words before
intptr_t *heap_end = NULL; // first block outside heap intptr_t *heap_end = NULL; // first block outside heap
/*---------*/
/* Inlines */
/*---------*/
/* Returns the smallest number p such that n <= p*m. */
static inline intptr_t round_div(intptr_t n, intptr_t m) {
return (n + m - 1) / m;
}
/* Returns the smallest multiple of m that is >= n. */
static inline intptr_t round_to(intptr_t n, intptr_t m) {
return round_div(n,m) * m;
}
/*----------------------*/ /*----------------------*/
/* Function definitions */ /* Function definitions */
/*----------------------*/ /*----------------------*/
@ -77,18 +102,18 @@ void block_clear(intptr_t *block) {
/* Returns the size in words of the smallest block that can /* Returns the size in words of the smallest block that can
* store n_bytes bytes. Takes alignment and boundary tags into account */ * store n_bytes bytes. Takes alignment and boundary tags into account */
intptr_t block_fit(size_t n_bytes) { intptr_t block_fit(size_t n_bytes) {
intptr_t n_words = YA_ROUND_DIV(n_bytes, YA_WORD_SZ); // size in words
intptr_t n_words = round_div(n_bytes, WORD_SIZE); // size in words
// round to dword and make space for tags // round to dword and make space for tags
intptr_t size = 2 + YA_ROUND(n_words, 2);
intptr_t size = 2 + round_to(n_words, 2);
ya_debug("block_fit: requested = %ld, allocating = %ld * %ld = %ld\n", ya_debug("block_fit: requested = %ld, allocating = %ld * %ld = %ld\n",
n_bytes, size, YA_WORD_SZ, size * YA_WORD_SZ);
n_bytes, size, WORD_SIZE, size * WORD_SIZE);
return size; return size;
} }
/* Tries to coalesce a block with its previous neighbor. /* Tries to coalesce a block with its previous neighbor.
* Returns a pointer to the coalesced block. */ * Returns a pointer to the coalesced block. */
intptr_t *block_join_prev(intptr_t *block) { intptr_t *block_join_prev(intptr_t *block) {
if (block < heap_start + YA_BLK_MIN_SZ) {
if (block < heap_start + MIN_BLOCK_SIZE) {
return block; // there cannot be a previous block return block; // there cannot be a previous block
} }
intptr_t prev_size = tag_size(block[-2]); intptr_t prev_size = tag_size(block[-2]);
@ -118,6 +143,7 @@ intptr_t *block_join_next(intptr_t *block) {
return block; return block;
} }
/* Tries to coalesce a block with its previous and next neighbors. /* Tries to coalesce a block with its previous and next neighbors.
* Returns a pointer to the coalesced block. */ * Returns a pointer to the coalesced block. */
intptr_t *block_join(intptr_t *block) { intptr_t *block_join(intptr_t *block) {
@ -129,7 +155,7 @@ intptr_t *block_join(intptr_t *block) {
* Returns a pointer to the second block or NULL if no split occurred. */ * Returns a pointer to the second block or NULL if no split occurred. */
intptr_t *block_split(intptr_t *block, intptr_t size) { intptr_t *block_split(intptr_t *block, intptr_t size) {
intptr_t next_size = block_size(block) - size; intptr_t next_size = block_size(block) - size;
if (next_size < YA_BLK_MIN_SZ) {
if (next_size < MIN_BLOCK_SIZE) {
return NULL; // not enough space to warrant a split return NULL; // not enough space to warrant a split
} }
block_init(block, size); block_init(block, size);
@ -157,8 +183,8 @@ intptr_t *block_find(intptr_t min_size) {
* Sets heap_start and heap_end to their appropriate values. * Sets heap_start and heap_end to their appropriate values.
* Returns the pointer to the start of the heap or NULL in case of failure. */ * Returns the pointer to the start of the heap or NULL in case of failure. */
intptr_t *heap_init() { intptr_t *heap_init() {
intptr_t size_w = YA_CHUNK_SZ / YA_WORD_SZ;
void *ptr = sbrk(YA_WORD_SZ * (size_w + 2));
intptr_t size = block_fit(CHUNK_SIZE);
void *ptr = sbrk(WORD_SIZE * (size + 2));
if (ptr == (void*) -1) { if (ptr == (void*) -1) {
heap_start = NULL; heap_start = NULL;
heap_end = NULL; heap_end = NULL;
@ -166,28 +192,28 @@ intptr_t *heap_init() {
} }
heap_start = ptr; // cast to intptr_t * heap_start = ptr; // cast to intptr_t *
heap_start += 2; // space for the first block[-1] + dword alignment heap_start += 2; // space for the first block[-1] + dword alignment
heap_end = heap_start + size_w;
block_init(heap_start, size_w);
ya_debug("heap_init: start = %p, end = %p, size_w = %ld\n",
heap_start, heap_end, size_w);
heap_end = heap_start + size;
block_init(heap_start, size);
ya_debug("heap_init: start = %p, end = %p, size = %ld\n",
heap_start, heap_end, size);
return heap_start; return heap_start;
} }
/* Extends the heap by at least size_w words by calling sbrk. /* Extends the heap by at least size_w words by calling sbrk.
* Returns a pointer to the last (free) block or NULL in case of failure. */ * Returns a pointer to the last (free) block or NULL in case of failure. */
intptr_t *heap_extend(intptr_t size_w) {
intptr_t size = YA_ROUND(size_w * YA_WORD_SZ, YA_CHUNK_SZ);
size_w = size / YA_WORD_SZ;
ya_debug("heap_extend: size_w = %ld\n", size_w);
void *ptr = sbrk(size);
intptr_t *heap_extend(intptr_t size) {
intptr_t n_bytes = round_to(size * WORD_SIZE, CHUNK_SIZE);
size = n_bytes / WORD_SIZE;
ya_debug("heap_extend: n_bytes = %ld size = %ld\n", n_bytes, size);
void *ptr = sbrk(n_bytes);
if (ptr == (void *) - 1) { if (ptr == (void *) - 1) {
return NULL; return NULL;
} }
intptr_t *block = ptr; // == old heap_end intptr_t *block = ptr; // == old heap_end
heap_end = block + size_w;
block_init(block, size_w);
ya_debug("heap_extend: old end = %p, new end = %p, size_w = %ld\n",
block, heap_end, size_w);
heap_end = block + size;
block_init(block, size);
ya_debug("heap_extend: old end = %p, new end = %p, size = %ld\n",
block, heap_end, size);
ya_print_blocks(); ya_print_blocks();
return block_join(ptr); return block_join(ptr);
} }

+ 5
- 22
ya_block.h View File

@ -3,8 +3,8 @@
* ya_block.h * ya_block.h
*/ */
#ifndef BLOCK_H
#define BLOCK_H
#ifndef YA_BLOCK_H
#define YA_BLOCK_H
/*----------*/ /*----------*/
/* Includes */ /* Includes */
@ -14,25 +14,8 @@
#include <stdint.h> // for intptr_t #include <stdint.h> // for intptr_t
#include <stdbool.h> #include <stdbool.h>
/*-----------*/
/* Constants */
/*-----------*/
#define YA_WORD_SZ (sizeof(intptr_t)) // big enough to hold a pointer
#define YA_DWORD_SZ (2 * YA_WORD_SZ) // storage is aligned to a dword
#define YA_CHUNK_SZ 8192 // request memory 8k by 8k from OS
#define YA_BLK_MIN_SZ 4 // smallest block: dword-aligned with two boundary tags
/*--------*/
/* Macros */
/*--------*/
#define YA_ROUND_DIV(n, m) (((n) + ((m)-1)) / (m))
#define YA_ROUND(n, m) (YA_ROUND_DIV(n,m) * (m))
/*---------*/ /*---------*/
/* Globals */
/* Externs */
/*---------*/ /*---------*/
extern intptr_t *heap_start; // with space for 2 words before extern intptr_t *heap_start; // with space for 2 words before
@ -112,8 +95,8 @@ intptr_t *block_join(intptr_t *block);
* Returns a pointer to the second block or NULL if no split occurred. */ * Returns a pointer to the second block or NULL if no split occurred. */
intptr_t *block_split(intptr_t *block, intptr_t size); intptr_t *block_split(intptr_t *block, intptr_t size);
/* Try to find a free block at least size words big by walking the boundary
* tags. If no block is found the heap is grown adequately.
/* Try to find a free block at least min_size words big by walking the
* boundary tags. If no block is found the heap is grown adequately.
* Returns a pointer to the block or NULL in case of failure. */ * Returns a pointer to the block or NULL in case of failure. */
intptr_t *block_find(intptr_t min_size); intptr_t *block_find(intptr_t min_size);


Loading…
Cancel
Save