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