commit
6667b8fcf9
@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2011 Niels Thykier <niels@thykier.net>
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
import readline
|
||||
import bisect
|
||||
|
||||
class Completer:
|
||||
"""Completer class
|
||||
|
||||
This class provides a readline completer for the britney hint-tester
|
||||
command-line interface.
|
||||
"""
|
||||
|
||||
def __init__(self, britney):
|
||||
"""Constructor
|
||||
|
||||
Creates a completer for a given britney.
|
||||
"""
|
||||
self.matches = []
|
||||
self.cmds = ['easy', 'hint', 'force-hint', 'exit', 'quit']
|
||||
self.britney = britney
|
||||
self.packages = sorted(britney.generate_package_list())
|
||||
|
||||
def completer(self, text, state):
|
||||
"""readline completer (see the readline API)"""
|
||||
|
||||
origline = readline.get_line_buffer()
|
||||
words = origline.split()
|
||||
|
||||
if state < 1:
|
||||
self.matches = []
|
||||
if len(words) < 1 or words[0] == text:
|
||||
# complete a command
|
||||
self.matches = [x for x in self.cmds if x.startswith(text)]
|
||||
else:
|
||||
# complete pkg/[arch/]version
|
||||
prefix = ''
|
||||
if len(text) > 0 and text[0] == '-':
|
||||
text = text[1:]
|
||||
prefix = '-'
|
||||
start = bisect.bisect_left(self.packages, text)
|
||||
while start < len(self.packages):
|
||||
if not self.packages[start].startswith(text):
|
||||
break
|
||||
self.matches.append(prefix + self.packages[start])
|
||||
start += 1
|
||||
|
||||
if len(self.matches) > state:
|
||||
return self.matches[state]
|
||||
return None
|
||||
|
@ -1,389 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "memory.h"
|
||||
#include "templates.h"
|
||||
#include "freelist.h"
|
||||
|
||||
/**** THEORY
|
||||
*
|
||||
|
||||
So, we have blocks with a freelist
|
||||
|
||||
XXX............XXXXXXX..XXXXX.....XXXXXX......
|
||||
|
||||
Within a block, we work with segments. A segment is...
|
||||
|
||||
^..........|
|
||||
|
||||
Every now and then we make sure we've got a decent sized segment.
|
||||
|
||||
We have multiple blocks. They're kept ordered by the size of their
|
||||
current segment.
|
||||
|
||||
**********************************************/
|
||||
|
||||
#define ALIGN 4
|
||||
|
||||
#define FLBT_BITS (sizeof(flb_t)*8)
|
||||
#define MEMBLOCKSIZE (1 << 22)
|
||||
#define ALIGNEDSIZE(s) (((s) + ALIGN - 1) / ALIGN * ALIGN)
|
||||
|
||||
struct memblock {
|
||||
struct memblock *next;
|
||||
|
||||
size_t n_bytes; /* index of free char */
|
||||
size_t size; /* size of block after char */
|
||||
|
||||
unsigned n_used_chunks; /* number of unfreed blocks */
|
||||
size_t n_used_bytes; /* number of bytes actually used */
|
||||
size_t n_productive_bytes; /* number of bytes used usefully */
|
||||
|
||||
flb_t free[MEMBLOCKSIZE/ALIGN/FLBT_BITS + 1];
|
||||
unsigned char mem[MEMBLOCKSIZE];
|
||||
};
|
||||
typedef struct memblock memblock;
|
||||
|
||||
static memblock *base = NULL;
|
||||
|
||||
#ifdef MDEBUG1
|
||||
static int valid_memblock_mdebug1(struct memblock *mb) {
|
||||
size_t cnt, i;
|
||||
static int rarity = 0;
|
||||
|
||||
assert(mb->n_bytes + mb->size <= sizeof(mb->mem));
|
||||
|
||||
if (mb->n_used_chunks == 0) assert(mb->n_bytes == 0);
|
||||
assert(((unsigned long)mb->mem + mb->n_bytes) % ALIGN == 0);
|
||||
|
||||
assert(mb->n_productive_bytes <= mb->n_used_bytes);
|
||||
assert(mb->n_used_bytes + mb->size <= sizeof(mb->mem));
|
||||
|
||||
#define TWO(k) (1ul << (k))
|
||||
#define CYCL(k) (~0ul / (1 + TWO(TWO(k))))
|
||||
|
||||
rarity++; rarity %= 25000;
|
||||
if (rarity != 0) {
|
||||
cnt = mb->n_used_bytes;
|
||||
} else {
|
||||
cnt = 0;
|
||||
for (i = 0; i < sizeof(mb->mem)/ALIGN/FLBT_BITS+1; i++) {
|
||||
unsigned long x = mb->free[i];
|
||||
size_t s;
|
||||
x = (x & CYCL(0)) + ((x >> TWO(0)) & CYCL(0));
|
||||
x = (x & CYCL(1)) + ((x >> TWO(1)) & CYCL(1));
|
||||
for (s = 2; (2u << s) <= FLBT_BITS; s++) {
|
||||
x += x >> TWO(s);
|
||||
x &= CYCL(s);
|
||||
}
|
||||
cnt += x * ALIGN;
|
||||
}
|
||||
}
|
||||
#undef TWO
|
||||
#undef CYCL
|
||||
|
||||
assert(cnt == mb->n_used_bytes);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MDEBUG3
|
||||
static int valid_memblock_mdebug3(struct memblock *mb) {
|
||||
size_t offset, step, used;
|
||||
unsigned chunk = 0;
|
||||
|
||||
offset = 0;
|
||||
used = 0;
|
||||
if ((unsigned long)mb->mem % ALIGN != 0)
|
||||
offset = ALIGN - ((unsigned long)mb->mem % ALIGN);
|
||||
|
||||
while(offset < mb->n_bytes) {
|
||||
step = *(size_t*)(mb->mem + offset);
|
||||
assert(step % ALIGN == 0 || step % ALIGN == 1);
|
||||
if (step % ALIGN == 1) step--; /* freed */
|
||||
else used += step;
|
||||
assert(step > 0);
|
||||
offset += step;
|
||||
chunk++;
|
||||
}
|
||||
|
||||
assert(used == mb->n_used_bytes);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline static int valid_memblock(struct memblock *mb) {
|
||||
(void)mb;
|
||||
|
||||
MDEBUG1_ONLY( if (!valid_memblock_mdebug1(mb)) return 0; )
|
||||
MDEBUG3_ONLY( if (!valid_memblock_mdebug3(mb)) return 0; )
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void print_memblock_summary(void) {
|
||||
struct memblock *mb;
|
||||
unsigned long tused = 0, talloc = 0, tprod = 0, tavail = 0, nb = 0;
|
||||
|
||||
for (mb = base; mb != NULL; mb = mb->next) {
|
||||
assert(valid_memblock(mb));
|
||||
|
||||
MDEBUG3_ONLY(
|
||||
fprintf(stderr, "%p: [%d,%lu/%lu,%p,%p]\n", mb,
|
||||
mb->n_used_chunks, (unsigned long)mb->n_used_bytes,
|
||||
(unsigned long)mb->n_bytes, mb->next, mb->mem);
|
||||
)
|
||||
|
||||
if (mb != base && mb->size * 50 < sizeof(mb->mem) - mb->n_used_bytes) {
|
||||
flb_t k; size_t s;
|
||||
k = mb->n_bytes / ALIGN;
|
||||
s = mb->size / ALIGN;
|
||||
find_long_freebits(mb->free,MEMBLOCKSIZE/ALIGN/FLBT_BITS+1,&k,&s);
|
||||
k *= ALIGN; s *= ALIGN;
|
||||
fprintf(stderr, "%p %lu: Wasted block "
|
||||
"[%d chunks, %lu free bytes, %lu avail bytes, %2.2f%%], suggested [%ld,%ld] -> [%ld,%ld]\n",
|
||||
mb->mem, nb, mb->n_used_chunks,
|
||||
(unsigned long) sizeof(mb->mem) - mb->n_used_bytes,
|
||||
(unsigned long) mb->size,
|
||||
(float) 100.0 * mb->size / (sizeof(mb->mem) - mb->n_used_bytes),
|
||||
(unsigned long) mb->n_bytes, (unsigned long) mb->size,
|
||||
(unsigned long) k, (unsigned long) s);
|
||||
if (s > mb->size * 4 || s * 25 > sizeof(mb->mem) - mb->n_used_bytes) {
|
||||
mb->n_bytes = k;
|
||||
mb->size = s;
|
||||
}
|
||||
}
|
||||
nb++;
|
||||
tprod += mb->n_productive_bytes;
|
||||
tused += mb->n_used_bytes;
|
||||
tavail += mb->size;
|
||||
talloc += sizeof(memblock);
|
||||
}
|
||||
fprintf(stderr, "TOTAL: %lu %lu KiB alloc"
|
||||
"(%lu/%lu available, %2.2f%%) (%lu KiB used, %2.2f%%) (%lu KiB useful, %2.2f%%)\n",
|
||||
nb, talloc / 1024,
|
||||
(unsigned long) (base ? base->size / 1024 : 0),
|
||||
tavail / 1024, (talloc > 0 ? 100.0*tavail/talloc : 0.0),
|
||||
tused / 1024, (talloc > 0 ? 100.0*tused/talloc : 0.0),
|
||||
tprod / 1024, (talloc > 0 ? 100.0*tprod/talloc : 0.0));
|
||||
}
|
||||
|
||||
MDEBUG1_ONLY(static int first_malloc = 0;)
|
||||
|
||||
#ifdef MDEBUG3
|
||||
static void print_memblock_stats(void) {
|
||||
struct memblock *mb;
|
||||
size_t offset;
|
||||
|
||||
for (mb = base; mb != NULL; mb = mb->next) {
|
||||
assert(valid_memblock(mb));
|
||||
|
||||
printf("%p: [%d,%lu/%lu/%lu,%p,%p:\n", mb,
|
||||
mb->n_used_chunks, (unsigned long)mb->n_productive_bytes,
|
||||
(unsigned long)mb->n_used_bytes, (unsigned long)mb->n_bytes,
|
||||
mb->next, mb->mem);
|
||||
|
||||
offset = 0;
|
||||
if ((unsigned long)mb->mem % ALIGN != 0)
|
||||
offset = ALIGN - ((unsigned long)mb->mem % ALIGN);
|
||||
while(offset < mb->n_bytes) {
|
||||
size_t step = *(size_t*)(mb->mem + offset);
|
||||
if (step % ALIGN == 1) {
|
||||
step--;
|
||||
printf(" (%d)", (int) step);
|
||||
} else {
|
||||
printf(" %d", (int) step);
|
||||
}
|
||||
offset += step;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
void *block_malloc(size_t size) {
|
||||
memblock *where = base;
|
||||
void *result;
|
||||
size_t realsize = size;
|
||||
|
||||
MDEBUG3_ONLY( if (first_malloc) print_memblock_stats(); )
|
||||
MDEBUG3_ONLY( first_malloc = 0; )
|
||||
|
||||
(void)assert(ALIGN >= sizeof(size_t)); /* ALIGN is set too small! */
|
||||
|
||||
MDEBUG2_ONLY(size += ALIGN;)
|
||||
/* for the size, so the caller can be checked */
|
||||
|
||||
size = ALIGNEDSIZE(size);
|
||||
|
||||
assert(size > 0 && size < sizeof(where->mem));
|
||||
assert(!where || ((unsigned long)where->mem + where->n_bytes) % ALIGN == 0);
|
||||
|
||||
if ( !where || where->size < size ) {
|
||||
MDEBUG1_ONLY(print_memblock_summary();)
|
||||
where = malloc(sizeof(memblock));
|
||||
if (where == NULL) {
|
||||
int i;
|
||||
fprintf(stderr, "block_malloc: failed trying to allocate memblock\n");
|
||||
i = 0; where = base; while(where) {i++; where = where->next;}
|
||||
fprintf(stderr, "(had allocated %d blocks, each %lu bytes)\n", i,
|
||||
(unsigned long)sizeof(memblock));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
where->n_used_chunks = 0;
|
||||
memset(where->free, 0, sizeof(where->free));
|
||||
where->n_bytes = 0;
|
||||
where->size = sizeof(where->mem);
|
||||
|
||||
assert( (unsigned long)where->mem % ALIGN == 0);
|
||||
/* XXX: should be able to cope with this :( */
|
||||
|
||||
where->n_used_bytes = where->n_bytes;
|
||||
where->n_productive_bytes = 0;
|
||||
(where)->next = base;
|
||||
base = where;
|
||||
|
||||
MDEBUG2_ONLY(memset(where->mem, 0xDD, sizeof(where->mem));)
|
||||
}
|
||||
|
||||
result = where->mem + where->n_bytes;
|
||||
|
||||
assert( (unsigned long)where->mem % ALIGN == where->n_bytes % ALIGN );
|
||||
assert( size % ALIGN == 0 );
|
||||
mark_bits(where->free,
|
||||
(unsigned long)((unsigned char*)result - where->mem) / ALIGN,
|
||||
size / ALIGN, 1);
|
||||
|
||||
where->n_bytes += size;
|
||||
where->size -= size;
|
||||
where->n_used_bytes += size;
|
||||
where->n_productive_bytes += realsize;
|
||||
where->n_used_chunks++;
|
||||
|
||||
MDEBUG2_ONLY( memset(result, 0xEE, size); )
|
||||
|
||||
MDEBUG2_ONLY( *(size_t *)result = realsize; )
|
||||
MDEBUG2_ONLY( result += ALIGN; )
|
||||
|
||||
assert(((unsigned long)where->mem + where->n_bytes) % ALIGN == 0);
|
||||
|
||||
assert(valid_memblock(where));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static memblock **find_memblock(unsigned char *mem) {
|
||||
memblock **where;
|
||||
|
||||
for (where = &base; *where != NULL; where = &(*where)->next) {
|
||||
memblock *mb = *where;
|
||||
assert(valid_memblock(mb));
|
||||
if (&mb->mem[0] <= mem && (size_t)(mem - mb->mem) < sizeof(mb->mem)) {
|
||||
return where;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void free_in_memblock(memblock *mb, unsigned char *mem, size_t size) {
|
||||
MDEBUG2_ONLY(size_t *stmem = ((size_t*)mem) - 1;)
|
||||
|
||||
assert(mb && mem && size > 0);
|
||||
|
||||
mb->n_used_chunks--;
|
||||
|
||||
mb->n_used_bytes -= ALIGNEDSIZE(size);
|
||||
mark_bits(mb->free, (unsigned long)(mem - mb->mem) / ALIGN,
|
||||
ALIGNEDSIZE(size) / ALIGN, 0);
|
||||
|
||||
#ifdef MDEBUG2
|
||||
mark_bits(mb->free, (unsigned long)(mem - mb->mem) / ALIGN - 1, 1, 0);
|
||||
mb->n_used_bytes -= ALIGN;
|
||||
#endif
|
||||
|
||||
if ((size_t)(mem - mb->mem) + ALIGNEDSIZE(size) == mb->n_bytes) {
|
||||
size_t k = count_free_bits_back(mb->free, mb->n_bytes / ALIGN) * ALIGN;
|
||||
mb->n_bytes -= k;
|
||||
mb->size += k;
|
||||
}
|
||||
if ((size_t)(mem - mb->mem) == mb->n_bytes + mb->size) {
|
||||
mb->size += count_free_bits_after(mb->free,
|
||||
(mb->n_bytes + mb->size) / ALIGN,
|
||||
sizeof(mb->mem) / ALIGN) * ALIGN;
|
||||
}
|
||||
|
||||
mb->n_productive_bytes -= size;
|
||||
|
||||
if (mb->n_used_chunks == 0) {
|
||||
assert(mb->n_productive_bytes == 0);
|
||||
assert(mb->n_used_bytes == 0);
|
||||
|
||||
mb->n_bytes = 0;
|
||||
mb->size = sizeof(mb->mem);
|
||||
mb->n_used_bytes = 0;
|
||||
mb->n_productive_bytes = 0;
|
||||
}
|
||||
|
||||
MDEBUG2_ONLY( memset(mem, 0xAA, size); )
|
||||
|
||||
#ifdef MDEBUG2
|
||||
assert((unsigned char*)stmem >= mb->mem && (unsigned char*)stmem < mb->mem + sizeof(mb->mem));
|
||||
assert(*stmem % ALIGN == 0);
|
||||
assert(*stmem == size);
|
||||
#endif
|
||||
|
||||
assert(valid_memblock(mb));
|
||||
}
|
||||
|
||||
void block_free(void *vmem, size_t size) {
|
||||
memblock **where;
|
||||
MDEBUG1_ONLY(static int free_count = 0;)
|
||||
|
||||
if (vmem == NULL) return;
|
||||
|
||||
MDEBUG1_ONLY(first_malloc = 1;)
|
||||
|
||||
where = find_memblock(vmem);
|
||||
assert(where);
|
||||
free_in_memblock(*where, vmem, size);
|
||||
if ((*where)->n_used_chunks == 0 && *where != base) {
|
||||
memblock *mb = *where;
|
||||
MDEBUG1_ONLY( print_memblock_summary(); )
|
||||
*where = (*where)->next;
|
||||
free(mb);
|
||||
MDEBUG1_ONLY( fprintf(stderr, "Freed memblock\n"); )
|
||||
}
|
||||
MDEBUG1_ONLY( free_count++; free_count %= 10000; )
|
||||
MDEBUG1_ONLY( if (!free_count) print_memblock_summary(); )
|
||||
}
|
||||
|
||||
void *block_realloc(void *vmem, size_t oldsize, size_t newsize) {
|
||||
void *vnewmem;
|
||||
|
||||
if (vmem == NULL && newsize == 0) abort();
|
||||
if (vmem == NULL) return block_malloc(newsize);
|
||||
if (newsize == 0) {
|
||||
block_free(vmem, oldsize);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vnewmem = block_malloc(newsize);
|
||||
if (vnewmem) {
|
||||
memcpy(vnewmem, vmem, (oldsize < newsize ? oldsize : newsize));
|
||||
block_free(vmem, oldsize);
|
||||
}
|
||||
return vnewmem;
|
||||
}
|
||||
|
||||
char *block_strdup(char *from) {
|
||||
char *result;
|
||||
if (!from) return NULL;
|
||||
result = block_malloc(strlen(from) + 1);
|
||||
strcpy(result, from);
|
||||
return result;
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
#define M 16
|
||||
|
||||
void *block_malloc(size_t size) { return malloc(size); }
|
||||
void block_free(void *vmem) { free(vmem); }
|
||||
void *block_realloc(void *vmem, size_t newsize) { return realloc(vmem, newsize); }
|
||||
char *block_strdup(char *from) {
|
||||
char *d;
|
||||
if (!from) return 0;
|
||||
d = block_malloc(strlen(from+1));
|
||||
if (d) strcpy(d, from);
|
||||
return d;
|
||||
}
|
||||
|
||||
void print_memblock_summary(void) { }
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue