blob: 083c75d958097b4a973f6ac72bc3c4074cf31dbc [file] [log] [blame]
mostang.com!davidmdd3c6812002-07-18 03:58:34 +00001#include <assert.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5
6#include <sys/mman.h>
7
8#include "libunwind.h"
9#include "mempool.h"
10
11#define SOSLOCK() /* XXX fix me */
12#define SOSUNLOCK() /* XXX fix me */
13#define LOCK(p) /* XXX fix me */
14#define UNLOCK(p) /* XXX fix me */
15
16#define MAX_ALIGN (sizeof (long double))
17#define SOS_MEMORY_SIZE 16384
18
19static char sos_memory[SOS_MEMORY_SIZE];
20static char *sos_memp = sos_memory;
21static size_t pg_size = 0;
22
23void *
24sos_alloc (size_t size)
25{
26 char *mem;
27
28 size = (size + MAX_ALIGN - 1) & -MAX_ALIGN;
29
30 mem = (char *) (((unsigned long) sos_memp + MAX_ALIGN - 1)
31 & -MAX_ALIGN);
32 if (mem + size >= sos_memory + sizeof (sos_memory))
33 sos_memp = mem + size;
34
35 if (!mem)
36 abort ();
37
38 return mem;
39}
40
41void
42sos_free (void *ptr)
43{
44}
45
46static void *
47alloc_memory (size_t size)
48{
49 /* Hopefully, mmap() goes straight through to a system call stub... */
50 void *mem = mmap (0, size, PROT_READ | PROT_WRITE,
51 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
52 if (mem == MAP_FAILED)
53 return NULL;
54
55 return mem;
56}
57
58/* Must be called while holding the mempool lock. */
59
60static void
61free_object (struct mempool *pool, void *object)
62{
63 struct object *obj = object;
64
65 obj->next = pool->free_list;
66 pool->free_list = obj;
67 ++pool->num_free;
68}
69
70static void
71add_memory (struct mempool *pool, char *mem, size_t size, size_t obj_size)
72{
73 char *obj;
74
75 for (obj = mem; obj + obj_size <= mem + size; obj += obj_size)
76 free_object (pool, obj);
77}
78
79static void
80expand (struct mempool *pool)
81{
82 size_t size;
83 char *mem;
84
85 size = pool->chunk_size;
86 mem = alloc_memory (size);
87 if (!mem)
88 {
89 size = (pool->obj_size + pg_size - 1) & -pg_size;
90 mem = alloc_memory (size);
91 if (!mem)
92 {
93 /* last chance: try to allocate one object from the SOS memory */
94 size = pool->obj_size;
95 mem = sos_alloc (size);
96 }
97 }
98 add_memory (pool, mem, size, pool->obj_size);
99}
100
101void
102mempool_init (struct mempool *pool, size_t obj_size, size_t reserve)
103{
104 if (pg_size == 0)
105 pg_size = getpagesize ();
106
107 memset (pool, 0, sizeof (*pool));
108
109 /* round object-size up to integer multiple of MAX_ALIGN */
110 obj_size = (obj_size + MAX_ALIGN - 1) & -MAX_ALIGN;
111
112 if (!reserve)
113 {
114 reserve = pg_size / obj_size / 2;
115 if (!reserve)
116 reserve = 16;
117 }
118
119 pool->obj_size = obj_size;
120 pool->reserve = reserve;
121 pool->chunk_size = (2*reserve*obj_size + pg_size - 1) & -pg_size;
122
123 expand (pool);
124}
125
126void *
127mempool_alloc (struct mempool *pool)
128{
129 struct object *obj;
130
131 LOCK(pool);
132 {
133 if (pool->num_free <= pool->reserve)
134 expand (pool);
135
136 assert (pool->num_free > 0);
137
138 --pool->num_free;
139 obj = pool->free_list;
140 pool->free_list = obj->next;
141 }
142 UNLOCK(pool);
143 return obj;
144}
145
146void
147mempool_free (struct mempool *pool, void *object)
148{
149 LOCK(pool);
150 free_object (pool, object);
151 UNLOCK(pool);
152}