summaryrefslogtreecommitdiff
path: root/server/zalloc.c
blob: f4e5e239c9771afb3e0be58535ecd1a02c8671e6 (plain)
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/*
 * Memory allocator for Zephyr server.
 */

#include <stdio.h>
#include <zephyr/zephyr.h>
#include "unix.h"
#include "zalloc.h"

#ifndef MPROF
/*
 * What's the maximum number of words to expect to allocate through
 * this mechanism?  (Larger requests will be fed to malloc.)
 */
#define MAX_SIZE 32

static void *free_space;
static unsigned int free_space_size;
static void *buckets[MAX_SIZE];
#ifdef ZALLOC_STATS
enum zalloc_memtype {
    FREE=0, ALLOCATED,
    N_zalloc_memtype
};
static int zalloc_count[MAX_SIZE][(int) N_zalloc_memtype];
#endif

/* 
  union misc_types {
    void *void_p;
    int i;
    long l;
    double d;
  };
*/
/* SZ = sizeof(misc_types) */
#define SZ 32

/*
 * Pick some size here that will help keep down the number of calls to
 * malloc, but doesn't waste too much space.  To avoid waste of space,
 * we leave some overhead before the next power of two.
 */


/* ALLOC_SIZE = ((16384 - 32) / SZ) * SZ      */
#define ALLOC_SIZE 16352

unsigned int round (size)
     unsigned int size;
{
    size += SZ - 1;
    size -= (size % SZ);
    return size;
}

#define ROUND(size)	(size = round (size))
int BUCKET (size)
     unsigned int size;
{
    ROUND (size);
    return size / SZ - 1;
}

static void
zmemset (ptr, size, fill)
     void *ptr;
     int size;
     int fill;
{
#ifdef ZALLOC_DEBUG
    char *cptr = (char *) ptr;
    while (size--)
	cptr[size] = fill;
#endif
}

void *
zalloc (size)
     unsigned int size;
{
    int bucket;
    void *ret;
    void **ptr;

    ROUND (size);
    bucket = BUCKET (size);
    if (bucket < 0 || bucket >= MAX_SIZE)
	return (void *) malloc (size);

    ptr = &buckets[bucket];
#ifdef ZALLOC_DEBUG_PRINT
    fprintf (stderr, "zalloc(%d); looking in bucket %d, found %08X\n",
	     size, bucket, *ptr);
#endif
    if (*ptr) {
	ret = *ptr;
	*ptr = *(void**)ret;
	goto return_it;
    }

    if (free_space_size < size) {
	if (free_space_size > 0) {
	    ptr = &buckets[BUCKET (free_space_size)];
	    *(void**)free_space = *ptr;
	    *ptr = free_space;
#ifdef ZALLOC_DEBUG_PRINT
	    fprintf (stderr, "tossing %08X into bucket %d\n",
		     free_space, bucket);
#endif
#ifdef ZALLOC_STATS
	    zalloc_count[BUCKET (free_space_size)][FREE]++;
#endif
	}

	free_space_size = ALLOC_SIZE;
	free_space = (void *) malloc (free_space_size);
	if (!free_space)
	    abort ();
#ifdef ZALLOC_DEBUG_PRINT
	fprintf (stderr, "grabbing more free store at %08X\n", free_space);
#endif
    }

    ret = free_space;
    free_space = (char *) free_space + size;
    free_space_size -= size;
return_it:
#ifdef ZALLOC_DEBUG_PRINT
    fprintf (stderr, "returning %08X\n", ret);
#endif
    zmemset (ret, size, 0xe5);
#ifdef ZALLOC_STATS
    zalloc_count[bucket][FREE]--, zalloc_count[bucket][ALLOCATED]++;
#endif
    return ret;
}

void zfree (ptr, size)
     void *ptr;
     unsigned int size;
{
    int bucket;
    void **b;

    ROUND (size);
    bucket = BUCKET (size);
    if (bucket < 0 || bucket >= MAX_SIZE) {
	free (ptr);
	return;
    }

    b = &buckets[bucket];
    zmemset (ptr, size, 0xe5);
    *(void **) ptr = *b;
    *b = ptr;
#ifdef ZALLOC_DEBUG
#ifdef ZALLOC_DEBUG_PRINT
    fprintf (stderr, "putting %08X into bucket %d\n",
	     ptr, bucket);
    fprintf (stderr, "bucket %d:");
    for (ptr = buckets[bucket]; ptr; ptr=*(void**)ptr)
	fprintf (stderr, " %X", ptr);
    fprintf (stderr, "\n");
#else
    for (ptr = buckets[bucket]; ptr; ptr=*(void**)ptr)
	/* do nothing, just read value */;
#endif
#endif

#ifdef ZALLOC_STATS
    zalloc_count[bucket][FREE]++, zalloc_count[bucket][ALLOCATED]--;
#endif
}
#endif