Add support for the IO manager thread on Windows
[ghc-base.git] / cbits / Win32Utils.c
diff --git a/cbits/Win32Utils.c b/cbits/Win32Utils.c
new file mode 100644 (file)
index 0000000..dca270a
--- /dev/null
@@ -0,0 +1,121 @@
+/* ----------------------------------------------------------------------------\r
+   (c) The University of Glasgow 2006\r
+   \r
+   Useful Win32 bits\r
+   ------------------------------------------------------------------------- */\r
+\r
+#include "HsBase.h"\r
+\r
+/* This is the error table that defines the mapping between OS error\r
+   codes and errno values */\r
+\r
+struct errentry {\r
+        unsigned long oscode;           /* OS return value */\r
+        int errnocode;  /* System V error code */\r
+};\r
+\r
+static struct errentry errtable[] = {\r
+        {  ERROR_INVALID_FUNCTION,       EINVAL    },  /* 1 */\r
+        {  ERROR_FILE_NOT_FOUND,         ENOENT    },  /* 2 */\r
+        {  ERROR_PATH_NOT_FOUND,         ENOENT    },  /* 3 */\r
+        {  ERROR_TOO_MANY_OPEN_FILES,    EMFILE    },  /* 4 */\r
+        {  ERROR_ACCESS_DENIED,          EACCES    },  /* 5 */\r
+        {  ERROR_INVALID_HANDLE,         EBADF     },  /* 6 */\r
+        {  ERROR_ARENA_TRASHED,          ENOMEM    },  /* 7 */\r
+        {  ERROR_NOT_ENOUGH_MEMORY,      ENOMEM    },  /* 8 */\r
+        {  ERROR_INVALID_BLOCK,          ENOMEM    },  /* 9 */\r
+        {  ERROR_BAD_ENVIRONMENT,        E2BIG     },  /* 10 */\r
+        {  ERROR_BAD_FORMAT,             ENOEXEC   },  /* 11 */\r
+        {  ERROR_INVALID_ACCESS,         EINVAL    },  /* 12 */\r
+        {  ERROR_INVALID_DATA,           EINVAL    },  /* 13 */\r
+        {  ERROR_INVALID_DRIVE,          ENOENT    },  /* 15 */\r
+        {  ERROR_CURRENT_DIRECTORY,      EACCES    },  /* 16 */\r
+        {  ERROR_NOT_SAME_DEVICE,        EXDEV     },  /* 17 */\r
+        {  ERROR_NO_MORE_FILES,          ENOENT    },  /* 18 */\r
+        {  ERROR_LOCK_VIOLATION,         EACCES    },  /* 33 */\r
+        {  ERROR_BAD_NETPATH,            ENOENT    },  /* 53 */\r
+        {  ERROR_NETWORK_ACCESS_DENIED,  EACCES    },  /* 65 */\r
+        {  ERROR_BAD_NET_NAME,           ENOENT    },  /* 67 */\r
+        {  ERROR_FILE_EXISTS,            EEXIST    },  /* 80 */\r
+        {  ERROR_CANNOT_MAKE,            EACCES    },  /* 82 */\r
+        {  ERROR_FAIL_I24,               EACCES    },  /* 83 */\r
+        {  ERROR_INVALID_PARAMETER,      EINVAL    },  /* 87 */\r
+        {  ERROR_NO_PROC_SLOTS,          EAGAIN    },  /* 89 */\r
+        {  ERROR_DRIVE_LOCKED,           EACCES    },  /* 108 */\r
+        {  ERROR_BROKEN_PIPE,            EPIPE     },  /* 109 */\r
+        {  ERROR_DISK_FULL,              ENOSPC    },  /* 112 */\r
+        {  ERROR_INVALID_TARGET_HANDLE,  EBADF     },  /* 114 */\r
+        {  ERROR_INVALID_HANDLE,         EINVAL    },  /* 124 */\r
+        {  ERROR_WAIT_NO_CHILDREN,       ECHILD    },  /* 128 */\r
+        {  ERROR_CHILD_NOT_COMPLETE,     ECHILD    },  /* 129 */\r
+        {  ERROR_DIRECT_ACCESS_HANDLE,   EBADF     },  /* 130 */\r
+        {  ERROR_NEGATIVE_SEEK,          EINVAL    },  /* 131 */\r
+        {  ERROR_SEEK_ON_DEVICE,         EACCES    },  /* 132 */\r
+        {  ERROR_DIR_NOT_EMPTY,          ENOTEMPTY },  /* 145 */\r
+        {  ERROR_NOT_LOCKED,             EACCES    },  /* 158 */\r
+        {  ERROR_BAD_PATHNAME,           ENOENT    },  /* 161 */\r
+        {  ERROR_MAX_THRDS_REACHED,      EAGAIN    },  /* 164 */\r
+        {  ERROR_LOCK_FAILED,            EACCES    },  /* 167 */\r
+        {  ERROR_ALREADY_EXISTS,         EEXIST    },  /* 183 */\r
+        {  ERROR_FILENAME_EXCED_RANGE,   ENOENT    },  /* 206 */\r
+        {  ERROR_NESTING_NOT_ALLOWED,    EAGAIN    },  /* 215 */\r
+        {  ERROR_NOT_ENOUGH_QUOTA,       ENOMEM    }    /* 1816 */\r
+};\r
+\r
+/* size of the table */\r
+#define ERRTABLESIZE (sizeof(errtable)/sizeof(errtable[0]))\r
+\r
+/* The following two constants must be the minimum and maximum\r
+   values in the (contiguous) range of Exec Failure errors. */\r
+#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG\r
+#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN\r
+\r
+/* These are the low and high value in the range of errors that are\r
+   access violations */\r
+#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT\r
+#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED\r
+\r
+void maperrno (void)\r
+{\r
+       int i;\r
+       DWORD dwErrorCode;\r
+\r
+       dwErrorCode = GetLastError();\r
+\r
+       /* check the table for the OS error code */\r
+       for (i = 0; i < ERRTABLESIZE; ++i)\r
+       {\r
+               if (dwErrorCode == errtable[i].oscode)\r
+               {\r
+                       errno = errtable[i].errnocode;\r
+                       return;\r
+               }\r
+       }\r
+\r
+       /* The error code wasn't in the table.  We check for a range of */\r
+       /* EACCES errors or exec failure errors (ENOEXEC).  Otherwise   */\r
+       /* EINVAL is returned.                                          */\r
+\r
+       if (dwErrorCode >= MIN_EACCES_RANGE && dwErrorCode <= MAX_EACCES_RANGE)\r
+               errno = EACCES;\r
+       else\r
+               if (dwErrorCode >= MIN_EXEC_ERROR && dwErrorCode <= MAX_EXEC_ERROR)\r
+                       errno = ENOEXEC;\r
+               else\r
+                       errno = EINVAL;\r
+}\r
+\r
+#define TICKS_PER_SECOND 50\r
+// must match GHC.Conc.tick_freq\r
+\r
+HsInt getTicksOfDay(void)\r
+{\r
+    HsInt64 t;\r
+    FILETIME ft;\r
+    GetSystemTimeAsFileTime(&ft);\r
+    t = ((HsInt64)ft.dwHighDateTime << 32) | ft.dwLowDateTime;\r
+    t = (t * TICKS_PER_SECOND) / 10000000LL;\r
+      /* FILETIMES are in units of 100ns */\r
+    return (HsInt)t;\r
+}\r
+\r