OSDN Git Service

* path.cc (conv_path_list): Take cygwin_conv_path_t as third parameter.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / cygheap.cc
1 /* cygheap.cc: Cygwin heap manager.
2
3    Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
4    2010, 2011 Red Hat, Inc.
5
6    This file is part of Cygwin.
7
8    This software is a copyrighted work licensed under the terms of the
9    Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10    details. */
11
12 #include "winsup.h"
13 #include <assert.h>
14 #include <stdlib.h>
15 #include "cygerrno.h"
16 #include "security.h"
17 #include "path.h"
18 #include "tty.h"
19 #include "fhandler.h"
20 #include "dtable.h"
21 #include "cygheap.h"
22 #include "child_info.h"
23 #include "heap.h"
24 #include "sigproc.h"
25 #include "pinfo.h"
26 #include <unistd.h>
27 #include <wchar.h>
28
29 static mini_cygheap NO_COPY cygheap_dummy =
30 {
31   {__utf8_mbtowc, __utf8_wctomb}
32 };
33
34 init_cygheap NO_COPY *cygheap = (init_cygheap *) &cygheap_dummy;
35 void NO_COPY *cygheap_max;
36
37 extern "C" char  _cygheap_end[];
38
39 static NO_COPY muto cygheap_protect;
40
41 struct cygheap_entry
42 {
43   int type;
44   struct cygheap_entry *next;
45   char data[0];
46 };
47
48 #define NBUCKETS (sizeof (cygheap->buckets) / sizeof (cygheap->buckets[0]))
49 #define N0 ((_cmalloc_entry *) NULL)
50 #define to_cmalloc(s) ((_cmalloc_entry *) (((char *) (s)) - (unsigned) (N0->data)))
51
52 #define CFMAP_OPTIONS (SEC_RESERVE | PAGE_READWRITE)
53 #define MVMAP_OPTIONS (FILE_MAP_WRITE)
54
55 extern "C" {
56 static void __stdcall _cfree (void *) __attribute__((regparm(1)));
57 static void *__stdcall _csbrk (int);
58 }
59
60 /* Called by fork or spawn to reallocate cygwin heap */
61 void __stdcall
62 cygheap_fixup_in_child (bool execed)
63 {
64   cygheap_max = cygheap = (init_cygheap *) _cygheap_start;
65   _csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap);
66   child_copy (child_proc_info->parent, false, "cygheap", cygheap, cygheap_max, NULL);
67   cygheap_init ();
68   debug_fixup_after_fork_exec ();
69   if (execed)
70     {
71       cygheap->hooks.next = NULL;
72       cygheap->user_heap.base = NULL;           /* We can allocate the heap anywhere */
73     }
74   /* Walk the allocated memory chain looking for orphaned memory from
75      previous execs or forks */
76   for (_cmalloc_entry *rvc = cygheap->chain; rvc; rvc = rvc->prev)
77     {
78       cygheap_entry *ce = (cygheap_entry *) rvc->data;
79       if (!rvc->ptr || rvc->b >= NBUCKETS || ce->type <= HEAP_1_START)
80         continue;
81       else if (ce->type > HEAP_2_MAX)
82         _cfree (ce);            /* Marked for freeing in any child */
83       else if (!execed)
84         continue;
85       else if (ce->type > HEAP_1_MAX)
86         _cfree (ce);            /* Marked for freeing in execed child */
87       else
88         ce->type += HEAP_1_MAX; /* Mark for freeing after next exec */
89     }
90 }
91
92 int
93 init_cygheap::manage_console_count (const char *something, int amount, bool avoid_freeing_console)
94 {
95   if (console_count == 0 && amount > 0)
96     init_console_handler (true);
97   console_count += amount;
98   debug_printf ("%s: console_count %d, amount %d, %s, avoid_freeing_console %d",
99                 something, console_count, amount, myctty (), avoid_freeing_console);
100   if (!avoid_freeing_console && amount <= 0 && !console_count && myself->ctty == -1)
101     {
102       BOOL res = FreeConsole ();
103       debug_printf ("freed console, res %d", res);
104       init_console_handler (false);
105     }
106   return console_count;
107 }
108
109 void
110 init_cygheap::close_ctty ()
111 {
112   debug_printf ("closing cygheap->ctty %p", cygheap->ctty);
113   cygheap->ctty->close_with_arch ();
114   cygheap->ctty = NULL;
115 }
116
117 #define nextpage(x) ((char *) (((DWORD) ((char *) x + granmask)) & ~granmask))
118 #define allocsize(x) ((DWORD) nextpage (x))
119 #ifdef DEBUGGING
120 #define somekinda_printf debug_printf
121 #else
122 #define somekinda_printf malloc_printf
123 #endif
124
125 static void *__stdcall
126 _csbrk (int sbs)
127 {
128   void *prebrk = cygheap_max;
129   size_t granmask = getpagesize () - 1;
130   char *newbase = nextpage (prebrk);
131   cygheap_max = (char *) cygheap_max + sbs;
132   if (!sbs || (newbase >= cygheap_max) || (cygheap_max <= _cygheap_end))
133     /* nothing to do */;
134   else
135     {
136       if (prebrk <= _cygheap_end)
137         newbase = _cygheap_end;
138
139       DWORD adjsbs = allocsize ((char *) cygheap_max - newbase);
140       if (adjsbs && !VirtualAlloc (newbase, adjsbs, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))
141         {
142           MEMORY_BASIC_INFORMATION m;
143           if (!VirtualQuery (newbase, &m, sizeof m))
144             system_printf ("couldn't get memory info, %E");
145           somekinda_printf ("Couldn't reserve/commit %d bytes of space for cygwin's heap, %E",
146                             adjsbs);
147           somekinda_printf ("AllocationBase %p, BaseAddress %p, RegionSize %p, State %p\n",
148                             m.AllocationBase, m.BaseAddress, m.RegionSize, m.State);
149           __seterrno ();
150           cygheap_max = (char *) cygheap_max - sbs;
151           return NULL;
152         }
153     }
154
155   return prebrk;
156 }
157
158 void __stdcall
159 cygheap_init ()
160 {
161   cygheap_protect.init ("cygheap_protect");
162   if (cygheap == &cygheap_dummy)
163     {
164       cygheap = (init_cygheap *) memset (_cygheap_start, 0,
165                                          sizeof (*cygheap));
166       cygheap_max = cygheap;
167       _csbrk (sizeof (*cygheap));
168       /* Default locale settings. */
169       cygheap->locale.mbtowc = __utf8_mbtowc;
170       cygheap->locale.wctomb = __utf8_wctomb;
171       strcpy (cygheap->locale.charset, "UTF-8");
172       /* Set umask to a sane default. */
173       cygheap->umask = 022;
174       cygheap->rlim_core = RLIM_INFINITY;
175     }
176   if (!cygheap->fdtab)
177     cygheap->fdtab.init ();
178   if (!cygheap->sigs)
179     sigalloc ();
180 }
181
182 /* Copyright (C) 1997, 2000 DJ Delorie */
183
184 static void *__stdcall _cmalloc (unsigned size) __attribute__ ((regparm(1)));
185 static void *__stdcall _crealloc (void *ptr, unsigned size) __attribute__ ((regparm(2)));
186
187 static void *__stdcall __attribute__ ((regparm(1)))
188 _cmalloc (unsigned size)
189 {
190   _cmalloc_entry *rvc;
191   unsigned b, sz;
192
193   /* Calculate "bit bucket" and size as a power of two. */
194   for (b = 3, sz = 8; sz && sz < size; b++, sz <<= 1)
195     continue;
196
197   cygheap_protect.acquire ();
198   if (cygheap->buckets[b])
199     {
200       rvc = (_cmalloc_entry *) cygheap->buckets[b];
201       cygheap->buckets[b] = rvc->ptr;
202       rvc->b = b;
203     }
204   else
205     {
206       rvc = (_cmalloc_entry *) _csbrk (sz + sizeof (_cmalloc_entry));
207       if (!rvc)
208         {
209           cygheap_protect.release ();
210           return NULL;
211         }
212
213       rvc->b = b;
214       rvc->prev = cygheap->chain;
215       cygheap->chain = rvc;
216     }
217   cygheap_protect.release ();
218   return rvc->data;
219 }
220
221 static void __stdcall __attribute__ ((regparm(1)))
222 _cfree (void *ptr)
223 {
224   cygheap_protect.acquire ();
225   _cmalloc_entry *rvc = to_cmalloc (ptr);
226   DWORD b = rvc->b;
227   rvc->ptr = cygheap->buckets[b];
228   cygheap->buckets[b] = (char *) rvc;
229   cygheap_protect.release ();
230 }
231
232 static void *__stdcall __attribute__ ((regparm(2)))
233 _crealloc (void *ptr, unsigned size)
234 {
235   void *newptr;
236   if (ptr == NULL)
237     newptr = _cmalloc (size);
238   else
239     {
240       unsigned oldsize = 1 << to_cmalloc (ptr)->b;
241       if (size <= oldsize)
242         return ptr;
243       newptr = _cmalloc (size);
244       if (newptr)
245         {
246           memcpy (newptr, ptr, oldsize);
247           _cfree (ptr);
248         }
249     }
250   return newptr;
251 }
252
253 /* End Copyright (C) 1997 DJ Delorie */
254
255 #define sizeof_cygheap(n) ((n) + sizeof (cygheap_entry))
256
257 #define N ((cygheap_entry *) NULL)
258 #define tocygheap(s) ((cygheap_entry *) (((char *) (s)) - (int) (N->data)))
259
260 inline static void *
261 creturn (cygheap_types x, cygheap_entry * c, unsigned len, const char *fn = NULL)
262 {
263   if (c)
264     /* nothing to do */;
265   else if (fn)
266     api_fatal ("%s would have returned NULL", fn);
267   else
268     {
269       set_errno (ENOMEM);
270       return NULL;
271     }
272   c->type = x;
273   char *cend = ((char *) c + sizeof (*c) + len);
274   if (cygheap_max < cend)
275     cygheap_max = cend;
276   MALLOC_CHECK;
277   return (void *) c->data;
278 }
279
280 inline static void *
281 cmalloc (cygheap_types x, DWORD n, const char *fn)
282 {
283   cygheap_entry *c;
284   MALLOC_CHECK;
285   c = (cygheap_entry *) _cmalloc (sizeof_cygheap (n));
286   return creturn (x, c, n, fn);
287 }
288
289 extern "C" void *
290 cmalloc (cygheap_types x, DWORD n)
291 {
292   return cmalloc (x, n, NULL);
293 }
294
295 extern "C" void *
296 cmalloc_abort (cygheap_types x, DWORD n)
297 {
298   return cmalloc (x, n, "cmalloc");
299 }
300
301 inline static void *
302 crealloc (void *s, DWORD n, const char *fn)
303 {
304   MALLOC_CHECK;
305   if (s == NULL)
306     return cmalloc (HEAP_STR, n);       // kludge
307
308   assert (!inheap (s));
309   cygheap_entry *c = tocygheap (s);
310   cygheap_types t = (cygheap_types) c->type;
311   c = (cygheap_entry *) _crealloc (c, sizeof_cygheap (n));
312   return creturn (t, c, n, fn);
313 }
314
315 extern "C" void *__stdcall  __attribute__ ((regparm(2)))
316 crealloc (void *s, DWORD n)
317 {
318   return crealloc (s, n, NULL);
319 }
320
321 extern "C" void *__stdcall  __attribute__ ((regparm(2)))
322 crealloc_abort (void *s, DWORD n)
323 {
324   return crealloc (s, n, "crealloc");
325 }
326
327 extern "C" void __stdcall __attribute__ ((regparm(1)))
328 cfree (void *s)
329 {
330   assert (!inheap (s));
331   _cfree (tocygheap (s));
332   MALLOC_CHECK;
333 }
334
335 extern "C" void __stdcall __attribute__ ((regparm(2)))
336 cfree_and_set (char *&s, char *what)
337 {
338   if (s && s != almost_null)
339     cfree (s);
340   s = what;
341 }
342
343 inline static void *
344 ccalloc (cygheap_types x, DWORD n, DWORD size, const char *fn)
345 {
346   cygheap_entry *c;
347   MALLOC_CHECK;
348   n *= size;
349   c = (cygheap_entry *) _cmalloc (sizeof_cygheap (n));
350   if (c)
351     memset (c->data, 0, n);
352   return creturn (x, c, n, fn);
353 }
354
355 extern "C" void *__stdcall __attribute__ ((regparm(3)))
356 ccalloc (cygheap_types x, DWORD n, DWORD size)
357 {
358   return ccalloc (x, n, size, NULL);
359 }
360
361 extern "C" void *__stdcall __attribute__ ((regparm(3)))
362 ccalloc_abort (cygheap_types x, DWORD n, DWORD size)
363 {
364   return ccalloc (x, n, size, "ccalloc");
365 }
366
367 extern "C" PWCHAR __stdcall __attribute__ ((regparm(1)))
368 cwcsdup (const PWCHAR s)
369 {
370   MALLOC_CHECK;
371   PWCHAR p = (PWCHAR) cmalloc (HEAP_STR, (wcslen (s) + 1) * sizeof (WCHAR));
372   if (!p)
373     return NULL;
374   wcpcpy (p, s);
375   MALLOC_CHECK;
376   return p;
377 }
378
379 extern "C" PWCHAR __stdcall __attribute__ ((regparm(1)))
380 cwcsdup1 (const PWCHAR s)
381 {
382   MALLOC_CHECK;
383   PWCHAR p = (PWCHAR) cmalloc (HEAP_1_STR, (wcslen (s) + 1) * sizeof (WCHAR));
384   if (!p)
385     return NULL;
386   wcpcpy (p, s);
387   MALLOC_CHECK;
388   return p;
389 }
390
391 extern "C" char *__stdcall __attribute__ ((regparm(1)))
392 cstrdup (const char *s)
393 {
394   MALLOC_CHECK;
395   char *p = (char *) cmalloc (HEAP_STR, strlen (s) + 1);
396   if (!p)
397     return NULL;
398   strcpy (p, s);
399   MALLOC_CHECK;
400   return p;
401 }
402
403 extern "C" char *__stdcall __attribute__ ((regparm(1)))
404 cstrdup1 (const char *s)
405 {
406   MALLOC_CHECK;
407   char *p = (char *) cmalloc (HEAP_1_STR, strlen (s) + 1);
408   if (!p)
409     return NULL;
410   strcpy (p, s);
411   MALLOC_CHECK;
412   return p;
413 }
414
415 void
416 cygheap_root::set (const char *posix, const char *native, bool caseinsensitive)
417 {
418   if (*posix == '/' && posix[1] == '\0')
419     {
420       if (m)
421         {
422           cfree (m);
423           m = NULL;
424         }
425       return;
426     }
427   if (!m)
428     m = (struct cygheap_root_mount_info *) ccalloc (HEAP_MOUNT, 1, sizeof (*m));
429   strcpy (m->posix_path, posix);
430   m->posix_pathlen = strlen (posix);
431   if (m->posix_pathlen >= 1 && m->posix_path[m->posix_pathlen - 1] == '/')
432     m->posix_path[--m->posix_pathlen] = '\0';
433
434   strcpy (m->native_path, native);
435   m->native_pathlen = strlen (native);
436   if (m->native_pathlen >= 1 && m->native_path[m->native_pathlen - 1] == '\\')
437     m->native_path[--m->native_pathlen] = '\0';
438   m->caseinsensitive = caseinsensitive;
439 }
440
441 cygheap_user::~cygheap_user ()
442 {
443 }
444
445 void
446 cygheap_user::set_name (const char *new_name)
447 {
448   bool allocated = !!pname;
449
450   if (allocated)
451     {
452       /* Windows user names are case-insensitive.  Here we want the correct
453          username, though, even if it only differs by case. */
454       if (!strcmp (new_name, pname))
455         return;
456       cfree (pname);
457     }
458
459   pname = cstrdup (new_name ? new_name : "");
460   if (!allocated)
461     return;             /* Initializing.  Don't bother with other stuff. */
462
463   cfree_and_set (homedrive);
464   cfree_and_set (homepath);
465   cfree_and_set (plogsrv);
466   cfree_and_set (pdomain);
467   cfree_and_set (pwinname);
468 }