llvm-project

Форк
0
187 строк · 4.4 Кб
1
/*
2
 * This code is derived from uClibc (original license follows).
3
 * https://git.uclibc.org/uClibc/tree/utils/mmap-windows.c
4
 */
5
 /* mmap() replacement for Windows
6
 *
7
 * Author: Mike Frysinger <vapier@gentoo.org>
8
 * Placed into the public domain
9
 */
10

11
/* References:
12
 * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
13
 * CloseHandle:       http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
14
 * MapViewOfFile:     http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
15
 * UnmapViewOfFile:   http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
16
 */
17

18
#if defined(_WIN32)
19

20
#include "WindowsMMap.h"
21

22
#define WIN32_LEAN_AND_MEAN
23
#include <windows.h>
24

25
#include "InstrProfiling.h"
26

27
COMPILER_RT_VISIBILITY
28
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
29
{
30
  if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
31
    return MAP_FAILED;
32
  if (fd == -1) {
33
    if (!(flags & MAP_ANON) || offset)
34
      return MAP_FAILED;
35
  } else if (flags & MAP_ANON)
36
    return MAP_FAILED;
37

38
  DWORD flProtect;
39
  if (prot & PROT_WRITE) {
40
    if (prot & PROT_EXEC)
41
      flProtect = PAGE_EXECUTE_READWRITE;
42
    else
43
      flProtect = PAGE_READWRITE;
44
  } else if (prot & PROT_EXEC) {
45
    if (prot & PROT_READ)
46
      flProtect = PAGE_EXECUTE_READ;
47
    else if (prot & PROT_EXEC)
48
      flProtect = PAGE_EXECUTE;
49
  } else
50
    flProtect = PAGE_READONLY;
51

52
  off_t end = length + offset;
53
  HANDLE mmap_fd, h;
54
  if (fd == -1)
55
    mmap_fd = INVALID_HANDLE_VALUE;
56
  else
57
    mmap_fd = (HANDLE)_get_osfhandle(fd);
58
  h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL);
59
  if (h == NULL)
60
    return MAP_FAILED;
61

62
  DWORD dwDesiredAccess;
63
  if (prot & PROT_WRITE)
64
    dwDesiredAccess = FILE_MAP_WRITE;
65
  else
66
    dwDesiredAccess = FILE_MAP_READ;
67
  if (prot & PROT_EXEC)
68
    dwDesiredAccess |= FILE_MAP_EXECUTE;
69
  if (flags & MAP_PRIVATE)
70
    dwDesiredAccess |= FILE_MAP_COPY;
71
  void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length);
72
  if (ret == NULL) {
73
    CloseHandle(h);
74
    ret = MAP_FAILED;
75
  }
76
  return ret;
77
}
78

79
COMPILER_RT_VISIBILITY
80
void munmap(void *addr, size_t length)
81
{
82
  UnmapViewOfFile(addr);
83
  /* ruh-ro, we leaked handle from CreateFileMapping() ... */
84
}
85

86
COMPILER_RT_VISIBILITY
87
int msync(void *addr, size_t length, int flags)
88
{
89
  if (flags & MS_INVALIDATE)
90
    return -1; /* Not supported. */
91

92
  /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */
93
  switch (flags & (MS_ASYNC | MS_SYNC)) {
94
    case MS_SYNC:
95
    case MS_ASYNC:
96
      break;
97
    default:
98
      return -1;
99
  }
100

101
  if (!FlushViewOfFile(addr, length))
102
    return -1;
103

104
  if (flags & MS_SYNC) {
105
    /* FIXME: No longer have access to handle from CreateFileMapping(). */
106
    /*
107
     * if (!FlushFileBuffers(h))
108
     *   return -1;
109
     */
110
  }
111

112
  return 0;
113
}
114

115
COMPILER_RT_VISIBILITY
116
int madvise(void *addr, size_t length, int advice)
117
{
118
  if (advice != MADV_DONTNEED)
119
    return -1; /* Not supported. */
120

121
  if (!VirtualUnlock(addr, length))
122
    return -1;
123

124
  return 0;
125
}
126

127
static int lock(HANDLE handle, DWORD lockType, BOOL blocking) {
128
  DWORD flags = lockType;
129
  if (!blocking)
130
    flags |= LOCKFILE_FAIL_IMMEDIATELY;
131

132
  OVERLAPPED overlapped;
133
  ZeroMemory(&overlapped, sizeof(OVERLAPPED));
134
  overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
135
  BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped);
136
  if (!result) {
137
    DWORD dw = GetLastError();
138

139
    // In non-blocking mode, return an error if the file is locked.
140
    if (!blocking && dw == ERROR_LOCK_VIOLATION)
141
      return -1; // EWOULDBLOCK
142

143
    // If the error is ERROR_IO_PENDING, we need to wait until the operation
144
    // finishes. Otherwise, we return an error.
145
    if (dw != ERROR_IO_PENDING)
146
      return -1;
147

148
    DWORD dwNumBytes;
149
    if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE))
150
      return -1;
151
  }
152

153
  return 0;
154
}
155

156
COMPILER_RT_VISIBILITY
157
int flock(int fd, int operation) {
158
  HANDLE handle = (HANDLE)_get_osfhandle(fd);
159
  if (handle == INVALID_HANDLE_VALUE)
160
    return -1;
161

162
  BOOL blocking = (operation & LOCK_NB) == 0;
163
  int op = operation & ~LOCK_NB;
164

165
  switch (op) {
166
  case LOCK_EX:
167
    return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking);
168

169
  case LOCK_SH:
170
    return lock(handle, 0, blocking);
171

172
  case LOCK_UN:
173
    if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD))
174
      return -1;
175
    break;
176

177
  default:
178
    return -1;
179
  }
180

181
  return 0;
182
}
183

184
#undef DWORD_HI
185
#undef DWORD_LO
186

187
#endif /* _WIN32 */
188

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.