[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c

Would someone tell me if I'm on the wrong track?

luserXtrog

5/10/2011 6:47:00 AM

I'm trying to build a new memory allocation scheme for
my postscript interpreter to satisfy these requirements:
% pointer + offset + size + short tag <= 32bits
% 'garbage-collection'-ready (structure the heap for easy iteration)
% all memory is in one region for easy restore from disk

So I've written a prototype where the "pointer" is an index
into an extendable address table stored in the heap itself.
And it seems to work! But I don't trust it, you know?

I'd appreciate any comments the experts here could offer.

One apology. I'm trying to use mmap if available or malloc
as a fallback, but ifdefs, it seems, can't be made pretty.
Or, at least I have yet to discover how, unless it's just to
"put it in a file you don't need to look at". :)

569(1)01:27 AM:proto 0> make v
cc -g -Wall v.c -o v
570(1)01:27 AM:proto 0> v
put seven, got a 7
571(1)01:27 AM:proto 0> cat v.c
#define MMAP
#define _GNU_SOURCE

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#ifdef MMAP
#include <sys/mman.h>
#endif /* otherwise, use malloc/realloc/free */

void error(char *msg) {
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}

unsigned pgsz /*= getpagesize()*/;

typedef struct {
unsigned char *base;
unsigned used;
unsigned max;
} mfile;

/* initialize the memory file */
void initmem(mfile *mem) {
#ifdef MMAP
mem->base = mmap(NULL, pgsz, PROT_READ|PROT_WRITE, MAP_SHARED
|MAP_ANONYMOUS,-1,0 );
if (mem->base == MAP_FAILED)
#else
mem->base = malloc(pgsz);
if (mem->base == NULL)
#endif
error("unable to initialize memory file");
mem->used = 0;
mem->max = pgsz;
}

/* destroy memory file */
void exitmem(mfile *mem) {
#ifdef MMAP
munmap(mem->base, mem->max);
#else
free(mem->base);
#endif
mem->base = NULL;
mem->used = 0;
mem->max = 0;
}

/* grow memory by sz */
void growmem(mfile *mem, unsigned sz) {
unsigned char *tmp;
if (sz < pgsz) sz = pgsz;
else sz = (sz/pgsz + 1) * pgsz;
sz += mem->max;
#ifdef MMAP
tmp = mremap(mem->base, mem->max, sz, MREMAP_MAYMOVE);
if (tmp == MAP_FAILED)
#else
tmp = realloc(mem->base, sz);
if (!tmp)
#endif
error("unable to grow memory");
mem->base = tmp;
mem->max = sz;
}

/* allocate memory, returns offset in memory file */
unsigned mfalloc(mfile *mem, unsigned sz) {
unsigned adr = mem->used;
if (sz + mem->used > mem->max) growmem(mem,sz);
mem->used += sz;
return adr;
}


#define TABSZ 1000
typedef struct {
unsigned nexttab;
unsigned nextent;
struct {
unsigned adr;
} tab[TABSZ];
} mtab;

/* allocate and initialize a new table */
unsigned initmtab(mfile *mem) {
unsigned adr;
adr = mfalloc(mem, sizeof(mtab)); /*create mtab at address 0*/
memset(mem->base + adr, 0, sizeof(mtab));
return adr;
}

/* allocate memory, returns table index */
unsigned mtalloc(mfile *mem, unsigned mtabloc, unsigned sz) {
mtab *tab = (void *)(mem->base + mtabloc);
if (tab->nextent >= TABSZ)
return mtalloc(mem, tab->nexttab, sz);
else {
unsigned ent = tab->nextent;
tab->nextent++;
tab->tab[ent].adr = mfalloc(mem, sz);
if (tab->nextent == TABSZ) {
tab->nexttab = initmtab(mem);
}
return ent;
}
}

/* fetch a value from a composite object */
void get(mfile *mem, unsigned ent, unsigned offset, unsigned sz, void
*dest) {
mtab *tab;
unsigned mtabloc = 0;
tab = (void *)(mem->base + mtabloc);
while (ent >= TABSZ) {
tab = (void *)(mem->base + mtabloc);
mtabloc = tab->nexttab;
ent -= TABSZ;
}
memcpy(dest, mem->base + tab->tab[ent].adr + offset*sz, sz);
}

/* put a value into a composite object */
void put(mfile *mem, unsigned ent, unsigned offset, unsigned sz, void
*src) {
mtab *tab;
unsigned mtabloc = 0;
tab = (void *)(mem->base + mtabloc);
while (ent >= TABSZ) {
tab = (void *)(mem->base + mtabloc);
mtabloc = tab->nexttab;
ent -= TABSZ;
}
memcpy(mem->base + tab->tab[ent].adr + offset*sz, src, sz);
}

mfile mem;

/* initialize everything */
void init(void) {
pgsz = getpagesize();
initmem(&mem);
(void)initmtab(&mem); /* init table zero */
}

/* destroy everything */
void xit(void) {
exitmem(&mem);
}


int main() {
init();
unsigned adr;
int seven = 7;
int ret;
adr = mtalloc(&mem, 0, sizeof seven);
put(&mem, adr, 0, sizeof seven, &seven);
get(&mem, adr, 0, sizeof seven, &ret);
printf("put seven, got a %d\n", ret);

xit();
return 0;
}

--
572(1)01:27 AM:proto 0> !ni
nice -n 19 firefox &
[3] 4978
573(2)01:27 AM:proto 0>
21 Answers

luserXtrog

5/10/2011 7:05:00 AM

0

On May 10, 1:47 am, luser- -droog <mijo...@yahoo.com> wrote:
> I'm trying to build a new memory allocation scheme for
> my postscript interpreter to satisfy these requirements:
> % pointer + offset + size + short tag <= 32bits
> % 'garbage-collection'-ready (structure the heap for easy iteration)
> % all memory is in one region for easy restore from disk
>
> So I've written a prototype where the "pointer" is an index
> into an extendable address table stored in the heap itself.
> And it seems to work! But I don't trust it, you know?
[...]

A little more testing always helps.
It still looks good. I feel a little better.

581(2)02:02 AM:proto 0> tail -20 v.c
printf("put seven, got a %d\n", ret);

unsigned adr2;
adr2 = mtalloc(&mem, 0, 8*sizeof seven);
put(&mem, adr2, 6, sizeof seven, &seven);
get(&mem, adr2, 6, sizeof seven, &ret);
printf("put seven in slot 7, got a %d\n", ret);

unsigned adr3;
char str[] = "beads in buddha's necklace";
char sret[sizeof str];
adr3 = mtalloc(&mem, 0, strlen(str)+1);
put(&mem, adr3, 0, sizeof str, str);
get(&mem, adr3, 0, sizeof str, sret);
printf("stored and retrieved %s\n", sret);

xit();
return 0;
}

582(2)02:02 AM:proto 0> v
put seven, got a 7
put seven in slot 7, got a 7
stored and retrieved beads in buddha's necklace
583(2)02:02 AM:proto 0>

io_x

5/11/2011 6:31:00 AM

0


"luser- -droog" <mijoryx@yahoo.com> ha scritto nel messaggio
news:70cf2865-5c4a-47a5-a8e8-ac369c2b91b3@k22g2000yqh.googlegroups.com...
> I'm trying to build a new memory allocation scheme for
> my postscript interpreter to satisfy these requirements:
> % pointer + offset + size + short tag <= 32bits
> % 'garbage-collection'-ready (structure the heap for easy iteration)
> % all memory is in one region for easy restore from disk
>
> So I've written a prototype where the "pointer" is an index
> into an extendable address table stored in the heap itself.
> And it seems to work! But I don't trust it, you know?
>
> I'd appreciate any comments the experts here could offer.
>
> One apology. I'm trying to use mmap if available or malloc
> as a fallback, but ifdefs, it seems, can't be made pretty.
> Or, at least I have yet to discover how, unless it's just to
> "put it in a file you don't need to look at". :)

> 569(1)01:27 AM:proto 0> make v
> cc -g -Wall v.c -o v
> 570(1)01:27 AM:proto 0> v
> put seven, got a 7
> 571(1)01:27 AM:proto 0> cat v.c
> #define MMAP
> #define _GNU_SOURCE
>
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <unistd.h>
>
> #ifdef MMAP
> #include <sys/mman.h>
> #endif /* otherwise, use malloc/realloc/free */
>
> void error(char *msg) {
> fprintf(stderr, "%s\n", msg);
> exit(EXIT_FAILURE);
> }
>
> unsigned pgsz /*= getpagesize()*/;
>
> typedef struct {
> unsigned char *base;
> unsigned used;
> unsigned max;
> } mfile;
>
> /* initialize the memory file */
> void initmem(mfile *mem) {
> #ifdef MMAP
> mem->base = mmap(NULL, pgsz, PROT_READ|PROT_WRITE, MAP_SHARED
> |MAP_ANONYMOUS,-1,0 );
> if (mem->base == MAP_FAILED)
> #else
> mem->base = malloc(pgsz);
> if (mem->base == NULL)
> #endif
> error("unable to initialize memory file");
> mem->used = 0;
> mem->max = pgsz;
> }
>
> /* destroy memory file */
> void exitmem(mfile *mem) {
> #ifdef MMAP
> munmap(mem->base, mem->max);
> #else
> free(mem->base);
> #endif
> mem->base = NULL;
> mem->used = 0;
> mem->max = 0;
> }
>
> /* grow memory by sz */
> void growmem(mfile *mem, unsigned sz) {
> unsigned char *tmp;
> if (sz < pgsz) sz = pgsz;
> else sz = (sz/pgsz + 1) * pgsz;

what about if this mult above overflow?

> sz += mem->max;

what about if this sz += overflow?
i not understand well the remain (too much complex
for my little think)
but i think, it is better to see if sz overflow
and in input to write "if((int) sz <0) return -1;"
so that each function can fail.
never exist one function can not fail




luserXtrog

5/11/2011 6:47:00 AM

0

On May 11, 1:31 am, "io_x" <a...@b.c.invalid> wrote:
> "luser- -droog" <mijo...@yahoo.com> ha scritto nel messaggionews:70cf2865-5c4a-47a5-a8e8-ac369c2b91b3@k22g2000yqh.googlegroups.com...
>
>
>
> > I'm trying to build a new memory allocation scheme for
> > my postscript interpreter to satisfy these requirements:
> > % pointer + offset + size + short tag <= 32bits
> > % 'garbage-collection'-ready (structure the heap for easy iteration)
> > % all memory is in one region for easy restore from disk
>
> > So I've written a prototype where the "pointer" is an index
> > into an extendable address table stored in the heap itself.
> > And it seems to work! But I don't trust it, you know?
>
> > I'd appreciate any comments the experts here could offer.
>
> > One apology. I'm trying to use mmap if available or malloc
> > as a fallback, but ifdefs, it seems, can't be made pretty.
> > Or, at least I have yet to discover how, unless it's just to
> > "put it in a file you don't need to look at". :)
> > 569(1)01:27 AM:proto 0> make v
> > cc -g -Wall    v.c   -o v
> > 570(1)01:27 AM:proto 0> v
> > put seven, got a 7
> > 571(1)01:27 AM:proto 0> cat v.c
> > #define MMAP
> > #define _GNU_SOURCE
>
> > #include <stdlib.h>
> > #include <stdio.h>
> > #include <string.h>
> > #include <unistd.h>
>
> > #ifdef MMAP
> > #include <sys/mman.h>
> > #endif /* otherwise, use malloc/realloc/free */
>
> > void error(char *msg) {
> >    fprintf(stderr, "%s\n", msg);
> >    exit(EXIT_FAILURE);
> > }
>
> > unsigned pgsz /*= getpagesize()*/;
>
> > typedef struct {
> >    unsigned char *base;
> >    unsigned used;
> >    unsigned max;
> > } mfile;
>
> > /* initialize the memory file */
> > void initmem(mfile *mem) {
> > #ifdef MMAP
> >    mem->base = mmap(NULL, pgsz, PROT_READ|PROT_WRITE, MAP_SHARED
> >            |MAP_ANONYMOUS,-1,0 );
> >    if (mem->base == MAP_FAILED)
> > #else
> >    mem->base = malloc(pgsz);
> >    if (mem->base == NULL)
> > #endif
> >        error("unable to initialize memory file");
> >    mem->used = 0;
> >    mem->max = pgsz;
> > }
>
> > /* destroy memory file */
> > void exitmem(mfile *mem) {
> > #ifdef MMAP
> >    munmap(mem->base, mem->max);
> > #else
> >    free(mem->base);
> > #endif
> >    mem->base = NULL;
> >    mem->used = 0;
> >    mem->max = 0;
> > }
>
> > /* grow memory by sz */
> > void growmem(mfile *mem, unsigned sz) {
> >    unsigned char *tmp;
> >    if (sz < pgsz) sz = pgsz;
> >    else sz = (sz/pgsz + 1) * pgsz;
>
> what about if this mult above overflow?

That shouldn't be a problem for my application as sizes
will be limited to 16bit quantities.

> >    sz += mem->max;
>
> what about if this sz += overflow?
> i not understand well the remain (too much complex
> for my little think)
> but i think, it is better to see if sz overflow
> and in input to write "if((int) sz <0)  return  -1;"
> so that each function can fail.
> never exist one function can not fail

Yeah, you're right. There should be a lot more checking
throughout.

luserXtrog

5/12/2011 6:06:00 AM

0

On May 11, 1:31 am, "io_x" <a...@b.c.invalid> wrote:
> "luser- -droog" <mijo...@yahoo.com> ha scritto nel messaggionews:70cf2865-5c4a-47a5-a8e8-ac369c2b91b3@k22g2000yqh.googlegroups.com...
>
>
>
> > I'm trying to build a new memory allocation scheme for
> > my postscript interpreter to satisfy these requirements:
> > % pointer + offset + size + short tag <= 32bits
> > % 'garbage-collection'-ready (structure the heap for easy iteration)
> > % all memory is in one region for easy restore from disk
>
> > So I've written a prototype where the "pointer" is an index
> > into an extendable address table stored in the heap itself.
> > And it seems to work! But I don't trust it, you know?
>
> > I'd appreciate any comments the experts here could offer.
>
[...]
> > /* grow memory by sz */
> > void growmem(mfile *mem, unsigned sz) {
> >    unsigned char *tmp;
> >    if (sz < pgsz) sz = pgsz;
> >    else sz = (sz/pgsz + 1) * pgsz;
>
> what about if this mult above overflow?
>
> >    sz += mem->max;
>
> what about if this sz += overflow?
> i not understand well the remain (too much complex
> for my little think)
> but i think, it is better to see if sz overflow
> and in input to write "if((int) sz <0)  return  -1;"
> so that each function can fail.
> never exist one function can not fail

unsigned sz;
(int) sz < 0

Does this just check the high bit (assuming 2's complement)?

Seebs

5/12/2011 7:36:00 AM

0

On 2011-05-12, luser- -droog <mijoryx@yahoo.com> wrote:
> unsigned sz;
> (int) sz < 0
>
> Does this just check the high bit (assuming 2's complement)?

Not necessarily.

If you're comfortable assuming 2s complement, I bet you can do better with:
sz > INT_MAX

-s
--
Copyright 2011, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seeb... <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/...(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

pete

5/12/2011 11:51:00 AM

0

Seebs wrote:
>
> On 2011-05-12, luser- -droog <mijoryx@yahoo.com> wrote:
> > unsigned sz;
> > (int) sz < 0
> >
> > Does this just check the high bit (assuming 2's complement)?
>
> Not necessarily.
>
> If you're comfortable assuming 2s complement,
> I bet you can do better with:
> sz > INT_MAX

I don't see anything unusual
about an unsigned int object
holding a value greater than INT_MAX.

--
pete

pete

5/12/2011 12:02:00 PM

0

luser- -droog wrote:
>
> On May 11, 1:31 am, "io_x" <a...@b.c.invalid> wrote:
> > "luser- -droog" <mijo...@yahoo.com> ha scritto nel messaggionews:70cf2865-5c4a-47a5-a8e8-ac369c2b91b3@k22g2000yqh.googlegroups.com...
> >
> >
> >
> > > I'm trying to build a new memory allocation scheme for
> > > my postscript interpreter to satisfy these requirements:
> > > % pointer + offset + size + short tag <= 32bits
> > > % 'garbage-collection'-ready (structure the heap for easy iteration)
> > > % all memory is in one region for easy restore from disk
> >
> > > So I've written a prototype where the "pointer" is an index
> > > into an extendable address table stored in the heap itself.
> > > And it seems to work! But I don't trust it, you know?
> >
> > > I'd appreciate any comments the experts here could offer.
> >
> [...]
> > > /* grow memory by sz */
> > > void growmem(mfile *mem, unsigned sz) {
> > > unsigned char *tmp;
> > > if (sz < pgsz) sz = pgsz;
> > > else sz = (sz/pgsz + 1) * pgsz;
> >
> > what about if this mult above overflow?
> >
> > > sz += mem->max;
> >
> > what about if this sz += overflow?
> > i not understand well the remain (too much complex
> > for my little think)
> > but i think, it is better to see if sz overflow
> > and in input to write "if((int) sz <0) return -1;"
> > so that each function can fail.
> > never exist one function can not fail
>
> unsigned sz;
> (int) sz < 0
>
> Does this just check the high bit (assuming 2's complement)?

I don't know,
but I don't see the relevance of ((int) sz < 0).

If you want to check for wrap around after (sz += mem->max), then

if (sz - mem->max > sz) ThenItWrapped;

--
pete

Seebs

5/12/2011 3:58:00 PM

0

On 2011-05-12, pete <pfiland@mindspring.com> wrote:
>> unsigned sz;
>> (int) sz < 0

>> Does this just check the high bit (assuming 2's complement)?

> I don't know,
> but I don't see the relevance of ((int) sz < 0).

The relevance was in that question there.

On a typical 2s complement system, it is quite likely that if you convert
a value greater than INT_MAX but no larger than UINT_MAX to a signed integer
type, you will end up with a negative value. Thus,
sz > INT_MAX
and
(int) sz < 0
are both fancy ways of saying something much like:

(sz & ((UNIT_MAX) & ~(UINT_MAX >> 1))) != 0

(unless my lack of morning coffee made me get that wrong...)

-s
--
Copyright 2011, all wrongs reversed. Peter Seebach / usenet-nospam@seebs.net
http://www.seeb... <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/...(Scientology) <-- get educated!
I am not speaking for my employer, although they do rent some of my opinions.

luserXtrog

5/12/2011 4:33:00 PM

0

On May 12, 7:01 am, pete <pfil...@mindspring.com> wrote:
> luser- -droog wrote:
>
> > On May 11, 1:31 am, "io_x" <a...@b.c.invalid> wrote:
> > > "luser- -droog" <mijo...@yahoo.com> ha scritto nel messaggionews:70cf2865-5c4a-47a5-a8e8-ac369c2b91b3@k22g2000yqh.googlegroups.com...
>
> > > > I'm trying to build a new memory allocation scheme for
> > > > my postscript interpreter to satisfy these requirements:
> > > > % pointer + offset + size + short tag <= 32bits
> > > > % 'garbage-collection'-ready (structure the heap for easy iteration)
> > > > % all memory is in one region for easy restore from disk
>
> > > > So I've written a prototype where the "pointer" is an index
> > > > into an extendable address table stored in the heap itself.
> > > > And it seems to work! But I don't trust it, you know?
>
> > > > I'd appreciate any comments the experts here could offer.
>
> > [...]
> > > > /* grow memory by sz */
> > > > void growmem(mfile *mem, unsigned sz) {
> > > >    unsigned char *tmp;
> > > >    if (sz < pgsz) sz = pgsz;
> > > >    else sz = (sz/pgsz + 1) * pgsz;
>
> > > what about if this mult above overflow?
>
> > > >    sz += mem->max;
>
> > > what about if this sz += overflow?
> > > i not understand well the remain (too much complex
> > > for my little think)
> > > but i think, it is better to see if sz overflow
> > > and in input to write "if((int) sz <0)  return  -1;"
> > > so that each function can fail.
> > > never exist one function can not fail
>
> > unsigned sz;
> > (int) sz < 0
>
> > Does this just check the high bit (assuming 2's complement)?
>
> I don't know,
> but I don't see the relevance of ((int) sz < 0).
>
> If you want to check for wrap around after (sz += mem->max), then
>
>     if (sz - mem->max > sz) ThenItWrapped;

I think that's closer to what io_x was suggesting.
For my current purposes sz will be no more than 8*USHORTMAX (if there
is such a thing). But mem-max itself could conceivably get pretty big.
(~2 gigs, right? assuming 32-bit words).

If I approach this limit, I think I can squeeze a little more life out
of this if I make mem->max and mem->used 64bits (since they cover the
whole space), but change the adresses to be relative to the table
location (mtabloc, above) instead of mem->base.

I'm eager to start building on top of this module, but I want to get
as close to "right" as is practical.

pete

5/12/2011 10:05:00 PM

0

Seebs wrote:
>
> On 2011-05-12, pete <pfiland@mindspring.com> wrote:
> >> unsigned sz;
> >> (int) sz < 0
>
> >> Does this just check the high bit (assuming 2's complement)?
>
> > I don't know,
> > but I don't see the relevance of ((int) sz < 0).
>
> The relevance was in that question there.
>
> On a typical 2s complement system,
> it is quite likely that if you convert
> a value greater than INT_MAX but no larger than UINT_MAX
> to a signed integer type,
> you will end up with a negative value. Thus,
> sz > INT_MAX
> and
> (int) sz < 0
> are both fancy ways of saying something much like:
>
> (sz & ((UNIT_MAX) & ~(UINT_MAX >> 1))) != 0
>
> (unless my lack of morning coffee made me get that wrong...)

But
why would you care about
whether or not an unsigned object
held a value which was greater than INT_MAX?

--
pete