Cygwin: sched_setscheduler: allow changes of the priority
[newlib-cygwin.git] / winsup / cygwin / mm / shared.cc
blob7977df382a350b54c339edb332bb55b5e0059f4f
1 /* shared.cc: shared data area support.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
9 #include "winsup.h"
10 #include "miscfuncs.h"
11 #include <unistd.h>
12 #include "cygerrno.h"
13 #include "pinfo.h"
14 #include "path.h"
15 #include "fhandler.h"
16 #include "dtable.h"
17 #include "cygheap.h"
18 #include "heap.h"
19 #include "shared_info_magic.h"
20 #include "registry.h"
21 #include "cygwin_version.h"
22 #include "memory_layout.h"
23 #include "spinlock.h"
24 #include <alloca.h>
25 #include <wchar.h>
27 shared_info NO_COPY *cygwin_shared;
28 user_info NO_COPY *user_shared;
29 HANDLE NO_COPY cygwin_shared_h;
30 HANDLE NO_COPY cygwin_user_h;
32 /* This function returns a handle to the top-level directory in the global
33 NT namespace used to implement global objects including shared memory. */
35 static HANDLE NO_COPY shared_parent_dir;
37 HANDLE
38 get_shared_parent_dir ()
40 UNICODE_STRING uname;
41 OBJECT_ATTRIBUTES attr;
42 NTSTATUS status;
44 if (!shared_parent_dir)
46 WCHAR bnoname[MAX_PATH];
47 __small_swprintf (bnoname, L"\\BaseNamedObjects\\%s%s-%S",
48 cygwin_version.shared_id,
49 _cygwin_testing ? cygwin_version.dll_build_date : "",
50 &cygheap->installation_key);
51 RtlInitUnicodeString (&uname, bnoname);
52 InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF, NULL,
53 everyone_sd (CYG_SHARED_DIR_ACCESS));
54 status = NtCreateDirectoryObject (&shared_parent_dir,
55 CYG_SHARED_DIR_ACCESS, &attr);
56 if (!NT_SUCCESS (status))
57 api_fatal ("NtCreateDirectoryObject(%S): %y", &uname, status);
59 return shared_parent_dir;
62 static HANDLE NO_COPY session_parent_dir;
64 HANDLE
65 get_session_parent_dir ()
67 UNICODE_STRING uname;
68 OBJECT_ATTRIBUTES attr;
69 NTSTATUS status;
71 if (!session_parent_dir)
73 PROCESS_SESSION_INFORMATION psi;
74 status = NtQueryInformationProcess (NtCurrentProcess (),
75 ProcessSessionInformation,
76 &psi, sizeof psi, NULL);
77 if (!NT_SUCCESS (status) || psi.SessionId == 0)
78 session_parent_dir = get_shared_parent_dir ();
79 else
81 WCHAR bnoname[MAX_PATH];
82 __small_swprintf (bnoname,
83 L"\\Sessions\\BNOLINKS\\%d\\%s%s-%S",
84 psi.SessionId, cygwin_version.shared_id,
85 _cygwin_testing ? cygwin_version.dll_build_date : "",
86 &cygheap->installation_key);
87 RtlInitUnicodeString (&uname, bnoname);
88 InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF, NULL,
89 everyone_sd(CYG_SHARED_DIR_ACCESS));
90 status = NtCreateDirectoryObject (&session_parent_dir,
91 CYG_SHARED_DIR_ACCESS, &attr);
92 if (!NT_SUCCESS (status))
93 api_fatal ("NtCreateDirectoryObject(%S): %y", &uname, status);
96 return session_parent_dir;
99 char *
100 shared_name (char *ret_buf, const char *str, int num)
102 __small_sprintf (ret_buf, "%s.%d", str, num);
103 return ret_buf;
106 WCHAR *
107 shared_name (WCHAR *ret_buf, const WCHAR *str, int num)
109 __small_swprintf (ret_buf, L"%W.%d", str, num);
110 return ret_buf;
113 #define page_const ((ptrdiff_t) 65535)
114 #define pround(n) ((ptrdiff_t)(((n) + page_const) & ~page_const))
116 static NO_COPY uintptr_t next_address = SHARED_REGIONS_ADDRESS_LOW;
118 void *
119 open_shared (const WCHAR *name, int n, HANDLE& shared_h, DWORD size,
120 shared_locations m, PSECURITY_ATTRIBUTES psa, DWORD access)
122 bool created_dummy;
123 return open_shared (name, n, shared_h, size, m, created_dummy, psa, access);
126 void *
127 open_shared (const WCHAR *name, int n, HANDLE& shared_h, DWORD size,
128 shared_locations m, bool &created, PSECURITY_ATTRIBUTES psa,
129 DWORD access)
131 WCHAR map_buf[MAX_PATH];
132 WCHAR *mapname = NULL;
133 void *shared;
134 void *addr;
136 created = false;
137 if (!shared_h)
139 if (name)
140 mapname = shared_name (map_buf, name, n);
141 if (m == SH_JUSTOPEN)
142 shared_h = OpenFileMappingW (access, FALSE, mapname);
143 else
145 created = true;
146 shared_h = CreateFileMappingW (INVALID_HANDLE_VALUE, psa,
147 PAGE_READWRITE, 0, size, mapname);
148 if (GetLastError () == ERROR_ALREADY_EXISTS)
149 created = false;
151 if (shared_h)
152 /* ok! */;
153 else if (m != SH_JUSTOPEN)
154 api_fatal ("CreateFileMapping %W, %E. Terminating.", mapname);
155 else
156 return NULL;
159 /* Locate shared regions in the area between SHARED_REGIONS_ADDRESS_LOW
160 and SHARED_REGIONS_ADDRESS_HIGH, retrying until we have a slot.
161 Don't use MapViewOfFile3 (STATUS_DLL_INIT_FAILED during fork). */
162 bool loop = false;
166 addr = (void *) next_address;
167 shared = MapViewOfFileEx (shared_h, access, 0, 0, 0, addr);
168 next_address += wincap.allocation_granularity ();
169 if (next_address >= SHARED_REGIONS_ADDRESS_HIGH)
171 if (!shared && loop)
172 break;
173 next_address = SHARED_REGIONS_ADDRESS_LOW;
174 loop = true;
177 while (!shared);
179 if (!shared)
180 api_fatal ("MapViewOfFileEx '%W'(%p, size %u, m %d, created %d), %E. "
181 "Terminating.", mapname, shared_h, size, m, created);
183 debug_printf ("name %W, shared %p (wanted %p), h %p, m %d, created %d",
184 mapname, shared, addr, shared_h, m, created);
186 return shared;
189 /* Second half of user shared initialization: Initialize content. */
190 void
191 user_info::initialize ()
193 /* Wait for initialization of the Cygwin per-user shared, if necessary */
194 spinlock sversion (version, CURR_USER_MAGIC);
195 if (!sversion)
197 cb = sizeof (*user_shared);
198 /* Initialize mount table from system fstab prior to calling
199 internal_getpwsid. This allows to convert pw_dir and pw_shell
200 paths given in DOS notation to valid POSIX paths. */
201 mountinfo.init (false);
202 cygpsid sid (cygheap->user.sid ());
203 struct passwd *pw = internal_getpwsid (sid);
204 /* Correct the user name with what's defined in /etc/passwd before
205 loading the user fstab file. */
206 if (pw)
207 cygheap->user.set_name (pw->pw_name);
208 /* After fetching the user infos, add mount entries from user's fstab. */
209 mountinfo.init (true);
211 else if (sversion != CURR_USER_MAGIC)
212 sversion.multiple_cygwin_problem ("user shared memory version", version,
213 sversion);
214 else if (user_shared->cb != sizeof (*user_shared))
215 sversion.multiple_cygwin_problem ("user shared memory size", cb,
216 sizeof (*user_shared));
219 /* First half of user shared initialization: Create shared mem region. */
220 void
221 user_info::create (bool reinit)
223 WCHAR name[UNLEN + 1] = L""; /* Large enough for SID */
225 if (reinit)
227 if (!UnmapViewOfFile (user_shared))
228 debug_printf("UnmapViewOfFile %E");
229 if (!ForceCloseHandle (cygwin_user_h))
230 debug_printf("CloseHandle %E");
231 cygwin_user_h = NULL;
234 if (!cygwin_user_h)
235 cygheap->user.get_windows_id (name);
237 user_shared = (user_info *) open_shared (name, USER_VERSION,
238 cygwin_user_h, sizeof (user_info),
239 SH_USER_SHARED, &sec_none);
240 debug_printf ("opening user shared for '%W' at %p", name, user_shared);
241 ProtectHandleINH (cygwin_user_h);
242 debug_printf ("user shared version %x", user_shared->version);
243 if (reinit)
244 user_shared->initialize ();
245 cygheap->shared_regions.user_shared_addr = user_shared;
248 void
249 shared_destroy ()
251 ForceCloseHandle (cygwin_shared_h);
252 UnmapViewOfFile (cygwin_shared);
253 ForceCloseHandle (cygwin_user_h);
254 UnmapViewOfFile (user_shared);
257 /* Initialize obcaseinsensitive.*/
258 void
259 shared_info::init_obcaseinsensitive ()
261 /* Instead of reading the obcaseinsensitive registry value, test the
262 actual state of case sensitivity handling in the kernel. */
263 UNICODE_STRING sysroot;
264 OBJECT_ATTRIBUTES attr;
265 HANDLE h;
267 RtlInitUnicodeString (&sysroot, L"\\SYSTEMROOT");
268 InitializeObjectAttributes (&attr, &sysroot, 0, NULL, NULL);
269 /* NtOpenSymbolicLinkObject returns STATUS_ACCESS_DENIED when called
270 with a 0 access mask. However, if the kernel is case sensitive,
271 it returns STATUS_OBJECT_NAME_NOT_FOUND because we used the incorrect
272 case for the filename (It's actually "\\SystemRoot"). */
273 obcaseinsensitive = NtOpenSymbolicLinkObject (&h, 0, &attr)
274 != STATUS_OBJECT_NAME_NOT_FOUND;
277 void inline
278 shared_info::create ()
280 cygwin_shared = (shared_info *) open_shared (L"shared",
281 CYGWIN_VERSION_SHARED_DATA,
282 cygwin_shared_h,
283 sizeof (*cygwin_shared),
284 SH_CYGWIN_SHARED,
285 &sec_all_nih);
286 cygwin_shared->initialize ();
287 cygheap->shared_regions.cygwin_shared_addr = cygwin_shared;
290 void
291 shared_info::initialize ()
293 spinlock sversion (version, CURR_SHARED_MAGIC);
294 if (!sversion)
296 LUID luid;
298 cb = sizeof (*this);
299 get_session_parent_dir (); /* Create session dir if first process. */
300 init_obcaseinsensitive (); /* Initialize obcaseinsensitive */
301 tty.init (); /* Initialize tty table */
302 mt.initialize (); /* Initialize shared tape information */
303 loadavg.initialize (); /* Initialize loadavg information */
304 NtAllocateLocallyUniqueId (&luid);/* Initialize pid_src to a low */
305 InterlockedExchange (&pid_src, /* random value to make start pid */
306 luid.LowPart % 2048);/* less predictably */
307 forkable_hardlink_support = 0; /* 0: Unknown, 1: Yes, -1: No */
308 /* Defer debug output printing the installation root and installation key
309 up to this point. Debug output except for system_printf requires
310 the global shared memory to exist. */
311 debug_printf ("Installation root: <%W> key: <%S>",
312 cygheap->installation_root, &cygheap->installation_key);
314 else if (sversion != CURR_SHARED_MAGIC)
315 sversion.multiple_cygwin_problem ("system shared memory version",
316 sversion, CURR_SHARED_MAGIC);
317 else if (cb != sizeof (*this))
318 system_printf ("size of shared memory region changed from %lu to %u",
319 sizeof (*this), cb);
322 void
323 memory_init ()
325 shared_info::create (); /* Initialize global shared memory */
326 cygheap->user_heap.init (); /* Initialize user heap */
327 user_info::create (false); /* Initialize per-user shared memory */
328 /* Initialize tty list session stuff. Doesn't really belong here but
329 this needs to be initialized before any tty or console manipulation
330 happens and it is a common location. */
331 tty_list::init_session ();