1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
  
     | 
    
      /*
20130503
Jan Mojzis
Public domain.
*/
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "e.h"
#include "uint64_pack.h"
#include "uint64_unpack.h"
#include "byte.h"
#include "purge.h"
#include "alloc.h"
#define ALLOC_ALIGNMENT 16
#define ALLOC_SPACE 8192
#define ALLOC_LIMIT 4000000000LL
typedef union { unsigned char irrelevant[ALLOC_ALIGNMENT]; double d; } aligned;
static aligned realspace[ALLOC_SPACE / ALLOC_ALIGNMENT];
#define space ((unsigned char *) realspace)
static long long avail = ALLOC_SPACE;
static long long allocated = 0;
static long long limit     = -1;
static long long getlimit(void) {
    struct rlimit r;
    if (limit >= 0) return limit;
#ifdef RLIMIT_DATA
    if (getrlimit(RLIMIT_DATA, &r) == 0) {
        if (r.rlim_cur > r.rlim_max)
            r.rlim_cur = r.rlim_max;
        limit = (long long)r.rlim_cur;
    }
#endif
    if (limit < 0 || limit > ALLOC_LIMIT) limit = ALLOC_LIMIT;
    return limit;
}
#ifdef TEST
void alloc_setlimit(long long l) {
    limit = l;
}
long long alloc_getallocated(void) {
    return allocated;
}
long long alloc_getspace(void) {
    return ALLOC_SPACE;
}
#endif
static void **ptr = 0;
static long long ptrlen = 0;
static long long ptralloc = 0;
static int ptr_add(void *x) {
    void **newptr;
    if (ptrlen + 1 > ptralloc) {
        while (ptrlen + 1 > ptralloc)
            ptralloc = 2 * ptralloc + 1;
        newptr = (void **)malloc(ptralloc * sizeof(void *));
        if (!newptr) return 0;
        if (ptr) {
            byte_copy(newptr, ptrlen * sizeof(void *), ptr);
            free(ptr);
        }
        ptr = newptr;
    }
    if (!x) return 1;
    ptr[ptrlen++] = x;
    return 1;
}
static int ptr_remove(void *x) {
    long long i;
    for (i = 0; i < ptrlen; ++i) {
        if (ptr[i] == x) goto ok;
    }
    return 0;
ok:
    --ptrlen;
    ptr[i] = ptr[ptrlen];
    return 1;
}
void *alloc(long long nn) {
    unsigned char *x;
    crypto_uint64 n;
    if (nn < 0 || nn > ALLOC_LIMIT) goto nomem;
    if (nn == 0) nn = 1;
    n = nn;
    n = ALLOC_ALIGNMENT + n - (n & (ALLOC_ALIGNMENT - 1));
    if (n <= avail) { avail -= n; return (void *)(space + avail); }
    n += ALLOC_ALIGNMENT;
    if (allocated + n > getlimit()) goto nomem;
    x = (unsigned char *)malloc(n);
    if (!x) goto nomem;
    allocated += n;
    byte_zero(x, n);
    uint64_pack(x, n);
    x += ALLOC_ALIGNMENT;
    if (!ptr_add(x)) goto nomem;
    return (void *)x;
nomem:
    errno = ENOMEM;
    return (void *)0;
}
void alloc_free(void *xv) {
    crypto_uint64 n;
    unsigned char *x = xv;
    if (x >= space)
        if (x < space + ALLOC_SPACE)
            return;
    if (!ptr_remove(x)) return;
    x -= ALLOC_ALIGNMENT;
    n = uint64_unpack(x);
    allocated -= n;
    purge(x, n);
    free(x);
}
void alloc_freeall(void) {
    while (ptrlen > 0) {
        alloc_free(ptr[0]);
    }
    if (ptr) { free(ptr); ptr = 0; ptrlen = 0; ptralloc = 0; }
    purge(space, ALLOC_SPACE);
}
 
     |