forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			177 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C
		
	
	
	
/*
 | 
						|
 * This code is derived from uClibc (original license follows).
 | 
						|
 * https://git.uclibc.org/uClibc/tree/utils/mmap-windows.c
 | 
						|
 */
 | 
						|
 /* mmap() replacement for Windows
 | 
						|
 *
 | 
						|
 * Author: Mike Frysinger <vapier@gentoo.org>
 | 
						|
 * Placed into the public domain
 | 
						|
 */
 | 
						|
 | 
						|
/* References:
 | 
						|
 * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx
 | 
						|
 * CloseHandle:       http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx
 | 
						|
 * MapViewOfFile:     http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx
 | 
						|
 * UnmapViewOfFile:   http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx
 | 
						|
 */
 | 
						|
 | 
						|
#if defined(_WIN32)
 | 
						|
 | 
						|
#include "WindowsMMap.h"
 | 
						|
 | 
						|
#define WIN32_LEAN_AND_MEAN
 | 
						|
#include <windows.h>
 | 
						|
 | 
						|
#include "InstrProfiling.h"
 | 
						|
 | 
						|
COMPILER_RT_VISIBILITY
 | 
						|
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
 | 
						|
{
 | 
						|
  if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC))
 | 
						|
    return MAP_FAILED;
 | 
						|
  if (fd == -1) {
 | 
						|
    if (!(flags & MAP_ANON) || offset)
 | 
						|
      return MAP_FAILED;
 | 
						|
  } else if (flags & MAP_ANON)
 | 
						|
    return MAP_FAILED;
 | 
						|
 | 
						|
  DWORD flProtect;
 | 
						|
  if (prot & PROT_WRITE) {
 | 
						|
    if (prot & PROT_EXEC)
 | 
						|
      flProtect = PAGE_EXECUTE_READWRITE;
 | 
						|
    else
 | 
						|
      flProtect = PAGE_READWRITE;
 | 
						|
  } else if (prot & PROT_EXEC) {
 | 
						|
    if (prot & PROT_READ)
 | 
						|
      flProtect = PAGE_EXECUTE_READ;
 | 
						|
    else if (prot & PROT_EXEC)
 | 
						|
      flProtect = PAGE_EXECUTE;
 | 
						|
  } else
 | 
						|
    flProtect = PAGE_READONLY;
 | 
						|
 | 
						|
  off_t end = length + offset;
 | 
						|
  HANDLE mmap_fd, h;
 | 
						|
  if (fd == -1)
 | 
						|
    mmap_fd = INVALID_HANDLE_VALUE;
 | 
						|
  else
 | 
						|
    mmap_fd = (HANDLE)_get_osfhandle(fd);
 | 
						|
  h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL);
 | 
						|
  if (h == NULL)
 | 
						|
    return MAP_FAILED;
 | 
						|
 | 
						|
  DWORD dwDesiredAccess;
 | 
						|
  if (prot & PROT_WRITE)
 | 
						|
    dwDesiredAccess = FILE_MAP_WRITE;
 | 
						|
  else
 | 
						|
    dwDesiredAccess = FILE_MAP_READ;
 | 
						|
  if (prot & PROT_EXEC)
 | 
						|
    dwDesiredAccess |= FILE_MAP_EXECUTE;
 | 
						|
  if (flags & MAP_PRIVATE)
 | 
						|
    dwDesiredAccess |= FILE_MAP_COPY;
 | 
						|
  void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length);
 | 
						|
  if (ret == NULL) {
 | 
						|
    CloseHandle(h);
 | 
						|
    ret = MAP_FAILED;
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
COMPILER_RT_VISIBILITY
 | 
						|
void munmap(void *addr, size_t length)
 | 
						|
{
 | 
						|
  UnmapViewOfFile(addr);
 | 
						|
  /* ruh-ro, we leaked handle from CreateFileMapping() ... */
 | 
						|
}
 | 
						|
 | 
						|
COMPILER_RT_VISIBILITY
 | 
						|
int msync(void *addr, size_t length, int flags)
 | 
						|
{
 | 
						|
  if (flags & MS_INVALIDATE)
 | 
						|
    return -1; /* Not supported. */
 | 
						|
 | 
						|
  /* Exactly one of MS_ASYNC or MS_SYNC must be specified. */
 | 
						|
  switch (flags & (MS_ASYNC | MS_SYNC)) {
 | 
						|
    case MS_SYNC:
 | 
						|
    case MS_ASYNC:
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!FlushViewOfFile(addr, length))
 | 
						|
    return -1;
 | 
						|
 | 
						|
  if (flags & MS_SYNC) {
 | 
						|
    /* FIXME: No longer have access to handle from CreateFileMapping(). */
 | 
						|
    /*
 | 
						|
     * if (!FlushFileBuffers(h))
 | 
						|
     *   return -1;
 | 
						|
     */
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
COMPILER_RT_VISIBILITY
 | 
						|
int lock(HANDLE handle, DWORD lockType, BOOL blocking) {
 | 
						|
  DWORD flags = lockType;
 | 
						|
  if (!blocking)
 | 
						|
    flags |= LOCKFILE_FAIL_IMMEDIATELY;
 | 
						|
 | 
						|
  OVERLAPPED overlapped;
 | 
						|
  ZeroMemory(&overlapped, sizeof(OVERLAPPED));
 | 
						|
  overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
 | 
						|
  BOOL result = LockFileEx(handle, flags, 0, MAXDWORD, MAXDWORD, &overlapped);
 | 
						|
  if (!result) {
 | 
						|
    DWORD dw = GetLastError();
 | 
						|
 | 
						|
    // In non-blocking mode, return an error if the file is locked.
 | 
						|
    if (!blocking && dw == ERROR_LOCK_VIOLATION)
 | 
						|
      return -1; // EWOULDBLOCK
 | 
						|
 | 
						|
    // If the error is ERROR_IO_PENDING, we need to wait until the operation
 | 
						|
    // finishes. Otherwise, we return an error.
 | 
						|
    if (dw != ERROR_IO_PENDING)
 | 
						|
      return -1;
 | 
						|
 | 
						|
    DWORD dwNumBytes;
 | 
						|
    if (!GetOverlappedResult(handle, &overlapped, &dwNumBytes, TRUE))
 | 
						|
      return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
COMPILER_RT_VISIBILITY
 | 
						|
int flock(int fd, int operation) {
 | 
						|
  HANDLE handle = (HANDLE)_get_osfhandle(fd);
 | 
						|
  if (handle == INVALID_HANDLE_VALUE)
 | 
						|
    return -1;
 | 
						|
 | 
						|
  BOOL blocking = (operation & LOCK_NB) == 0;
 | 
						|
  int op = operation & ~LOCK_NB;
 | 
						|
 | 
						|
  switch (op) {
 | 
						|
  case LOCK_EX:
 | 
						|
    return lock(handle, LOCKFILE_EXCLUSIVE_LOCK, blocking);
 | 
						|
 | 
						|
  case LOCK_SH:
 | 
						|
    return lock(handle, 0, blocking);
 | 
						|
 | 
						|
  case LOCK_UN:
 | 
						|
    if (!UnlockFile(handle, 0, 0, MAXDWORD, MAXDWORD))
 | 
						|
      return -1;
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    return -1;
 | 
						|
  }
 | 
						|
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
#undef DWORD_HI
 | 
						|
#undef DWORD_LO
 | 
						|
 | 
						|
#endif /* _WIN32 */
 |