1 /* cygheap.cc: Cygwin heap manager.
3 Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
20 #include "child_info.h"
27 init_cygheap NO_COPY
*cygheap
;
28 void NO_COPY
*cygheap_max
;
30 extern "C" char _cygheap_mid
[] __attribute__((section(".cygheap")));
31 extern "C" char _cygheap_end
[];
33 static NO_COPY muto cygheap_protect
;
38 struct cygheap_entry
*next
;
42 #define NBUCKETS (sizeof (cygheap->buckets) / sizeof (cygheap->buckets[0]))
43 #define N0 ((_cmalloc_entry *) NULL)
44 #define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (unsigned) (N0->data)))
46 #define CFMAP_OPTIONS (SEC_RESERVE | PAGE_READWRITE)
47 #define MVMAP_OPTIONS (FILE_MAP_WRITE)
50 static void __stdcall
_cfree (void *) __attribute__((regparm(1)));
51 static void *__stdcall
_csbrk (int);
54 /* Called by fork or spawn to reallocate cygwin heap */
56 cygheap_fixup_in_child (bool execed
)
58 cygheap_max
= child_proc_info
->cygheap
;
59 cygheap
= (init_cygheap
*) cygheap_max
;
60 _csbrk ((char *) child_proc_info
->cygheap_max
- (char *) cygheap
);
61 child_copy (child_proc_info
->parent
, false, "cygheap", cygheap
, cygheap_max
, NULL
);
63 debug_fixup_after_fork_exec ();
66 cygheap
->hooks
.next
= NULL
;
67 cygheap
->user_heap
.base
= NULL
; /* We can allocate the heap anywhere */
68 /* Walk the allocated memory chain looking for orphaned memory from
70 for (_cmalloc_entry
*rvc
= cygheap
->chain
; rvc
; rvc
= rvc
->prev
)
72 cygheap_entry
*ce
= (cygheap_entry
*) rvc
->data
;
73 if (!rvc
->ptr
|| rvc
->b
>= NBUCKETS
|| ce
->type
<= HEAP_1_START
)
75 else if (ce
->type
< HEAP_1_MAX
)
76 ce
->type
+= HEAP_1_MAX
; /* Mark for freeing after next exec */
78 _cfree (ce
); /* Marked by parent for freeing in child */
84 init_cygheap::manage_console_count (const char *something
, int amount
, bool avoid_freeing_console
)
86 if (console_count
== 0 && amount
> 0)
87 init_console_handler (true);
88 console_count
+= amount
;
89 debug_printf ("%s: console_count %d, amount %d, %s, avoid_freeing_console %d",
90 something
, console_count
, amount
, myctty (), avoid_freeing_console
);
91 if (!avoid_freeing_console
&& amount
<= 0 && !console_count
&& myself
->ctty
== -1)
93 BOOL res
= FreeConsole ();
94 debug_printf ("freed console, res %d", res
);
95 init_console_handler (false);
101 init_cygheap::close_ctty ()
103 debug_printf ("closing cygheap->ctty %p", cygheap
->ctty
);
104 cygheap
->ctty
->close ();
105 cygheap
->ctty
= NULL
;
108 #define nextpage(x) ((char *) (((DWORD) ((char *) x + granmask)) & ~granmask))
109 #define allocsize(x) ((DWORD) nextpage (x))
111 #define somekinda_printf debug_printf
113 #define somekinda_printf malloc_printf
116 static void *__stdcall
119 void *prebrk
= cygheap_max
;
120 size_t granmask
= getpagesize () - 1;
121 char *newbase
= nextpage (prebrk
);
122 cygheap_max
= (char *) cygheap_max
+ sbs
;
123 if (!sbs
|| (newbase
>= cygheap_max
) || (cygheap_max
<= _cygheap_end
))
127 if (prebrk
<= _cygheap_end
)
128 newbase
= _cygheap_end
;
130 DWORD adjsbs
= allocsize ((char *) cygheap_max
- newbase
);
131 if (adjsbs
&& !VirtualAlloc (newbase
, adjsbs
, MEM_COMMIT
| MEM_RESERVE
, PAGE_READWRITE
))
133 MEMORY_BASIC_INFORMATION m
;
134 if (!VirtualQuery (newbase
, &m
, sizeof m
))
135 system_printf ("couldn't get memory info, %E");
136 somekinda_printf ("Couldn't reserve/commit %d bytes of space for cygwin's heap, %E",
138 somekinda_printf ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n",
139 m
.AllocationBase
, m
.BaseAddress
, m
.RegionSize
, m
.State
);
141 cygheap_max
= (char *) cygheap_max
- sbs
;
149 extern "C" void __stdcall
152 cygheap_protect
.init ("cygheap_protect");
155 cygheap
= (init_cygheap
*) memset (_cygheap_start
, 0,
156 _cygheap_mid
- _cygheap_start
);
157 cygheap_max
= cygheap
;
158 _csbrk (sizeof (*cygheap
));
161 cygheap
->fdtab
.init ();
166 /* Copyright (C) 1997, 2000 DJ Delorie */
168 static void *_cmalloc (unsigned size
) __attribute ((regparm(1)));
169 static void *__stdcall
_crealloc (void *ptr
, unsigned size
) __attribute ((regparm(2)));
171 static void *__stdcall
172 _cmalloc (unsigned size
)
177 /* Calculate "bit bucket" and size as a power of two. */
178 for (b
= 3, sz
= 8; sz
&& sz
< size
; b
++, sz
<<= 1)
181 cygheap_protect
.acquire ();
182 if (cygheap
->buckets
[b
])
184 rvc
= (_cmalloc_entry
*) cygheap
->buckets
[b
];
185 cygheap
->buckets
[b
] = rvc
->ptr
;
190 rvc
= (_cmalloc_entry
*) _csbrk (sz
+ sizeof (_cmalloc_entry
));
193 cygheap_protect
.release ();
198 rvc
->prev
= cygheap
->chain
;
199 cygheap
->chain
= rvc
;
201 cygheap_protect
.release ();
205 static void __stdcall
208 cygheap_protect
.acquire ();
209 _cmalloc_entry
*rvc
= to_cmalloc (ptr
);
211 rvc
->ptr
= cygheap
->buckets
[b
];
212 cygheap
->buckets
[b
] = (char *) rvc
;
213 cygheap_protect
.release ();
216 static void *__stdcall
217 _crealloc (void *ptr
, unsigned size
)
221 newptr
= _cmalloc (size
);
224 unsigned oldsize
= 1 << to_cmalloc (ptr
)->b
;
227 newptr
= _cmalloc (size
);
230 memcpy (newptr
, ptr
, oldsize
);
237 /* End Copyright (C) 1997 DJ Delorie */
239 #define sizeof_cygheap(n) ((n) + sizeof (cygheap_entry))
241 #define N ((cygheap_entry *) NULL)
242 #define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - (int) (N->data)))
245 creturn (cygheap_types x
, cygheap_entry
* c
, unsigned len
, const char *fn
= NULL
)
249 api_fatal ("%s would have returned NULL", fn
);
256 char *cend
= ((char *) c
+ sizeof (*c
) + len
);
257 if (cygheap_max
< cend
)
260 return (void *) c
->data
;
264 cmalloc (cygheap_types x
, DWORD n
, const char *fn
)
268 c
= (cygheap_entry
*) _cmalloc (sizeof_cygheap (n
));
269 return creturn (x
, c
, n
, fn
);
273 cmalloc (cygheap_types x
, DWORD n
)
275 return cmalloc (x
, n
, NULL
);
279 cmalloc_abort (cygheap_types x
, DWORD n
)
281 return cmalloc (x
, n
, "cmalloc");
285 crealloc (void *s
, DWORD n
, const char *fn
)
289 return cmalloc (HEAP_STR
, n
); // kludge
291 assert (!inheap (s
));
292 cygheap_entry
*c
= tocygheap (s
);
293 cygheap_types t
= (cygheap_types
) c
->type
;
294 c
= (cygheap_entry
*) _crealloc (c
, sizeof_cygheap (n
));
295 return creturn (t
, c
, n
, fn
);
298 extern "C" void *__stdcall
299 crealloc (void *s
, DWORD n
)
301 return crealloc (s
, n
, NULL
);
304 extern "C" void *__stdcall
305 crealloc_abort (void *s
, DWORD n
)
307 return crealloc (s
, n
, "crealloc");
310 extern "C" void __stdcall
313 assert (!inheap (s
));
314 _cfree (tocygheap (s
));
318 extern "C" void __stdcall
319 cfree_and_set (char *&s
, char *what
)
321 if (s
&& s
!= almost_null
)
327 ccalloc (cygheap_types x
, DWORD n
, DWORD size
, const char *fn
)
332 c
= (cygheap_entry
*) _cmalloc (sizeof_cygheap (n
));
334 memset (c
->data
, 0, n
);
335 return creturn (x
, c
, n
, fn
);
338 extern "C" void *__stdcall
339 ccalloc (cygheap_types x
, DWORD n
, DWORD size
)
341 return ccalloc (x
, n
, size
, NULL
);
344 extern "C" void *__stdcall
345 ccalloc_abort (cygheap_types x
, DWORD n
, DWORD size
)
347 return ccalloc (x
, n
, size
, "ccalloc");
350 extern "C" PWCHAR __stdcall
351 cwcsdup (const PWCHAR s
)
354 PWCHAR p
= (PWCHAR
) cmalloc (HEAP_STR
, wcslen (s
) + 1);
362 extern "C" PWCHAR __stdcall
363 cwcsdup1 (const PWCHAR s
)
366 PWCHAR p
= (PWCHAR
) cmalloc (HEAP_1_STR
, wcslen (s
) + 1);
374 extern "C" char *__stdcall
375 cstrdup (const char *s
)
378 char *p
= (char *) cmalloc (HEAP_STR
, strlen (s
) + 1);
386 extern "C" char *__stdcall
387 cstrdup1 (const char *s
)
390 char *p
= (char *) cmalloc (HEAP_1_STR
, strlen (s
) + 1);
399 cygheap_root::set (const char *posix
, const char *native
)
401 if (*posix
== '/' && posix
[1] == '\0')
411 m
= (struct cygheap_root_mount_info
*) ccalloc (HEAP_MOUNT
, 1, sizeof (*m
));
412 strcpy (m
->posix_path
, posix
);
413 m
->posix_pathlen
= strlen (posix
);
414 if (m
->posix_pathlen
>= 1 && m
->posix_path
[m
->posix_pathlen
- 1] == '/')
415 m
->posix_path
[--m
->posix_pathlen
] = '\0';
417 strcpy (m
->native_path
, native
);
418 m
->native_pathlen
= strlen (native
);
419 if (m
->native_pathlen
>= 1 && m
->native_path
[m
->native_pathlen
- 1] == '\\')
420 m
->native_path
[--m
->native_pathlen
] = '\0';
423 cygheap_user::~cygheap_user ()
438 cygheap_user::set_name (const char *new_name
)
440 bool allocated
= !!pname
;
444 if (strcasematch (new_name
, pname
))
449 pname
= cstrdup (new_name
? new_name
: "");
451 return; /* Initializing. Don't bother with other stuff. */
453 cfree_and_set (homedrive
);
454 cfree_and_set (homepath
);
455 cfree_and_set (plogsrv
);
456 cfree_and_set (pdomain
);
457 cfree_and_set (pwinname
);