OSDN Git Service

* times.cc (hires::prime): Restore thread priority on failure condition.
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / how-cygheap-works.txt
1 Copyright 2001 Red Hat Inc., Christopher Faylor
2
3 Cygwin has recently adopted something called the "cygwin heap".  This is
4 an internal heap that is inherited by forked/execed children.  It
5 consists of process specific information that should be inherited.  So
6 things like the file descriptor table, the current working directory,
7 and the chroot value live there.
8
9 The cygheap is also used to pass argv information to a child process.
10 There is a problem here, though.  If you allocate space for argv on the
11 heap and then exec a process the child process (1) will happily use the
12 space in the heap.  But what happens when that process execs another
13 process (2)?  The space used by child process (1) still is being used in
14 child process (2) but it is basically just a memory leak.
15
16 To rectify this problem, memory used by child process 1 is tagged in
17 such a way that child process 2 will know to delete it.  This is in
18 cygheap_fixup_in_child.
19
20 The cygheap memory allocation functions are adapted from memory
21 allocators developed by DJ Delorie.  They are similar to early BSD
22 malloc and are intended to be relatively lightweight and relatively
23 fast.
24
25 How is the cygheap propagated to the child?
26
27 Well, it depends if you are running on Windows 9x or Windows NT.
28
29 On NT and 9x, just before CreateProcess is about to be called in
30 fork or exec, a shared memory region is prepared for copying of the
31 cygwin heap.  This is in cygheap_setup_for_child.  The handle to this
32 shared memory region is passed to the new process in the 'child_info'
33 structure.
34
35 If there are no handles that need "fixing up" prior to starting another
36 process, cygheap_setup_for_child will also copy the contents of the
37 cygwin heap to the shared memory region.
38
39 If there are any handles that need "fixing up" prior to invoking
40 another process (i.e., sockets) then the creation of the shared
41 memory region and copying of the current cygwin heap is a two
42 step process.
43
44 First the shared memory region is created and the process is started
45 in a "CREATE_SUSPENDED" state, inheriting the handle.  After the
46 process is created, the fixup_before_*() functions are called.  These
47 set information in the heap and duplicate handles in the child, essentially
48 ensuring that the child's fd table is correct.
49
50 (Note that it is vital that the cygwin heap should not grow during this
51 process.  Currently, there is no guard against this happening so this
52 operation is not thread safe.)
53
54 Meanwhile, back in fork_parent, the function
55 cygheap_setup_for_child_cleanup is called.  In the simple "one step"
56 case above, all that happens is that the shared memory is ummapped and
57 the handle referring to it is closed.
58
59 In the two step process, the cygheap is now copied to the shared memory
60 region, complete with new fdtab info (the child process will see the
61 updated information as soon as it starts).  Then the memory is unmapped,
62 the handle is closed, and upon return the child process is started.
63
64 It is in the child process that the difference between Windows 9x and
65 Windows NT becomes evident.
66
67 Under Windows NT, the operation is simple.  The shared memory handle is
68 used to map the information that the parent has set up into the cygheap
69 location in the child.  This means that the child has a copy of the
70 cygwin heap existing in "shared memory" but the only process with a view
71 to this "shared memory" is the child.
72
73 Under Windows 9x, due to address limitations, we can't just map the
74 shared memory region into the cygheap position.  So, instead, the memory
75 is mapped whereever Windows wants to put it, a new heap region is
76 allocated at the same place as in the parent, the contents of the shared
77 memory is *copied* to the new heap, and the shared memory is unmapped.
78 Simple, huh?
79
80 Why do we go to these contortions?  Previous versions (<1.3.3) of cygwin
81 used to block when creating a child so that the child could copy the
82 parent's cygheap.  The problem with this was that when a cygwin process
83 invoked a non-cygwin child, it would block forever waiting for the child
84 to let it know that it was done copying the heap.  That caused
85 understandable complaints from people who wanted to run non-cygwin
86 applications "in the background".
87
88 In Cygwin 1.3.3 (and presumably beyond) the location of the cygwin heap
89 has been fixed to be at the end of the cygwin1.dll address space.
90 Previously, we let the "OS" choose where to allocate the cygwin heap in
91 the initial cygwin process and attempted to use this same location in
92 subsequent cygwin processes started from this parent.
93
94 The reason for putting cygheap at a fixed, known location is that we
95 need to put this information at a fixed location since it incorporates
96 pointers to entities within itself.  So, when a process forks or execs,
97 the memory referred to by the pointers has to exist at the same place in
98 both the parent or the child.
99
100 (It "might be nice" to used something like Microsoft's "based pointers"
101 for the cygheap.  Unfortunately gcc does not support that feature, as of
102 this writing.)
103
104 The reason for choosing a fixed, arbitrary location is to accommodate
105 Windows XP, although there were sporadic complaints of cygwin heap
106 failures in other pathological situations with both NT and 9x.  In
107 Windows XP, Microsoft made the allocation of memory less deterministic.
108 This is certainly their right.  Cygwin was previously relying on
109 undocumented and "iffy" behavior before.  So, now we always allocate
110 space immediately after the dll in the theory that there is not going
111 to be anything else living there.
112
113 Recent (2001-09-20) cygwin email threads have indicated that we're not
114 exactly on completely firm ground now, though.  We are assuming that
115 there is sufficient space after the cygwin DLL for the allocation of the
116 cygwin heap.  Unfortunately the ld option '--enable-auto-image-base'
117 has a tendency to allocate DLLs immediately after cygwin1.dll.  This
118 causes the dreaded "Couldn't reserve space for cygwin's heap" message.
119
120 Solutions for this behavior are currently in the musing state.