Skip to content

Commit

Permalink
zmalloc/dwarfstar: move ROUNDUP and minimum size of area to free during
Browse files Browse the repository at this point in the history
realloc to the application to make the zmalloc library more universally
usable instead of imposing application specific behaviour to every user.
the resulting binary is slightly larger, but speed is the same.
  • Loading branch information
ivop committed Sep 14, 2024
1 parent 690f7af commit 13f1a81
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 27 deletions.
17 changes: 10 additions & 7 deletions apps/dwarfstar.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#include "lib/zmalloc.h"
#include "lib/screen.h"

#define ROUNDUP(x) (((x)+7) & -8) // nearest multiple of 8
#define MINSIZE 8 // realloc doesn't free smaller than this

struct erow {
int size;
char *chars;
Expand Down Expand Up @@ -65,13 +68,13 @@ bool editorInsertRow(int at, char *s, size_t len) {

void *tmp;
if (E.numrows == E.rowsroom) {
tmp = zrealloc(E.row, sizeof(struct erow) * (E.rowsroom + ROOMINC));
tmp = zrealloc(E.row, ROUNDUP(sizeof(struct erow) * (E.rowsroom + ROOMINC)));
if (!tmp) return false;
E.row = tmp;
E.rowsroom += ROOMINC;
}

tmp = zmalloc(len + 1);
tmp = zmalloc(ROUNDUP(len + 1));
if (!tmp) return false;

memmove(&E.row[at+1], &E.row[at], sizeof(struct erow) * (E.numrows - at));
Expand Down Expand Up @@ -105,7 +108,7 @@ void editorDelRow(int at) {
bool editorRowInsertChar(struct erow *row, int at, uint8_t c) {
if (at < 0 || at > row->size) at = row->size;

void *tmp = zrealloc(row->chars, row->size + 2);
void *tmp = zrealloc(row->chars, ROUNDUP(row->size + 2));
if (!tmp) return false;

row->chars = tmp;
Expand All @@ -117,7 +120,7 @@ bool editorRowInsertChar(struct erow *row, int at, uint8_t c) {
}

bool editorRowAppendString(struct erow *row, char *s, size_t len) {
void *tmp = zrealloc(row->chars, row->size + len + 1);
void *tmp = zrealloc(row->chars, ROUNDUP(row->size + len + 1));
if (!tmp) return false;
row->chars = tmp;
memcpy(&row->chars[row->size], s, len);
Expand Down Expand Up @@ -151,7 +154,7 @@ void editorInsertChar(uint8_t c) {

void editorClearToEOL(struct erow *row) {
row->size = E.cx;
row->chars = zrealloc(row->chars, row->size + 1);
row->chars = zrealloc(row->chars, ROUNDUP(row->size + 1));
}

void editorInsertNewline(void) {
Expand Down Expand Up @@ -709,8 +712,8 @@ void initEditor(void) {

uint16_t tpa = cpm_bios_gettpa();
uint8_t *top = (uint8_t *) (tpa & 0xff00);
// zmalloc_init(cpm_ram, 4096); // test low RAM
zmalloc_init(cpm_ram, top - cpm_ram);
// zmalloc_init(cpm_ram, 4096, MINSIZE); // test low RAM
zmalloc_init(cpm_ram, top - cpm_ram, MINSIZE);

screen_getsize(&E.screencols, &E.screenrows);
E.screencols++;
Expand Down
24 changes: 5 additions & 19 deletions lib/zmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,11 @@
*/

#include <stdbool.h>
#include <stdint.h>
#include <string.h> // memset, memcpy
#include <stdlib.h> // abort

// Round up, use to avoid constant copies on ascending realloc sizes and
// reduce memory fragmentation
//
//#define ROUNDUP(x) x // no roundup
//#define ROUNDUP(x) (((x)+3) & -4) // nearest multiple of 4

#define ROUNDUP(x) (((x)+7) & -8) // nearest multiple of 8
#define MINSIZE 8 // used during realloc

//#define ROUNDUP(x) (((x)+15) & -16) // nearest multiple of 16
//#define ROUNDUP(x) (((x)+31) & -32) // nearest multiple of 32

static void *base;
static uint8_t minsize = 1;

struct block_info;

Expand All @@ -37,21 +26,20 @@ struct __attribute__((packed)) block_info {

static struct block_info sentinel_begin, sentinel_end;

void zmalloc_init(void *start, size_t size) {
void zmalloc_init(void *start, size_t size, uint8_t realloc_free_minsize) {
base = start;
struct block_info *p = base;
p->free = 1;
p->size = size - block_info_size;
p->prev = &sentinel_begin;
p->next = &sentinel_end;
p->prev->next = p->next->prev = p;
minsize = realloc_free_minsize;
}

void *zmalloc(size_t size) {
if (!size) return NULL;

size = ROUNDUP(size);

struct block_info *p;

for (p = base; p && !(p->free && p->size >= size); p = p->next) ; // find
Expand Down Expand Up @@ -124,8 +112,6 @@ void *zrealloc(void *ptr, size_t size) {
if (!ptr) return zmalloc(size);
if (!size) { zfree(ptr); return NULL; }

size = ROUNDUP(size);

struct block_info *p = (void *) ptr - block_info_size;

if (size > p->size) { // bigger
Expand All @@ -135,7 +121,7 @@ void *zrealloc(void *ptr, size_t size) {
memcpy(q, ptr, p->size);
zfree(ptr);
return q;
} else if (p->size > size + block_info_size + MINSIZE) { // smaller enough
} else if (p->size > size + block_info_size + minsize) { // smaller enough
// split and create new free block
struct block_info *q = (void *) p + block_info_size + size;
q->next = p->next;
Expand Down
3 changes: 2 additions & 1 deletion lib/zmalloc.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#pragma once
#include <stddef.h>
#include <stdint.h>

void zmalloc_init(void *start, size_t size);
void zmalloc_init(void *start, size_t size, uint8_t realloc_free_minsize);
void *zmalloc(size_t size);
void *zcalloc(size_t nmemb, size_t size);
void zfree(void *ptr);
Expand Down

0 comments on commit 13f1a81

Please sign in to comment.