]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/cygheap.cc
*** empty log message ***
[newlib-cygwin.git] / winsup / cygwin / cygheap.cc
CommitLineData
b0e82b74
CF
1/* cygheap.cc: Cygwin heap manager.
2
ca1cea7e 3 Copyright 2000, 2001 Red Hat, Inc.
b0e82b74
CF
4
5 This file is part of Cygwin.
6
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9 details. */
10
11#include "winsup.h"
12#include <errno.h>
13#include <fhandler.h>
14#include <assert.h>
9fc09d00 15#include <stdlib.h>
b0e82b74
CF
16#include "cygheap.h"
17#include "heap.h"
18#include "cygerrno.h"
9fc09d00 19#include "sync.h"
2a6fc028 20#include "shared_info.h"
b0e82b74 21
a4785603 22init_cygheap NO_COPY *cygheap;
1ec4f618 23void NO_COPY *cygheap_max = NULL;
8d82847a 24
9fc09d00
CF
25static NO_COPY muto *cygheap_protect = NULL;
26
b0e82b74
CF
27inline static void
28init_cheap ()
29{
6a4878cf 30 cygheap = (init_cygheap *) VirtualAlloc (NULL, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS);
9149d76e
CF
31 if (!cygheap)
32 api_fatal ("Couldn't reserve space for cygwin's heap, %E");
a4785603 33 cygheap_max = cygheap + 1;
b0e82b74
CF
34}
35
36#define pagetrunc(x) ((void *) (((DWORD) (x)) & ~(4096 - 1)))
8d82847a 37
b0e82b74
CF
38static void *__stdcall
39_csbrk (int sbs)
40{
41 void *lastheap;
8d82847a
CF
42 bool needalloc;
43
44 if (cygheap)
45 needalloc = 0;
46 else
47 {
48 init_cheap ();
49 needalloc = 1;
50 }
51
b0e82b74
CF
52 lastheap = cygheap_max;
53 (char *) cygheap_max += sbs;
54 void *heapalign = (void *) pagetrunc (lastheap);
8d82847a
CF
55
56 if (!needalloc)
57 needalloc = sbs && ((heapalign == lastheap) || heapalign != pagetrunc (cygheap_max));
a4785603 58 if (needalloc && !VirtualAlloc (lastheap, (DWORD) sbs ?: 1, MEM_COMMIT, PAGE_READWRITE))
b0e82b74
CF
59 api_fatal ("couldn't commit memory for cygwin heap, %E");
60
61 return lastheap;
62}
63
a4785603
CF
64extern "C" void __stdcall
65cygheap_init ()
66{
67 cygheap_protect = new_muto (FALSE, "cygheap_protect");
68 _csbrk (0);
69}
70
b0e82b74
CF
71/* Copyright (C) 1997, 2000 DJ Delorie */
72
8d82847a
CF
73#define NBUCKETS 32
74char *buckets[NBUCKETS] = {0};
b0e82b74 75
8d82847a
CF
76#define N0 ((_cmalloc_entry *) NULL)
77#define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (int) (N0->data)))
8d82847a 78
166b2571
CF
79static void *_cmalloc (int size) __attribute ((regparm(1)));
80static void *__stdcall _crealloc (void *ptr, int size) __attribute ((regparm(2)));
81
b0e82b74
CF
82static void *__stdcall
83_cmalloc (int size)
84{
8d82847a 85 _cmalloc_entry *rvc;
166b2571 86 int b, sz;
b0e82b74 87
166b2571
CF
88 /* Calculate "bit bucket" and size as a power of two. */
89 for (b = 3, sz = 8; sz && sz < (size + 4); b++, sz <<= 1)
90 continue;
b0e82b74 91
9fc09d00 92 cygheap_protect->acquire ();
b0e82b74
CF
93 if (buckets[b])
94 {
8d82847a
CF
95 rvc = (_cmalloc_entry *) buckets[b];
96 buckets[b] = rvc->ptr;
97 rvc->b = b;
b0e82b74 98 }
9fc09d00
CF
99 else
100 {
166b2571 101 size = sz + sizeof (_cmalloc_entry);
9fc09d00 102 rvc = (_cmalloc_entry *) _csbrk (size);
b0e82b74 103
9fc09d00 104 rvc->b = b;
a4785603
CF
105 rvc->prev = cygheap->chain;
106 cygheap->chain = rvc;
9fc09d00
CF
107 }
108 cygheap_protect->release ();
8d82847a 109 return rvc->data;
b0e82b74
CF
110}
111
112static void __stdcall
113_cfree (void *ptr)
114{
9fc09d00 115 cygheap_protect->acquire ();
8d82847a
CF
116 _cmalloc_entry *rvc = to_cmalloc (ptr);
117 DWORD b = rvc->b;
118 rvc->ptr = buckets[b];
119 buckets[b] = (char *) rvc;
9fc09d00 120 cygheap_protect->release ();
b0e82b74
CF
121}
122
123static void *__stdcall
124_crealloc (void *ptr, int size)
125{
7e24f1bf
CF
126 void *newptr;
127 if (ptr == NULL)
128 newptr = _cmalloc (size);
129 else
130 {
166b2571 131 int oldsize = 1 << to_cmalloc (ptr)->b;
7e24f1bf
CF
132 if (size <= oldsize)
133 return ptr;
134 newptr = _cmalloc (size);
135 memcpy (newptr, ptr, oldsize);
136 _cfree (ptr);
137 }
b0e82b74
CF
138 return newptr;
139}
140
141/* End Copyright (C) 1997 DJ Delorie */
142
b0e82b74
CF
143#define sizeof_cygheap(n) ((n) + sizeof(cygheap_entry))
144
145struct cygheap_entry
146 {
8d82847a
CF
147 int type;
148 struct cygheap_entry *next;
b0e82b74
CF
149 char data[0];
150 };
151
152#define N ((cygheap_entry *) NULL)
153#define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - (int) (N->data)))
154
8d82847a 155/* Called by fork or spawn to reallocate cygwin heap */
b0e82b74 156extern "C" void __stdcall
8d82847a 157cygheap_fixup_in_child (HANDLE parent, bool execed)
b0e82b74
CF
158{
159 DWORD m, n;
160 n = (DWORD) cygheap_max - (DWORD) cygheap;
8d82847a
CF
161
162 /* Reserve cygwin heap in same spot as parent */
b0e82b74 163 if (!VirtualAlloc (cygheap, CYGHEAPSIZE, MEM_RESERVE, PAGE_NOACCESS))
a4785603 164 api_fatal ("Couldn't reserve space for cygwin's heap (%p) in child, cygheap, %E", cygheap);
b0e82b74 165
8d82847a 166 /* Allocate same amount of memory as parent */
b0e82b74
CF
167 if (!VirtualAlloc (cygheap, n, MEM_COMMIT, PAGE_READWRITE))
168 api_fatal ("Couldn't allocate space for child's heap %p, size %d, %E",
169 cygheap, n);
8d82847a
CF
170
171 /* Copy memory from the parent */
b0e82b74 172 m = 0;
aece55b9 173 if (!ReadProcessMemory (parent, cygheap, cygheap, n, &m) || m != n)
b0e82b74
CF
174 api_fatal ("Couldn't read parent's cygwin heap %d bytes != %d, %E",
175 n, m);
8d82847a 176
a4785603 177 cygheap_init ();
8d82847a 178
a4785603 179 if (execed)
8d82847a 180 {
a4785603
CF
181 /* Walk the allocated memory chain looking for orphaned memory from
182 previous execs */
183 for (_cmalloc_entry *rvc = cygheap->chain; rvc; rvc = rvc->prev)
184 {
185 cygheap_entry *ce = (cygheap_entry *) rvc->data;
186 if (rvc->b >= NBUCKETS || ce->type <= HEAP_1_START)
187 continue;
188 else if (ce->type < HEAP_1_MAX)
189 ce->type += HEAP_1_MAX; /* Mark for freeing after next exec */
190 else
191 _cfree (ce); /* Marked by parent for freeing in child */
192 }
8d82847a 193 }
b0e82b74
CF
194}
195
166b2571 196inline static void *
b0e82b74
CF
197creturn (cygheap_types x, cygheap_entry * c, int len)
198{
199 if (!c)
200 {
201 __seterrno ();
202 return NULL;
203 }
204 c->type = x;
47f81092
CF
205 char *cend = ((char *) c + sizeof (*c) + len);
206 if (cygheap_max < cend)
207 cygheap_max = cend;
9fc09d00 208 MALLOC_CHECK;
b0e82b74
CF
209 return (void *) c->data;
210}
211
212extern "C" void *__stdcall
213cmalloc (cygheap_types x, DWORD n)
214{
215 cygheap_entry *c;
9fc09d00 216 MALLOC_CHECK;
b0e82b74
CF
217 c = (cygheap_entry *) _cmalloc (sizeof_cygheap (n));
218 if (!c)
219 system_printf ("cmalloc returned NULL");
220 return creturn (x, c, n);
221}
222
223extern "C" void *__stdcall
224crealloc (void *s, DWORD n)
225{
9fc09d00 226 MALLOC_CHECK;
b0e82b74
CF
227 if (s == NULL)
228 return cmalloc (HEAP_STR, n); // kludge
229
230 assert (!inheap (s));
231 cygheap_entry *c = tocygheap (s);
8d82847a 232 cygheap_types t = (cygheap_types) c->type;
b0e82b74
CF
233 c = (cygheap_entry *) _crealloc (c, sizeof_cygheap (n));
234 if (!c)
235 system_printf ("crealloc returned NULL");
236 return creturn (t, c, n);
237}
238
239extern "C" void __stdcall
240cfree (void *s)
241{
9fc09d00 242 MALLOC_CHECK;
b0e82b74
CF
243 assert (!inheap (s));
244 (void) _cfree (tocygheap (s));
9fc09d00 245 MALLOC_CHECK;
b0e82b74
CF
246}
247
248extern "C" void *__stdcall
249ccalloc (cygheap_types x, DWORD n, DWORD size)
250{
251 cygheap_entry *c;
9fc09d00 252 MALLOC_CHECK;
b0e82b74
CF
253 c = (cygheap_entry *) _cmalloc (sizeof_cygheap (n * size));
254 if (c)
bb5d559a 255 memset (c->data, 0, n * size);
b0e82b74
CF
256 if (!c)
257 system_printf ("ccalloc returned NULL");
258 return creturn (x, c, n);
259}
260
261extern "C" char *__stdcall
262cstrdup (const char *s)
263{
9fc09d00 264 MALLOC_CHECK;
b0e82b74
CF
265 char *p = (char *) cmalloc (HEAP_STR, strlen (s) + 1);
266 if (!p)
267 return NULL;
268 strcpy (p, s);
9fc09d00 269 MALLOC_CHECK;
b0e82b74
CF
270 return p;
271}
e5648465
CF
272
273extern "C" char *__stdcall
274cstrdup1 (const char *s)
275{
9fc09d00 276 MALLOC_CHECK;
e5648465
CF
277 char *p = (char *) cmalloc (HEAP_1_STR, strlen (s) + 1);
278 if (!p)
279 return NULL;
280 strcpy (p, s);
9fc09d00 281 MALLOC_CHECK;
e5648465
CF
282 return p;
283}
1f0f8e12
CV
284
285cygheap_root::cygheap_root (cygheap_root &nroot)
286{
287 rootlen = nroot.rootlen;
288 root = nroot.root ? cstrdup (nroot.root) : NULL;
289}
290
291cygheap_root::~cygheap_root ()
292{
293 if (root)
294 cfree (root);
295}
296
297char *
298cygheap_root::operator =(const char *new_root)
299{
300 if (root)
301 {
302 cfree (root);
303 root = NULL;
304 }
305 rootlen = 0;
306 if (new_root && *new_root)
307 {
308 root = cstrdup (new_root);
309 rootlen = strlen (root);
09872ef8 310 if (rootlen >= 1 && root[rootlen - 1] == '/')
1f0f8e12
CV
311 root[--rootlen] = '\0';
312 if (!rootlen)
313 {
314 cfree (root);
315 root = NULL;
316 }
317 }
318 return root;
319}
320
321cygheap_user::~cygheap_user ()
322{
cb503978 323#if 0
1f0f8e12
CV
324 if (pname)
325 cfree (pname);
326 if (plogsrv)
327 cfree (plogsrv);
328 if (pdomain)
329 cfree (pdomain);
330 if (psid)
331 cfree (psid);
cb503978 332#endif
1f0f8e12
CV
333}
334
335void
336cygheap_user::set_name (const char *new_name)
337{
338 if (pname)
339 cfree (pname);
340 pname = cstrdup (new_name ? new_name : "");
341}
342
343void
344cygheap_user::set_logsrv (const char *new_logsrv)
345{
346 if (plogsrv)
347 cfree (plogsrv);
348 plogsrv = (new_logsrv && *new_logsrv) ? cstrdup (new_logsrv) : NULL;
349}
350
351void
352cygheap_user::set_domain (const char *new_domain)
353{
354 if (pdomain)
355 cfree (pdomain);
356 pdomain = (new_domain && *new_domain) ? cstrdup (new_domain) : NULL;
357}
358
359BOOL
360cygheap_user::set_sid (PSID new_sid)
361{
362 if (!new_sid)
363 {
364 if (psid)
365 cfree (psid);
366 psid = NULL;
367 return TRUE;
368 }
369 else
370 {
371 if (!psid)
372 psid = cmalloc (HEAP_STR, MAX_SID_LEN);
373 return CopySid (MAX_SID_LEN, psid, new_sid);
374 }
375}
This page took 0.076476 seconds and 5 git commands to generate.