File: alloc.c

package info (click to toggle)
dq 20230101-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,020 kB
  • sloc: ansic: 8,269; makefile: 363; sh: 176; python: 82
file content (154 lines) | stat: -rw-r--r-- 3,007 bytes parent folder | download | duplicates (3)
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);
}