]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/heap.cc
* environ.cc (environ_init): Avoid a compiler warning.
[newlib-cygwin.git] / winsup / cygwin / heap.cc
1 /* heap.cc: Cygwin heap manager.
2
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
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 "cygerrno.h"
14 #include "sigproc.h"
15 #include "pinfo.h"
16 #include "heap.h"
17 #include "shared_info.h"
18 #include "security.h"
19 #include "fhandler.h"
20 #include "path.h"
21 #include "dtable.h"
22 #include "cygheap.h"
23
24 #define assert(x)
25
26 static unsigned page_const;
27
28 extern "C" size_t getpagesize ();
29
30 /* Initialize the heap at process start up. */
31
32 void
33 heap_init ()
34 {
35 /* If we're the forkee, we must allocate the heap at exactly the same place
36 as our parent. If not, we don't care where it ends up. */
37
38 page_const = system_info.dwPageSize;
39 if (cygheap->heapbase)
40 {
41 DWORD chunk = cygwin_shared->heap_chunk_size (); /* allocation chunk */
42 /* total size commited in parent */
43 DWORD allocsize = (char *) cygheap->heaptop - (char *) cygheap->heapbase;
44 /* round up by chunk size */
45 DWORD reserve_size = chunk * ((allocsize + (chunk - 1)) / chunk);
46
47 /* Loop until we've managed to reserve an adequate amount of memory. */
48 char *p;
49 for (;;)
50 {
51 p = (char *) VirtualAlloc (cygheap->heapbase, reserve_size,
52 MEM_RESERVE, PAGE_READWRITE);
53 if (p)
54 break;
55 if ((reserve_size -= page_const) <= allocsize)
56 break;
57 }
58 if (p == NULL)
59 api_fatal ("1. unable to allocate heap %p, heap_chunk_size %d, pid %d, %E",
60 cygheap->heapbase, cygwin_shared->heap_chunk_size (), myself->pid);
61 if (p != cygheap->heapbase)
62 api_fatal ("heap allocated but not at %p", cygheap->heapbase);
63 if (! VirtualAlloc (cygheap->heapbase, allocsize, MEM_COMMIT, PAGE_READWRITE))
64 api_fatal ("MEM_COMMIT failed, %E");
65 }
66 else
67 {
68 /* Initialize page mask and default heap size. Preallocate a heap
69 * to assure contiguous memory. */
70 cygheap->heapptr = cygheap->heaptop = cygheap->heapbase =
71 VirtualAlloc (NULL, cygwin_shared->heap_chunk_size (), MEM_RESERVE,
72 PAGE_NOACCESS);
73 if (cygheap->heapbase == NULL)
74 api_fatal ("2. unable to allocate heap, heap_chunk_size %d, %E",
75 cygwin_shared->heap_chunk_size ());
76 }
77
78 debug_printf ("heap base %p, heap top %p", cygheap->heapbase,
79 cygheap->heaptop);
80 page_const--;
81 malloc_init ();
82 }
83
84 #define pround(n) (((size_t)(n) + page_const) & ~page_const)
85
86 /* FIXME: This function no longer handles "split heaps". */
87
88 extern "C" void *
89 _sbrk (int n)
90 {
91 sigframe thisframe (mainthread);
92 char *newtop, *newbrk;
93 unsigned commitbytes, newbrksize;
94
95 if (n == 0)
96 return cygheap->heapptr; /* Just wanted to find current cygheap->heapptr address */
97
98 newbrk = (char *) cygheap->heapptr + n; /* Where new cygheap->heapptr will be */
99 newtop = (char *) pround (newbrk); /* Actual top of allocated memory -
100 on page boundary */
101
102 if (newtop == cygheap->heaptop)
103 goto good;
104
105 if (n < 0)
106 { /* Freeing memory */
107 assert (newtop < cygheap->heaptop);
108 n = (char *) cygheap->heaptop - newtop;
109 if (VirtualFree (newtop, n, MEM_DECOMMIT)) /* Give it back to OS */
110 goto good; /* Didn't take */
111 else
112 goto err;
113 }
114
115 assert (newtop > cygheap->heaptop);
116
117 /* Need to grab more pages from the OS. If this fails it may be because
118 * we have used up previously reserved memory. Or, we're just plumb out
119 * of memory. */
120 commitbytes = pround (newtop - (char *) cygheap->heaptop);
121 if (VirtualAlloc (cygheap->heaptop, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL)
122 goto good;
123
124 /* Couldn't allocate memory. Maybe we can reserve some more.
125 Reserve either the maximum of the standard cygwin_shared->heap_chunk_size () or the requested
126 amount. Then attempt to actually allocate it. */
127
128 if ((newbrksize = cygwin_shared->heap_chunk_size ()) < commitbytes)
129 newbrksize = commitbytes;
130
131 if ((VirtualAlloc (cygheap->heaptop, newbrksize, MEM_RESERVE, PAGE_NOACCESS) != NULL) &&
132 (VirtualAlloc (cygheap->heaptop, commitbytes, MEM_COMMIT, PAGE_READWRITE) != NULL))
133 goto good;
134
135 err:
136 set_errno (ENOMEM);
137 return (void *) -1;
138
139 good:
140 void *oldbrk = cygheap->heapptr;
141 cygheap->heapptr = newbrk;
142 cygheap->heaptop = newtop;
143 return oldbrk;
144 }
This page took 0.044643 seconds and 5 git commands to generate.