1 /* cygheap.cc: Cygwin heap manager.
3 Copyright 2000, 2001 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"
24 #include "shared_info.h"
26 init_cygheap NO_COPY
*cygheap
;
27 void NO_COPY
*cygheap_max
= NULL
;
29 static NO_COPY muto
*cygheap_protect
= NULL
;
34 struct cygheap_entry
*next
;
38 #define NBUCKETS (sizeof (cygheap->buckets) / sizeof (cygheap->buckets[0]))
39 #define N0 ((_cmalloc_entry *) NULL)
40 #define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (int) (N0->data)))
42 #define CFMAP_OPTIONS (SEC_RESERVE | PAGE_READWRITE)
43 #define MVMAP_OPTIONS (FILE_MAP_WRITE)
46 static void __stdcall
_cfree (void *ptr
) __attribute__((regparm(1)));
47 extern void *_cygheap_start
;
53 cygheap
= (init_cygheap
*) VirtualAlloc ((void *) &_cygheap_start
, CYGHEAPSIZE
, MEM_RESERVE
, PAGE_NOACCESS
);
56 MEMORY_BASIC_INFORMATION m
;
57 if (!VirtualQuery ((LPCVOID
) &_cygheap_start
, &m
, sizeof m
))
58 system_printf ("couldn't get memory info, %E");
59 small_printf ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n",
60 m
.AllocationBase
, m
.BaseAddress
, m
.RegionSize
, m
.State
);
61 api_fatal ("Couldn't reserve space for cygwin's heap, %E");
63 cygheap_max
= cygheap
+ 1;
67 cygheap_setup_for_child (child_info
*ci
)
70 cygheap_protect
->acquire ();
71 unsigned n
= (char *) cygheap_max
- (char *) cygheap
;
72 ci
->cygheap_h
= CreateFileMapping (INVALID_HANDLE_VALUE
, &sec_none
,
73 CFMAP_OPTIONS
, 0, CYGHEAPSIZE
, NULL
);
74 newcygheap
= MapViewOfFileEx (ci
->cygheap_h
, MVMAP_OPTIONS
, 0, 0, 0, NULL
);
75 if (!VirtualAlloc (newcygheap
, n
, MEM_COMMIT
, PAGE_READWRITE
))
76 api_fatal ("couldn't allocate new cygwin heap for child, %E");
77 memcpy (newcygheap
, cygheap
, n
);
78 UnmapViewOfFile (newcygheap
);
79 ci
->cygheap
= cygheap
;
80 ci
->cygheap_max
= cygheap_max
;
81 ProtectHandle1 (ci
->cygheap_h
, passed_cygheap_h
);
82 cygheap_protect
->release ();
87 cygheap_setup_for_child_cleanup (child_info
*ci
)
89 ForceCloseHandle1 (ci
->cygheap_h
, passed_cygheap_h
);
92 /* Called by fork or spawn to reallocate cygwin heap */
94 cygheap_fixup_in_child (child_info
*ci
, bool execed
)
96 cygheap
= ci
->cygheap
;
97 cygheap_max
= ci
->cygheap_max
;
98 void *addr
= iswinnt
? cygheap
: NULL
;
101 newaddr
= MapViewOfFileEx (ci
->cygheap_h
, MVMAP_OPTIONS
, 0, 0, 0, addr
);
102 if (newaddr
!= cygheap
)
105 newaddr
= MapViewOfFileEx (ci
->cygheap_h
, MVMAP_OPTIONS
, 0, 0, 0, NULL
);
106 DWORD n
= (DWORD
) cygheap_max
- (DWORD
) cygheap
;
107 /* Reserve cygwin heap in same spot as parent */
108 if (!VirtualAlloc (cygheap
, CYGHEAPSIZE
, MEM_RESERVE
, PAGE_NOACCESS
))
110 MEMORY_BASIC_INFORMATION m
;
111 memset (&m
, 0, sizeof m
);
112 if (!VirtualQuery ((LPCVOID
) cygheap
, &m
, sizeof m
))
113 system_printf ("couldn't get memory info, %E");
115 small_printf ("m.AllocationBase %p, m.BaseAddress %p, m.RegionSize %p, m.State %p\n",
116 m
.AllocationBase
, m
.BaseAddress
, m
.RegionSize
, m
.State
);
117 api_fatal ("Couldn't reserve space for cygwin's heap (%p <%p>) in child, %E", cygheap
, newaddr
);
120 /* Allocate same amount of memory as parent */
121 if (!VirtualAlloc (cygheap
, n
, MEM_COMMIT
, PAGE_READWRITE
))
122 api_fatal ("Couldn't allocate space for child's heap %p, size %d, %E",
124 memcpy (cygheap
, newaddr
, n
);
125 UnmapViewOfFile (newaddr
);
128 ForceCloseHandle1 (ci
->cygheap_h
, passed_cygheap_h
);
134 /* Walk the allocated memory chain looking for orphaned memory from
136 for (_cmalloc_entry
*rvc
= cygheap
->chain
; rvc
; rvc
= rvc
->prev
)
138 cygheap_entry
*ce
= (cygheap_entry
*) rvc
->data
;
139 if (!rvc
->ptr
|| rvc
->b
>= NBUCKETS
|| ce
->type
<= HEAP_1_START
)
141 else if (ce
->type
< HEAP_1_MAX
)
142 ce
->type
+= HEAP_1_MAX
; /* Mark for freeing after next exec */
144 _cfree (ce
); /* Marked by parent for freeing in child */
149 #define pagetrunc(x) ((void *) (((DWORD) (x)) & ~(4096 - 1)))
151 static void *__stdcall
165 lastheap
= cygheap_max
;
166 (char *) cygheap_max
+= sbs
;
167 void *heapalign
= (void *) pagetrunc (lastheap
);
170 needalloc
= sbs
&& ((heapalign
== lastheap
) || heapalign
!= pagetrunc (cygheap_max
));
171 if (needalloc
&& !VirtualAlloc (lastheap
, (DWORD
) sbs
?: 1, MEM_COMMIT
, PAGE_READWRITE
))
172 api_fatal ("couldn't commit memory for cygwin heap, %E");
177 extern "C" void __stdcall
180 cygheap_protect
= new_muto (FALSE
, "cygheap_protect");
183 cygheap
->fdtab
.init ();
186 /* Copyright (C) 1997, 2000 DJ Delorie */
188 static void *_cmalloc (int size
) __attribute ((regparm(1)));
189 static void *__stdcall
_crealloc (void *ptr
, int size
) __attribute ((regparm(2)));
191 static void *__stdcall
197 /* Calculate "bit bucket" and size as a power of two. */
198 for (b
= 3, sz
= 8; sz
&& sz
< (size
+ sizeof (_cmalloc_entry
));
202 cygheap_protect
->acquire ();
203 if (cygheap
->buckets
[b
])
205 rvc
= (_cmalloc_entry
*) cygheap
->buckets
[b
];
206 cygheap
->buckets
[b
] = rvc
->ptr
;
211 size
= sz
+ sizeof (_cmalloc_entry
);
212 rvc
= (_cmalloc_entry
*) _csbrk (size
);
215 rvc
->prev
= cygheap
->chain
;
216 cygheap
->chain
= rvc
;
218 cygheap_protect
->release ();
222 static void __stdcall
225 cygheap_protect
->acquire ();
226 _cmalloc_entry
*rvc
= to_cmalloc (ptr
);
228 rvc
->ptr
= cygheap
->buckets
[b
];
229 cygheap
->buckets
[b
] = (char *) rvc
;
230 cygheap_protect
->release ();
233 static void *__stdcall
_crealloc (void *ptr
, int size
) __attribute__((regparm(2)));
234 static void *__stdcall
235 _crealloc (void *ptr
, int size
)
239 newptr
= _cmalloc (size
);
242 int oldsize
= 1 << to_cmalloc (ptr
)->b
;
245 newptr
= _cmalloc (size
);
246 memcpy (newptr
, ptr
, oldsize
);
252 /* End Copyright (C) 1997 DJ Delorie */
254 #define sizeof_cygheap(n) ((n) + sizeof(cygheap_entry))
256 #define N ((cygheap_entry *) NULL)
257 #define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - (int) (N->data)))
260 creturn (cygheap_types x
, cygheap_entry
* c
, int len
)
268 char *cend
= ((char *) c
+ sizeof (*c
) + len
);
269 if (cygheap_max
< cend
)
272 return (void *) c
->data
;
275 extern "C" void *__stdcall
276 cmalloc (cygheap_types x
, DWORD n
)
280 c
= (cygheap_entry
*) _cmalloc (sizeof_cygheap (n
));
282 system_printf ("cmalloc returned NULL");
283 return creturn (x
, c
, n
);
286 extern "C" void *__stdcall
287 crealloc (void *s
, DWORD n
)
291 return cmalloc (HEAP_STR
, n
); // kludge
293 assert (!inheap (s
));
294 cygheap_entry
*c
= tocygheap (s
);
295 cygheap_types t
= (cygheap_types
) c
->type
;
296 c
= (cygheap_entry
*) _crealloc (c
, sizeof_cygheap (n
));
298 system_printf ("crealloc returned NULL");
299 return creturn (t
, c
, n
);
302 extern "C" void __stdcall
306 assert (!inheap (s
));
307 (void) _cfree (tocygheap (s
));
311 extern "C" void *__stdcall
312 ccalloc (cygheap_types x
, DWORD n
, DWORD size
)
316 c
= (cygheap_entry
*) _cmalloc (sizeof_cygheap (n
* size
));
318 memset (c
->data
, 0, n
* size
);
320 system_printf ("ccalloc returned NULL");
321 return creturn (x
, c
, n
);
324 extern "C" char *__stdcall
325 cstrdup (const char *s
)
328 char *p
= (char *) cmalloc (HEAP_STR
, strlen (s
) + 1);
336 extern "C" char *__stdcall
337 cstrdup1 (const char *s
)
340 char *p
= (char *) cmalloc (HEAP_1_STR
, strlen (s
) + 1);
349 cygheap_root::set (const char *posix
, const char *native
)
351 if (*posix
== '/' && posix
[1] == '\0')
361 m
= (struct cygheap_root_mount_info
*) ccalloc (HEAP_MOUNT
, 1, sizeof (*m
));
362 strcpy (m
->posix_path
, posix
);
363 m
->posix_pathlen
= strlen (posix
);
364 if (m
->posix_pathlen
>= 1 && m
->posix_path
[m
->posix_pathlen
- 1] == '/')
365 m
->posix_path
[--m
->posix_pathlen
] = '\0';
367 strcpy (m
->native_path
, native
);
368 m
->native_pathlen
= strlen (native
);
369 if (m
->native_pathlen
>= 1 && m
->native_path
[m
->native_pathlen
- 1] == '\\')
370 m
->native_path
[--m
->native_pathlen
] = '\0';
373 cygheap_user::~cygheap_user ()
388 cygheap_user::set_name (const char *new_name
)
392 pname
= cstrdup (new_name
? new_name
: "");
396 cygheap_user::set_logsrv (const char *new_logsrv
)
400 plogsrv
= (new_logsrv
&& *new_logsrv
) ? cstrdup (new_logsrv
) : NULL
;
404 cygheap_user::set_domain (const char *new_domain
)
408 pdomain
= (new_domain
&& *new_domain
) ? cstrdup (new_domain
) : NULL
;
412 cygheap_user::set_sid (PSID new_sid
)
424 psid
= cmalloc (HEAP_STR
, MAX_SID_LEN
);
425 return CopySid (MAX_SID_LEN
, psid
, new_sid
);