Import Upstream version 20180207
[hcoop/debian/mlton.git] / runtime / platform / cygwin.c
1 #define _GNU_SOURCE
2
3 #include "platform.h"
4
5 #include "mmap.c"
6 #if not HAS_MSG_DONTWAIT
7 #include "recv.nonblock.c"
8 #endif
9 #include "windows.c"
10 #include "mremap.c"
11
12 /*
13 * The sysconf(_SC_PAGESIZE) is the necessary alignment for using
14 * mmap. Windows has another notion of page size (that corresponds to
15 * physical page size?). Just to be safe, we take the least common
16 * multiple of the sysconf and Windows notions of page size.
17 *
18 * Since sysconf(_SC_PAGESIZE) might not correspond to the physical
19 * page size, we can't use sysconf(_SC_PHYS_PAGES) to get physical
20 * memory. So, use the Windows function.
21 *
22 * See: http://cygwin.com/ml/cygwin/2006-06/msg00341.html
23 */
24 static size_t GC_pageSize_sysconf (void) {
25 SYSTEM_INFO sysinfo;
26 long int pageSize;
27
28 pageSize = sysconf (_SC_PAGESIZE);
29 GetSystemInfo(&sysinfo);
30
31 /* MLton_Platform_CygwinUseMmap is not set when this is called.
32 * Assume the worst; choose the larger allocation unit.
33 */
34 if ((size_t)pageSize < (size_t)sysinfo.dwAllocationGranularity)
35 return (size_t)sysinfo.dwAllocationGranularity;
36 else
37 return (size_t)pageSize;
38 }
39
40 static size_t GC_pageSize_windows (void) {
41 SYSTEM_INFO sysinfo;
42 GetSystemInfo(&sysinfo);
43 return (size_t)sysinfo.dwPageSize;
44 }
45
46 size_t GC_pageSize (void) {
47 size_t pageSize_sysconf = GC_pageSize_sysconf ();
48 size_t pageSize_windows = GC_pageSize_windows ();
49
50 size_t a = pageSize_sysconf;
51 size_t b = pageSize_windows;
52 size_t t;
53 while (b != 0) {
54 t = b;
55 b = a % b;
56 a = t;
57 }
58 size_t gcd = a;
59
60 size_t lcm = (pageSize_sysconf / gcd) * pageSize_windows;
61
62 return lcm;
63 }
64
65 uintmax_t GC_physMem (void) {
66 MEMORYSTATUS memstat;
67
68 memstat.dwLength = sizeof(memstat);
69 GlobalMemoryStatus(&memstat);
70 return (uintmax_t)memstat.dwTotalPhys;
71 }
72
73 void *GC_mmapAnon (void *start, size_t length) {
74 if (MLton_Platform_CygwinUseMmap)
75 return mmapAnon (start, length);
76 else
77 return Windows_mmapAnon (start, length);
78 }
79
80 void GC_release (void *base, size_t length) {
81 if (MLton_Platform_CygwinUseMmap)
82 munmap_safe (base, length);
83 else
84 Windows_release (base, length);
85 }
86
87 void* GC_extendHead (void *base, size_t length) {
88 if (MLton_Platform_CygwinUseMmap)
89 return mmapAnon (base, length);
90 else
91 return Windows_mmapAnon (base, length);
92 }
93
94 void* GC_extendTail (void *base, size_t length) {
95 if (MLton_Platform_CygwinUseMmap)
96 return mmapAnon (base, length);
97 else
98 return Windows_extend (base, length);
99 }
100
101 HANDLE fileDesHandle (int fd) {
102 // The temporary prevents a "cast does not match function type" warning.
103 long t;
104
105 t = get_osfhandle (fd);
106 return (HANDLE)t;
107 }
108
109 /* ------------------------------------------------- */
110 /* Cygwin */
111 /* ------------------------------------------------- */
112
113 C_String_t Cygwin_toFullWindowsPath (NullString8_t path) {
114 static char res[MAX_PATH];
115
116 #if ((CYGWIN_VERSION_API_MAJOR > 0) || (CYGWIN_VERSION_API_MINOR > 181))
117 cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE,
118 (char*)path, &res[0], MAX_PATH);
119 #else
120 cygwin_conv_to_full_win32_path ((char*)path, &res[0]);
121 #endif
122 return (C_String_t)&res[0];
123 }
124
125 /* ------------------------------------------------- */
126 /* Posix */
127 /* ------------------------------------------------- */
128
129 void Posix_IO_setbin (C_Fd_t fd) {
130 /* cygwin has a different method for working with its fds */
131 setmode (fd, O_BINARY);
132 }
133
134 void Posix_IO_settext (C_Fd_t fd) {
135 /* cygwin has a different method for working with its fds */
136 setmode (fd, O_TEXT);
137 }