source: branches/win64/lisp-kernel/windows-calls.c @ 9654

Last change on this file since 9654 was 9654, checked in by gb, 11 years ago

Fail in attempts to use overlapped I/O.
Use an OVERLAPPED structure in windows_read() and note its use in
the TCR, so that blocking reads (at least those that happen here)
can be canceled.

File size: 9.0 KB
Line 
1/*
2   Copyright (C) 2008, Clozure Associates and contributors,
3   This file is part of Clozure CL. 
4
5   Clozure CL is licensed under the terms of the Lisp Lesser GNU Public
6   License , known as the LLGPL and distributed with Clozure CL as the
7   file "LICENSE".  The LLGPL consists of a preamble and the LGPL,
8   which is distributed with Clozure CL as the file "LGPL".  Where these
9   conflict, the preamble takes precedence. 
10
11   Clozure CL is referenced in the preamble as the "LIBRARY."
12
13   The LLGPL is also available online at
14   http://opensource.franz.com/preamble.html
15*/
16
17/*
18   These aren't really system calls; they're just C runtime functions
19   that (a) are built in to the lisp, so they can be called early
20   in the cold load, before the FFI is initialized and (b) return negated
21   error code on failure, so that it's not necessary to separately
22   fetch errno.
23
24   It's reasonable to consider replacing these things with wrappers
25   around native functionality (ReadFile, etc.) someday.
26
27   The order of the entries in windows_syscall_table[] should match
28   the order of syscall indices defined in
29   "ccl:library;x86-win64-syscalls.lisp".
30
31   One last time: these aren't really system calls.
32*/
33
34#include "lisp.h"
35#include "x86-exceptions.h"
36#include <io.h>
37#include <unistd.h>
38#include <sys/fcntl.h>
39#include <errno.h>
40#include <sys/stat.h>
41#include <windows.h>
42#include <psapi.h>
43#include <dirent.h>
44#include <stdio.h>
45
46
47
48#define _dosmaperr mingw_dosmaperr
49
50
51#define WSYSCALL_RETURN(form) \
52  do { \
53    int __result = form; \
54\
55    if (__result < 0){ \
56      return -errno; \
57    } \
58    return __result; \
59  } while (0)
60
61
62
63__int64
64windows_open(wchar_t *path, int flag, int mode)
65{
66  int fd;
67  HANDLE hfile;
68  DWORD dwDesiredAccess = 0;
69  DWORD dwShareMode = 0;
70  DWORD dwCreationDistribution = 0;
71  DWORD dwFlagsAndAttributes = 0;
72  SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
73
74  if ((flag & S_IREAD) == S_IREAD) {
75    dwShareMode = FILE_SHARE_READ;
76  } else {
77    if ((flag & S_IWRITE) == S_IWRITE) {
78      dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
79    }
80  }
81
82  if ((flag & _O_WRONLY) == _O_WRONLY) {
83    dwDesiredAccess |= GENERIC_WRITE | FILE_WRITE_DATA |
84      FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
85  } else if ((flag & _O_RDWR) == _O_RDWR) {
86    dwDesiredAccess |= GENERIC_WRITE|GENERIC_READ | FILE_READ_DATA |
87      FILE_WRITE_DATA | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES;
88  } else {
89    dwDesiredAccess |= GENERIC_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES |
90      FILE_WRITE_ATTRIBUTES;
91  }
92   
93  if ((flag & S_IREAD) == S_IREAD) {
94    dwShareMode |= FILE_SHARE_READ;
95  }
96  if ((flag & S_IWRITE) == S_IWRITE) {
97    dwShareMode |= FILE_SHARE_WRITE;
98  }
99
100  if ((flag & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) {
101    dwCreationDistribution |= CREATE_NEW;
102  } else if ((flag &  O_TRUNC) == O_TRUNC) {
103    if ((flag &  O_CREAT) ==  O_CREAT) {
104      dwCreationDistribution |= CREATE_ALWAYS;
105    } else if ((flag & O_RDONLY) != O_RDONLY) {
106      dwCreationDistribution |= TRUNCATE_EXISTING;
107    }
108  } else if ((flag & _O_APPEND) == _O_APPEND) {
109    dwCreationDistribution |= OPEN_EXISTING;
110  } else if ((flag &  _O_CREAT) == _O_CREAT) {
111    dwCreationDistribution |= OPEN_ALWAYS;
112  } else {
113    dwCreationDistribution |= OPEN_EXISTING;
114  }
115  if ((flag &  _O_RANDOM) == _O_RANDOM) {
116    dwFlagsAndAttributes |= FILE_FLAG_RANDOM_ACCESS;
117  }
118  if ((flag &  _O_SEQUENTIAL) == _O_SEQUENTIAL) {
119    dwFlagsAndAttributes |= FILE_FLAG_SEQUENTIAL_SCAN;
120  }
121
122  if ((flag &  _O_TEMPORARY) == _O_TEMPORARY) {
123    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
124  }
125
126  if ((flag &  _O_SHORT_LIVED) == _O_SHORT_LIVED) {
127    dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;
128  }
129
130  if (flag & _O_NOINHERIT) {
131    sa.bInheritHandle = FALSE;
132  }
133
134#if 0
135  dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
136#endif
137   
138
139  hfile = CreateFileW(path,
140                      dwDesiredAccess,
141                      dwShareMode,
142                      &sa,
143                      dwCreationDistribution,
144                      dwFlagsAndAttributes,
145                      NULL);
146  if (hfile == ((HANDLE)-1)) {
147    _dosmaperr(GetLastError());
148    return -errno;
149  }
150  fd = _open_osfhandle((intptr_t)hfile, flag);
151
152  if (fd < 0) {
153    CloseHandle(hfile);
154    return -fd;
155  }
156  return fd;
157}
158
159__int64
160windows_close(int fd)
161{
162  WSYSCALL_RETURN(close(fd));
163}
164
165__int64
166windows_read(int fd, void *buf, unsigned int count)
167{
168  HANDLE hfile;
169  OVERLAPPED overlapped;
170  DWORD err, nread;
171  pending_io pending;
172  TCR *tcr;
173  extern TCR *get_tcr(int);
174
175  hfile = (HANDLE) _get_osfhandle(fd);
176
177  if (hfile == ((HANDLE)-1)) {
178    return -EBADF;
179  }
180 
181  memset(&overlapped,0,sizeof(overlapped));
182
183  if (GetFileType(hfile) == FILE_TYPE_DISK) {
184    overlapped.Offset = SetFilePointer(hfile, 0, &(overlapped.OffsetHigh), FILE_CURRENT);
185  }
186
187  tcr = (TCR *)get_tcr(1);
188  pending.h = hfile;
189  pending.o = &overlapped;
190  tcr->foreign_exception_status = (signed_natural)&pending;
191
192  if (ReadFile(hfile, buf, count, &nread, &overlapped)) {
193    tcr->foreign_exception_status = 0;
194    return nread;
195  }
196  err = GetLastError();
197
198  if (err == ERROR_HANDLE_EOF) {
199    tcr->foreign_exception_status = 0;
200    return 0;
201  }
202
203  if (err != ERROR_IO_PENDING) {
204    _dosmaperr(err);
205    tcr->foreign_exception_status = 0;
206    return -errno;
207  }
208 
209  /* We block here */
210  if (GetOverlappedResult(hfile, &overlapped, &nread, TRUE)) {
211    tcr->foreign_exception_status = 0;
212    return nread;
213  }
214  err = GetLastError();
215  tcr->foreign_exception_status = 0;
216
217  switch (err) {
218  case ERROR_HANDLE_EOF: 
219    return 0;
220  case ERROR_OPERATION_ABORTED: 
221    return -EINTR;
222  default:
223    _dosmaperr(err);
224    return -errno;
225  }
226}
227
228__int64
229windows_write(int fd, void *buf, unsigned int count)
230{
231  WSYSCALL_RETURN( _write(fd, buf, count));
232}
233
234__int64
235windows_fchmod(int fd, int mode)
236{
237  return -ENOSYS;
238}
239
240__int64
241windows_lseek(int fd, _off64_t offset, int whence)
242{
243  WSYSCALL_RETURN(lseek64(fd, offset, whence));
244}
245
246__int64
247windows_stat(wchar_t *path, struct _stat64 *buf)
248{
249  WSYSCALL_RETURN(_wstat64(path,buf));
250}
251
252__int64
253windows_fstat(int fd, struct _stat64 *buf)
254{
255  WSYSCALL_RETURN(_fstat64(fd,buf));
256}
257
258
259__int64
260windows_ftruncate(int fd, _off64_t new_size)
261{
262  /* Note that _ftruncate only allows 32-bit length */
263  WSYSCALL_RETURN(ftruncate(fd,(off_t)new_size));
264}
265
266_WDIR *
267windows_opendir(wchar_t *path)
268{
269  return _wopendir(path);
270}
271
272struct _wdirent *
273windows_readdir(_WDIR *dir)
274{
275  return _wreaddir(dir);
276}
277
278__int64
279windows_closedir(_WDIR *dir)
280{
281  WSYSCALL_RETURN(_wclosedir(dir));
282}
283
284__int64
285windows_pipe(int fd[2])
286{
287  HANDLE input, output;
288  SECURITY_ATTRIBUTES sa;
289
290  sa.nLength= sizeof(SECURITY_ATTRIBUTES);
291  sa.lpSecurityDescriptor = NULL;
292  sa.bInheritHandle = TRUE;
293
294  if (!CreatePipe(&input, &output, &sa, 0))
295    {
296      wperror("CreatePipe");
297      return -1;
298    }
299  fd[0] = _open_osfhandle((intptr_t)input, 0);
300  fd[1] = _open_osfhandle((intptr_t)output, 0);
301  return 0;
302}
303
304void *
305windows_syscall_table[] = {
306  windows_open,
307  windows_close,
308  windows_read,
309  windows_write,
310  windows_fchmod,
311  windows_lseek,
312  windows_stat,
313  windows_fstat,
314  windows_ftruncate,
315  windows_opendir,
316  windows_readdir,
317  windows_closedir,
318  windows_pipe
319};
320
321HMODULE *modules = NULL;
322DWORD cbmodules = 0;
323
324void *
325windows_find_symbol(void *handle, char *name)
326{
327  if (handle == ((void *)-2L)) {
328    handle = NULL;
329  }
330  if (handle != NULL) {
331    return GetProcAddress(handle, name);
332  } else {
333    DWORD cbneeded,  have, i;
334
335    if (cbmodules == 0) {
336      cbmodules = 16 * sizeof(HANDLE);
337      modules = LocalAlloc(LPTR, cbmodules);
338    }
339   
340    while (1) {
341      EnumProcessModules(GetCurrentProcess(),modules,cbmodules,&cbneeded);
342      if (cbmodules >= cbneeded) {
343        break;
344      }
345      cbmodules = cbneeded;
346      modules = LocalReAlloc(modules,cbmodules,0);
347    }
348    have = cbneeded/sizeof(HANDLE);
349
350    for (i = 0; i < have; i++) {
351      void *addr = GetProcAddress(modules[i],name);
352
353      if (addr) {
354        return addr;
355      }
356    }
357    return NULL;
358  }
359}
360
361void
362init_windows_io()
363{
364#if 0
365  int fd;
366  HANDLE hfile0, hfile1;
367
368  hfile0 = (HANDLE) _get_osfhandle(0);
369  hfile1 = ReOpenFile(hfile0,GENERIC_READ,FILE_SHARE_READ,FILE_FLAG_OVERLAPPED);
370  if (hfile1 != ((HANDLE)-1)) {
371    fd = _open_osfhandle(hfile1,O_RDONLY);
372    dup2(fd,0);
373    _close(fd);
374    SetStdHandle(STD_INPUT_HANDLE,hfile1);
375    CloseHandle(hfile0);
376  } else {
377    wperror("ReOpenFile");
378  }
379
380  hfile0 = (HANDLE) _get_osfhandle(1);
381  hfile1 = ReOpenFile(hfile0,GENERIC_WRITE,FILE_SHARE_WRITE,FILE_FLAG_OVERLAPPED);
382  if (hfile1 != ((HANDLE)-1)) {
383    fd = _open_osfhandle(hfile1,O_WRONLY);
384    dup2(fd,1);
385    _close(fd);
386    SetStdHandle(STD_OUTPUT_HANDLE,hfile1);
387    CloseHandle(hfile0);
388  }
389
390  hfile0 = (HANDLE) _get_osfhandle(2);
391  hfile1 = ReOpenFile(hfile0,GENERIC_WRITE,FILE_SHARE_WRITE,FILE_FLAG_OVERLAPPED);
392  if (hfile1 != ((HANDLE)-1)) {
393    fd = _open_osfhandle(hfile1,O_WRONLY);
394    dup2(fd,2);
395    _close(fd);
396    SetStdHandle(STD_ERROR_HANDLE,hfile1);
397    CloseHandle(hfile0);
398  }
399#endif 
400}
401
402void
403init_winsock()
404{
405  WSADATA data;
406
407  WSAStartup((2<<8)|2,&data);
408}
Note: See TracBrowser for help on using the repository browser.