[Pkg-gnupg-commit] [gnupg2] 20/132: gpgscm: Remove arbitrary limit on number of cell segments.
Daniel Kahn Gillmor
dkg at fifthhorseman.net
Wed May 17 03:07:36 UTC 2017
This is an automated email from the git hooks/post-receive script.
dkg pushed a commit to branch experimental
in repository gnupg2.
commit 56638c28adc1bbe9fc052b92549a50935c0fe99c
Author: Justus Winter <justus at g10code.com>
Date: Wed Mar 22 16:22:57 2017 +0100
gpgscm: Remove arbitrary limit on number of cell segments.
* tests/gpgscm/scheme-private.h (struct scheme): Remove fixed-size
arrays for cell segments, replace them with a pointer to the new
'struct cell_segment' instead.
* tests/gpgscm/scheme.c (struct cell_segment): New definition.
(_alloc_cellseg): Allocate the header within the segment, return a
pointer to the header.
(_dealloc_cellseg): New function.
(alloc_cellseg): Insert the segments into a list.
(_get_cell): Allocate a new segment if less than a quarter of
CELL_SIGSIZE is recovered during garbage collection.
(initialize_small_integers): Adapt callsite.
(gc): Walk the list of segments.
(scheme_init_custom_alloc): Remove initialization of removed field.
(scheme_deinit): Adapt deallocation.
--
Previously the number of cells that could be allocated was a
compile-time limit. Remove this limit.
Signed-off-by: Justus Winter <justus at g10code.com>
---
tests/gpgscm/scheme-private.h | 10 +---
tests/gpgscm/scheme.c | 108 ++++++++++++++++++++++++++++--------------
2 files changed, 74 insertions(+), 44 deletions(-)
diff --git a/tests/gpgscm/scheme-private.h b/tests/gpgscm/scheme-private.h
index fe50135..093442f 100644
--- a/tests/gpgscm/scheme-private.h
+++ b/tests/gpgscm/scheme-private.h
@@ -108,12 +108,7 @@ int tracing;
#ifndef CELL_SEGSIZE
#define CELL_SEGSIZE 5000 /* # of cells in one segment */
#endif
-#ifndef CELL_NSEGMENT
-#define CELL_NSEGMENT 10 /* # of segments for cells */
-#endif
-void *alloc_seg[CELL_NSEGMENT];
-pointer cell_seg[CELL_NSEGMENT];
-int last_cell_seg;
+struct cell_segment *cell_segments;
/* We use 4 registers. */
pointer args; /* register for arguments of function */
@@ -159,8 +154,7 @@ pointer COMPILE_HOOK; /* *compile-hook* */
#if USE_SMALL_INTEGERS
/* A fixed allocation of small integers. */
-void *integer_alloc;
-pointer integer_cells;
+struct cell_segment *integer_segment;
#endif
pointer free_cell; /* pointer to top of free cells */
diff --git a/tests/gpgscm/scheme.c b/tests/gpgscm/scheme.c
index aa0cf69..08b53a1 100644
--- a/tests/gpgscm/scheme.c
+++ b/tests/gpgscm/scheme.c
@@ -725,9 +725,26 @@ get_tag(scheme *sc, pointer v)
+/* Low-level allocator.
+ *
+ * Memory is allocated in segments. Every segment holds a fixed
+ * number of cells. Segments are linked into a list, sorted in
+ * reverse address order (i.e. those with a higher address first).
+ * This is used in the garbage collector to build the freelist in
+ * address order.
+ */
+
+struct cell_segment
+{
+ struct cell_segment *next;
+ void *alloc;
+ pointer cells;
+ size_t cells_len;
+};
+
/* Allocate a new cell segment but do not make it available yet. */
static int
-_alloc_cellseg(scheme *sc, size_t len, void **alloc, pointer *cells)
+_alloc_cellseg(scheme *sc, size_t len, struct cell_segment **segment)
{
int adj = ADJ;
void *cp;
@@ -735,46 +752,64 @@ _alloc_cellseg(scheme *sc, size_t len, void **alloc, pointer *cells)
if (adj < sizeof(struct cell))
adj = sizeof(struct cell);
- cp = sc->malloc(len * sizeof(struct cell) + adj);
+ /* The segment header is conveniently allocated with the cells. */
+ cp = sc->malloc(sizeof **segment + len * sizeof(struct cell) + adj);
if (cp == NULL)
return 1;
- *alloc = cp;
+ *segment = cp;
+ (*segment)->next = NULL;
+ (*segment)->alloc = cp;
+ cp = (void *) ((uintptr_t) cp + sizeof **segment);
/* adjust in TYPE_BITS-bit boundary */
if (((uintptr_t) cp) % adj != 0)
cp = (void *) (adj * ((uintptr_t) cp / adj + 1));
- *cells = cp;
+ (*segment)->cells = cp;
+ (*segment)->cells_len = len;
return 0;
}
+/* Deallocate a cell segment. Returns the next cell segment.
+ * Convenient for deallocation in a loop. */
+static struct cell_segment *
+_dealloc_cellseg(scheme *sc, struct cell_segment *segment)
+{
+
+ struct cell_segment *next;
+
+ if (segment == NULL)
+ return NULL;
+
+ next = segment->next;
+ sc->free(segment->alloc);
+ return next;
+}
+
/* allocate new cell segment */
static int alloc_cellseg(scheme *sc, int n) {
- pointer newp;
pointer last;
pointer p;
- long i;
int k;
for (k = 0; k < n; k++) {
- if (sc->last_cell_seg >= CELL_NSEGMENT - 1)
- return k;
- i = ++sc->last_cell_seg;
- if (_alloc_cellseg(sc, CELL_SEGSIZE, &sc->alloc_seg[i], &newp)) {
- sc->last_cell_seg--;
+ struct cell_segment *new, **s;
+ if (_alloc_cellseg(sc, CELL_SEGSIZE, &new)) {
return k;
}
- /* insert new segment in address order */
- sc->cell_seg[i] = newp;
- while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) {
- p = sc->cell_seg[i];
- sc->cell_seg[i] = sc->cell_seg[i - 1];
- sc->cell_seg[--i] = p;
- }
- sc->fcells += CELL_SEGSIZE;
- last = newp + CELL_SEGSIZE - 1;
- for (p = newp; p <= last; p++) {
+ /* insert new segment in reverse address order */
+ for (s = &sc->cell_segments;
+ *s && (uintptr_t) (*s)->alloc > (uintptr_t) new->alloc;
+ s = &(*s)->next) {
+ /* walk */
+ }
+ new->next = *s;
+ *s = new;
+
+ sc->fcells += new->cells_len;
+ last = new->cells + new->cells_len - 1;
+ for (p = new->cells; p <= last; p++) {
typeflag(p) = 0;
cdr(p) = p + 1;
car(p) = sc->NIL;
@@ -782,13 +817,13 @@ static int alloc_cellseg(scheme *sc, int n) {
/* insert new cells in address order on free list */
if (sc->free_cell == sc->NIL || p < sc->free_cell) {
cdr(last) = sc->free_cell;
- sc->free_cell = newp;
+ sc->free_cell = new->cells;
} else {
p = sc->free_cell;
- while (cdr(p) != sc->NIL && newp > cdr(p))
+ while (cdr(p) != sc->NIL && (uintptr_t) new->cells > (uintptr_t) cdr(p))
p = cdr(p);
cdr(last) = cdr(p);
- cdr(p) = newp;
+ cdr(p) = new->cells;
}
}
return n;
@@ -922,7 +957,7 @@ static pointer _get_cell(scheme *sc, pointer a, pointer b) {
assert (gc_enabled (sc));
if (sc->free_cell == sc->NIL) {
- const int min_to_be_recovered = sc->last_cell_seg*8;
+ const int min_to_be_recovered = CELL_SEGSIZE / 4;
gc(sc,a, b);
if (sc->fcells < min_to_be_recovered
|| sc->free_cell == sc->NIL) {
@@ -1283,12 +1318,11 @@ static int
initialize_small_integers(scheme *sc)
{
int i;
- if (_alloc_cellseg(sc, MAX_SMALL_INTEGER, &sc->integer_alloc,
- &sc->integer_cells))
+ if (_alloc_cellseg(sc, MAX_SMALL_INTEGER, &sc->integer_segment))
return 1;
for (i = 0; i < MAX_SMALL_INTEGER; i++) {
- pointer x = &sc->integer_cells[i];
+ pointer x = &sc->integer_segment->cells[i];
typeflag(x) = T_NUMBER | T_ATOM | MARK;
ivalue_unchecked(x) = i;
set_num_integer(x);
@@ -1302,7 +1336,7 @@ mk_small_integer(scheme *sc, long n)
{
#define mk_small_integer_allocates 0
assert(0 <= n && n < MAX_SMALL_INTEGER);
- return &sc->integer_cells[n];
+ return &sc->integer_segment->cells[n];
}
#else
@@ -1666,6 +1700,7 @@ E6: /* up. Undo the link switching from steps E4 and E5. */
/* garbage collection. parameter a, b is marked. */
static void gc(scheme *sc, pointer a, pointer b) {
pointer p;
+ struct cell_segment *s;
int i;
assert (gc_enabled (sc));
@@ -1712,9 +1747,9 @@ static void gc(scheme *sc, pointer a, pointer b) {
(which are also kept sorted by address) downwards to build the
free-list in sorted order.
*/
- for (i = sc->last_cell_seg; i >= 0; i--) {
- p = sc->cell_seg[i] + CELL_SEGSIZE;
- while (--p >= sc->cell_seg[i]) {
+ for (s = sc->cell_segments; s; s = s->next) {
+ p = s->cells + s->cells_len;
+ while (--p >= s->cells) {
if ((typeflag(p) & 1) == 0)
/* All types have the LSB set. This is not a typeflag. */
continue;
@@ -5592,7 +5627,6 @@ int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
sc->gensym_cnt=0;
sc->malloc=malloc;
sc->free=free;
- sc->last_cell_seg = -1;
sc->sink = &sc->_sink;
sc->NIL = &sc->_NIL;
sc->T = &sc->_HASHT;
@@ -5626,6 +5660,7 @@ int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
}
sc->strbuff_size = STRBUFFSIZE;
+ sc->cell_segments = NULL;
if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
sc->no_memory=1;
return 0;
@@ -5726,6 +5761,7 @@ void scheme_set_external_data(scheme *sc, void *p) {
}
void scheme_deinit(scheme *sc) {
+ struct cell_segment *s;
int i;
sc->oblist=sc->NIL;
@@ -5758,11 +5794,11 @@ void scheme_deinit(scheme *sc) {
gc(sc,sc->NIL,sc->NIL);
#if USE_SMALL_INTEGERS
- sc->free(sc->integer_alloc);
+ _dealloc_cellseg(sc, sc->integer_segment);
#endif
- for(i=0; i<=sc->last_cell_seg; i++) {
- sc->free(sc->alloc_seg[i]);
+ for (s = sc->cell_segments; s; s = _dealloc_cellseg(sc, s)) {
+ /* nop */
}
sc->free(sc->strbuff);
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gnupg2.git
More information about the Pkg-gnupg-commit
mailing list