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