Stacks grow down now
This commit is contained in:
1 parent
fd738bface
commit
15ad640202
1 file changed
+36
-14
+36
-14
@@ -1,6 +1,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
struct forkable_stack_header {
|
struct forkable_stack_header {
|
||||||
int next;
|
int next;
|
||||||
@@ -9,15 +10,18 @@ struct forkable_stack_header {
|
|||||||
#define FORKABLE_STACK_HEADER struct forkable_stack_header fk_header_
|
#define FORKABLE_STACK_HEADER struct forkable_stack_header fk_header_
|
||||||
|
|
||||||
struct forkable_stack {
|
struct forkable_stack {
|
||||||
|
// Stack grows down from stk+length
|
||||||
|
|
||||||
char* stk;
|
char* stk;
|
||||||
|
|
||||||
// stk+length is just past end of allocated area
|
// stk+length is just past end of allocated area
|
||||||
|
// stk = malloc(length)
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
// stk+pos is just past top-of-stack item
|
// stk+pos is header of top object, or stk+length if empty
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
// everything before stk+savedlimit must be preserved
|
// everything after-or-including stk+savedlimit must be preserved
|
||||||
int savedlimit;
|
int savedlimit;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,66 +33,84 @@ static void forkable_stack_check(struct forkable_stack* s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int forkable_stack_empty(struct forkable_stack* s) {
|
static int forkable_stack_empty(struct forkable_stack* s) {
|
||||||
return s->pos == 0;
|
return s->pos == s->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void forkable_stack_init(struct forkable_stack* s, size_t sz) {
|
static void forkable_stack_init(struct forkable_stack* s, size_t sz) {
|
||||||
s->stk = malloc(sz);
|
s->stk = malloc(sz);
|
||||||
s->length = sz;
|
s->length = sz;
|
||||||
s->pos = 0;
|
s->pos = s->length;
|
||||||
s->savedlimit = 0;
|
s->savedlimit = s->length;
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* forkable_stack_push(struct forkable_stack* s, size_t size) {
|
static void* forkable_stack_push(struct forkable_stack* s, size_t size) {
|
||||||
forkable_stack_check(s);
|
forkable_stack_check(s);
|
||||||
int curr = s->pos > s->savedlimit ? s->pos : s->savedlimit;
|
int curr = s->pos < s->savedlimit ? s->pos : s->savedlimit;
|
||||||
if (curr + size > s->length) {
|
if (curr - size < 0) {
|
||||||
s->length = (size + s->length + 1024) * 2;
|
assert(0);
|
||||||
|
int oldlen = s->length;
|
||||||
|
s->length = (size + oldlen + 1024) * 2;
|
||||||
s->stk = realloc(s->stk, s->length);
|
s->stk = realloc(s->stk, s->length);
|
||||||
|
int shift = s->length - oldlen;
|
||||||
|
memmove(s->stk + shift, s->stk, oldlen);
|
||||||
|
s->pos += shift;
|
||||||
|
s->savedlimit += shift;
|
||||||
|
curr += shift;
|
||||||
}
|
}
|
||||||
void* ret = (void*)(s->stk + curr);
|
void* ret = (void*)(s->stk + curr - size);
|
||||||
((struct forkable_stack_header*)ret)->next = s->pos;
|
((struct forkable_stack_header*)ret)->next = s->pos;
|
||||||
s->pos = curr + size;
|
s->pos = curr - size;
|
||||||
|
forkable_stack_check(s);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* forkable_stack_peek(struct forkable_stack* s, size_t size) {
|
static void* forkable_stack_peek(struct forkable_stack* s, size_t size) {
|
||||||
assert(!forkable_stack_empty(s));
|
assert(!forkable_stack_empty(s));
|
||||||
return (void*)(s->stk + s->pos - size);
|
forkable_stack_check(s);
|
||||||
|
return (void*)(s->stk + s->pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* forkable_stack_peek_next(struct forkable_stack* s, void* top, size_t size) {
|
static void* forkable_stack_peek_next(struct forkable_stack* s, void* top, size_t size) {
|
||||||
|
forkable_stack_check(s);
|
||||||
struct forkable_stack_header* elem = top;
|
struct forkable_stack_header* elem = top;
|
||||||
return (void*)(s->stk + elem->next - size);
|
return (void*)(s->stk + elem->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void forkable_stack_pop(struct forkable_stack* s, size_t size) {
|
static void forkable_stack_pop(struct forkable_stack* s, size_t size) {
|
||||||
|
forkable_stack_check(s);
|
||||||
struct forkable_stack_header* elem = forkable_stack_peek(s, size);
|
struct forkable_stack_header* elem = forkable_stack_peek(s, size);
|
||||||
s->pos = elem->next;
|
s->pos = elem->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct forkable_stack_state {
|
struct forkable_stack_state {
|
||||||
int prevpos, prevlimit;
|
int prevpos, prevlimit;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void forkable_stack_save(struct forkable_stack* s, struct forkable_stack_state* state) {
|
static void forkable_stack_save(struct forkable_stack* s, struct forkable_stack_state* state) {
|
||||||
|
forkable_stack_check(s);
|
||||||
state->prevpos = s->pos;
|
state->prevpos = s->pos;
|
||||||
state->prevlimit = s->savedlimit;
|
state->prevlimit = s->savedlimit;
|
||||||
if (s->pos > s->savedlimit) s->savedlimit = s->pos;
|
if (s->pos < s->savedlimit) s->savedlimit = s->pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void forkable_stack_switch(struct forkable_stack* s, struct forkable_stack_state* state) {
|
static void forkable_stack_switch(struct forkable_stack* s, struct forkable_stack_state* state) {
|
||||||
|
forkable_stack_check(s);
|
||||||
int curr_pos = s->pos;
|
int curr_pos = s->pos;
|
||||||
s->pos = state->prevpos;
|
s->pos = state->prevpos;
|
||||||
state->prevpos = curr_pos;
|
state->prevpos = curr_pos;
|
||||||
|
|
||||||
int curr_limit = s->savedlimit;
|
int curr_limit = s->savedlimit;
|
||||||
if (curr_pos > curr_limit) s->savedlimit = curr_pos;
|
if (curr_pos < curr_limit) s->savedlimit = curr_pos;
|
||||||
state->prevlimit = curr_limit;
|
state->prevlimit = curr_limit;
|
||||||
|
forkable_stack_check(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void forkable_stack_restore(struct forkable_stack* s, struct forkable_stack_state* state) {
|
static void forkable_stack_restore(struct forkable_stack* s, struct forkable_stack_state* state) {
|
||||||
|
forkable_stack_check(s);
|
||||||
s->pos = state->prevpos;
|
s->pos = state->prevpos;
|
||||||
s->savedlimit = state->prevlimit;
|
s->savedlimit = state->prevlimit;
|
||||||
|
forkable_stack_check(s);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user