aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2004-04-19 19:29:10 +0000
committerCorinna Vinschen <corinna@vinschen.de>2004-04-19 19:29:10 +0000
commit0c8731b8f43ff50700432767b34e67a11a713bff (patch)
tree0ed0a5a1284fbdfb58307e6c11df8624ad6f3e5d /winsup
parentda3c66eb9a72ab2e4dd969118f8e3c63c2beb086 (diff)
downloadnewlib-0c8731b8f43ff50700432767b34e67a11a713bff.zip
newlib-0c8731b8f43ff50700432767b34e67a11a713bff.tar.gz
newlib-0c8731b8f43ff50700432767b34e67a11a713bff.tar.bz2
* errno.cc (errmap): Handle ERROR_IO_PENDING.
* fhandler.cc (fhandler_base::open): Make tape I/O asynchronous. * fhandler.h (class fhandler_dev_tape): Add mt_evt member. * fhandler_tape.cc (mtinfo_drive::initialize): Initialize async_writes. (mtinfo_drive::close): Handle async writes. (mtinfo_drive::read): Add mt_evt parameter. Use overlapped I/O. (mtinfo_drive::async_wait): New function. (mtinfo_drive::write): Add mt_evt parameter. Use overlapped I/O. Handle async writes. (mtinfo_drive::_set_pos): Handle async writes. (mtinfo_drive::set_partition): Ditto. (mtinfo_drive::prepare): Ditto. (mtinfo_drive::get_status): Drop useless "else". Handle async_writes flag. (mtinfo_drive::set_options): Handle async_writes flags. (fhandler_dev_tape::close): Close mt_evt handle. (fhandler_dev_tape::raw_read): Create mt_evt handle and use in call to mtinfo_drive::read. (fhandler_dev_tape::raw_write): Create mt_evt handle and use in call to mtinfo_drive::write. * mtinfo.h (MTINFO_VERSION): Bump. (enum dirty_state): Add async_write_pending state. (class mtinfo_drive): Add OVERLAPPED struct "ov". Add async_writes flag. (mtinfo_drive::async_wait): Add declaration. (mtinfo_drive::read): Add mt_evt parameter. (mtinfo_drive::write): Ditto. * registry.cc (load_registry_hive): Call enable_restore_privilege instead of set_process_privilege.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog33
-rw-r--r--winsup/cygwin/errno.cc1
-rw-r--r--winsup/cygwin/fhandler.cc3
-rw-r--r--winsup/cygwin/fhandler.h1
-rw-r--r--winsup/cygwin/fhandler_tape.cc100
-rw-r--r--winsup/cygwin/mtinfo.h13
-rw-r--r--winsup/cygwin/registry.cc2
7 files changed, 130 insertions, 23 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 2d6d8af..7870c32 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,38 @@
2004-04-19 Corinna Vinschen <corinna@vinschen.de>
+ * errno.cc (errmap): Handle ERROR_IO_PENDING.
+ * fhandler.cc (fhandler_base::open): Make tape I/O asynchronous.
+ * fhandler.h (class fhandler_dev_tape): Add mt_evt member.
+ * fhandler_tape.cc (mtinfo_drive::initialize): Initialize async_writes.
+ (mtinfo_drive::close): Handle async writes.
+ (mtinfo_drive::read): Add mt_evt parameter. Use overlapped I/O.
+ (mtinfo_drive::async_wait): New function.
+ (mtinfo_drive::write): Add mt_evt parameter. Use overlapped I/O.
+ Handle async writes.
+ (mtinfo_drive::_set_pos): Handle async writes.
+ (mtinfo_drive::set_partition): Ditto.
+ (mtinfo_drive::prepare): Ditto.
+ (mtinfo_drive::get_status): Drop useless "else". Handle async_writes
+ flag.
+ (mtinfo_drive::set_options): Handle async_writes flags.
+ (fhandler_dev_tape::close): Close mt_evt handle.
+ (fhandler_dev_tape::raw_read): Create mt_evt handle and use in call
+ to mtinfo_drive::read.
+ (fhandler_dev_tape::raw_write): Create mt_evt handle and use in call
+ to mtinfo_drive::write.
+ * mtinfo.h (MTINFO_VERSION): Bump.
+ (enum dirty_state): Add async_write_pending state.
+ (class mtinfo_drive): Add OVERLAPPED struct "ov". Add async_writes
+ flag.
+ (mtinfo_drive::async_wait): Add declaration.
+ (mtinfo_drive::read): Add mt_evt parameter.
+ (mtinfo_drive::write): Ditto.
+
+ * registry.cc (load_registry_hive): Call enable_restore_privilege
+ instead of set_process_privilege.
+
+2004-04-19 Corinna Vinschen <corinna@vinschen.de>
+
* fhandler_tape.cc (mtinfo_drive::_set_pos): Take additional dont_wait
parameter. Use in call to SetTapePosition.
(mtinfo_drive::set_pos): Accomodate _set_pos calls to above change.
diff --git a/winsup/cygwin/errno.cc b/winsup/cygwin/errno.cc
index 475164a..7d99f75 100644
--- a/winsup/cygwin/errno.cc
+++ b/winsup/cygwin/errno.cc
@@ -119,6 +119,7 @@ static NO_COPY struct
X (NO_MEDIA_IN_DRIVE, ENOMEDIUM),
X (DEVICE_REQUIRES_CLEANING, EIO),
X (DEVICE_DOOR_OPEN, EIO),
+ X (IO_PENDING, EAGAIN),
{ 0, NULL, 0}
};
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index f1dfed8..a3ef1bb 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -610,7 +610,8 @@ fhandler_base::open (int flags, mode_t mode)
/* Allow reliable lseek on disk devices. */
if (get_major () == DEV_FLOPPY_MAJOR)
access |= GENERIC_READ;
- else if (get_major () != DEV_SERIAL_MAJOR)
+ else if (get_major () != DEV_SERIAL_MAJOR
+ && get_major () != DEV_TAPE_MAJOR)
{
create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
access |= SYNCHRONIZE;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 17f3ade..9903864 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -535,6 +535,7 @@ class fhandler_dev_floppy: public fhandler_dev_raw
class fhandler_dev_tape: public fhandler_dev_raw
{
HANDLE mt_mtx;
+ HANDLE mt_evt;
bool is_rewind_device () { return get_minor () < 128; }
unsigned int driveno () { return (unsigned int) get_minor () & 0x7f; }
diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc
index 0f3ed0e..2296d59 100644
--- a/winsup/cygwin/fhandler_tape.cc
+++ b/winsup/cygwin/fhandler_tape.cc
@@ -81,6 +81,7 @@ mtinfo_drive::initialize (int num, bool first_time)
if (first_time)
{
buffer_writes (true);
+ async_writes (false);
two_fm (false);
fast_eom (false);
auto_lock (false);
@@ -135,16 +136,22 @@ mtinfo_drive::close (HANDLE mt, bool rewind)
lasterr = 0;
if (GetTapeStatus (mt) == ERROR_NO_MEDIA_IN_DRIVE)
dirty = clean;
- if (dirty == has_written)
+ if (dirty >= has_written)
{
- /* if last operation was writing, write a filemark */
- debug_printf ("writing filemark");
- write_marks (mt, TAPE_FILEMARKS, two_fm () ? 2 : 1);
- if (two_fm () && !lasterr && !rewind) /* Backspace over 2nd filemark. */
+ /* If an async write is still pending, wait for completion. */
+ if (dirty == async_write_pending)
+ lasterr = async_wait (mt, NULL);
+ if (!lasterr)
{
- set_pos (mt, TAPE_SPACE_FILEMARKS, -1, false);
- if (!lasterr)
- part (partition)->fblock = 0; /* That's obvious, isn't it? */
+ /* if last operation was writing, write a filemark */
+ debug_printf ("writing filemark");
+ write_marks (mt, TAPE_FILEMARKS, two_fm () ? 2 : 1);
+ if (two_fm () && !lasterr && !rewind) /* Backspace over 2nd fmark. */
+ {
+ set_pos (mt, TAPE_SPACE_FILEMARKS, -1, false);
+ if (!lasterr)
+ part (partition)->fblock = 0; /* That's obvious, isn't it? */
+ }
}
}
else if (dirty == has_read && !rewind)
@@ -179,7 +186,7 @@ mtinfo_drive::close (HANDLE mt, bool rewind)
}
int
-mtinfo_drive::read (HANDLE mt, void *ptr, size_t &ulen)
+mtinfo_drive::read (HANDLE mt, HANDLE mt_evt, void *ptr, size_t &ulen)
{
BOOL ret;
DWORD bytes_read = 0;
@@ -191,6 +198,9 @@ mtinfo_drive::read (HANDLE mt, void *ptr, size_t &ulen)
ulen = 0;
goto out;
}
+ /* If an async write is still pending, wait for completion. */
+ if (dirty == async_write_pending)
+ lasterr = async_wait (mt, NULL);
dirty = clean;
if (part (partition)->emark == eof_hit)
{
@@ -225,8 +235,12 @@ mtinfo_drive::read (HANDLE mt, void *ptr, size_t &ulen)
part (partition)->smark = false;
if (auto_lock () && lock < auto_locked)
prepare (mt, TAPE_LOCK, true);
- ret = ReadFile (mt, ptr, ulen, &bytes_read, 0);
+ ov.Offset = ov.OffsetHigh = 0;
+ ov.hEvent = mt_evt;
+ ret = ReadFile (mt, ptr, ulen, &bytes_read, &ov);
lasterr = ret ? 0 : GetLastError ();
+ if (lasterr == ERROR_IO_PENDING)
+ lasterr = async_wait (mt, &bytes_read);
ulen = (size_t) bytes_read;
if (bytes_read > 0)
{
@@ -273,10 +287,22 @@ out:
}
int
-mtinfo_drive::write (HANDLE mt, const void *ptr, size_t &len)
+mtinfo_drive::async_wait (HANDLE mt, DWORD *bytes_written)
+{
+ DWORD written;
+
+ bool ret = GetOverlappedResult (mt, &ov, &written, TRUE);
+ if (bytes_written)
+ *bytes_written = written;
+ return ret ? 0 : GetLastError ();
+}
+
+int
+mtinfo_drive::write (HANDLE mt, HANDLE mt_evt, const void *ptr, size_t &len)
{
BOOL ret;
DWORD bytes_written = 0;
+ int async_err = 0;
if (GetTapeStatus (mt) == ERROR_NO_MEDIA_IN_DRIVE)
return lasterr = ERROR_NO_MEDIA_IN_DRIVE;
@@ -285,12 +311,24 @@ mtinfo_drive::write (HANDLE mt, const void *ptr, size_t &len)
len = 0;
return error ("write");
}
+ if (dirty == async_write_pending)
+ async_err = async_wait (mt, &bytes_written);
dirty = clean;
part (partition)->smark = false;
if (auto_lock () && lock < auto_locked)
prepare (mt, TAPE_LOCK, true);
- ret = WriteFile (mt, ptr, len, &bytes_written, 0);
+ ov.Offset = ov.OffsetHigh = 0;
+ ov.hEvent = mt_evt;
+ ret = WriteFile (mt, ptr, len, &bytes_written, &ov);
lasterr = ret ? 0: GetLastError ();
+ if (lasterr == ERROR_IO_PENDING)
+ {
+ if (async_writes () && mp ()->BlockSize == 0)
+ dirty = async_write_pending;
+ else
+ /* Wait for completion if a non-async write. */
+ lasterr = async_wait (mt, &bytes_written);
+ }
len = (size_t) bytes_written;
if (bytes_written > 0)
{
@@ -301,6 +339,8 @@ mtinfo_drive::write (HANDLE mt, const void *ptr, size_t &len)
if (part (partition)->fblock >= 0)
part (partition)->fblock += blocks_written;
}
+ if (!lasterr && async_err)
+ lasterr = async_err;
if (lasterr == ERROR_EOM_OVERFLOW)
part (partition)->emark = eom;
else if (lasterr == ERROR_END_OF_MEDIA)
@@ -310,6 +350,8 @@ mtinfo_drive::write (HANDLE mt, const void *ptr, size_t &len)
part (partition)->emark = no_eof;
if (!lasterr)
dirty = has_written;
+ else if (lasterr == ERROR_IO_PENDING)
+ dirty = async_write_pending;
}
return error ("write");
}
@@ -344,9 +386,12 @@ int
mtinfo_drive::_set_pos (HANDLE mt, int mode, long count, int partition,
BOOL dont_wait)
{
+ /* If an async write is still pending, wait for completion. */
+ if (dirty == async_write_pending)
+ lasterr = async_wait (mt, NULL);
+ dirty = clean;
TAPE_FUNC (SetTapePosition (mt, mode, partition, count, count < 0 ? -1 : 0,
dont_wait));
- dirty = clean;
return lasterr;
}
@@ -575,6 +620,12 @@ mtinfo_drive::set_partition (HANDLE mt, long count)
int
mtinfo_drive::write_marks (HANDLE mt, int marktype, DWORD count)
{
+ /* If an async write is still pending, wait for completion. */
+ if (dirty == async_write_pending)
+ {
+ lasterr = async_wait (mt, NULL);
+ dirty = has_written;
+ }
if (marktype != TAPE_SETMARKS)
dirty = clean;
if (marktype == TAPE_FILEMARKS
@@ -639,6 +690,9 @@ mtinfo_drive::prepare (HANDLE mt, int action, bool is_auto)
{
BOOL dont_wait = FALSE;
+ /* If an async write is still pending, wait for completion. */
+ if (dirty == async_write_pending)
+ lasterr = async_wait (mt, NULL);
dirty = clean;
if (action == TAPE_UNLOAD || action == TAPE_LOAD || action == TAPE_TENSION)
dont_wait = nowait () ? TRUE : FALSE;
@@ -781,7 +835,7 @@ mtinfo_drive::get_status (HANDLE mt, struct mtget *get)
if (buffer_writes ())
get->mt_gstat |= GMT_IM_REP_EN (-1); /* TODO: Async writes */
- else if (tstat == ERROR_DEVICE_REQUIRES_CLEANING)
+ if (tstat == ERROR_DEVICE_REQUIRES_CLEANING)
get->mt_gstat |= GMT_CLN (-1);
/* Cygwin specials: */
@@ -803,6 +857,8 @@ mtinfo_drive::get_status (HANDLE mt, struct mtget *get)
get->mt_gstat |= GMT_SYSV (-1);
if (nowait ())
get->mt_gstat |= GMT_NOWAIT (-1);
+ if (async_writes ())
+ get->mt_gstat |= GMT_ASYNC (-1);
get->mt_erreg = 0; /* FIXME: No softerr counting */
@@ -842,6 +898,7 @@ mtinfo_drive::set_options (HANDLE mt, long options)
break;
case MT_ST_BOOLEANS:
buffer_writes (!!(options & MT_ST_BUFFER_WRITES));
+ async_writes (!!(options & MT_ST_ASYNC_WRITES));
two_fm (!!(options & MT_ST_TWO_FM));
fast_eom (!!(options & MT_ST_FAST_MTEOM));
auto_lock (!!(options & MT_ST_AUTO_LOCK));
@@ -862,6 +919,8 @@ mtinfo_drive::set_options (HANDLE mt, long options)
set = (what == MT_ST_SETBOOLEANS);
if (options & MT_ST_BUFFER_WRITES)
buffer_writes (set);
+ if (options & MT_ST_ASYNC_WRITES)
+ async_writes (set);
if (options & MT_ST_TWO_FM)
two_fm (set);
if (options & MT_ST_FAST_MTEOM)
@@ -1197,6 +1256,8 @@ fhandler_dev_tape::close (void)
lock (-1);
ret = mt->drive (driveno ())->close (get_handle (), is_rewind_device ());
+ if (mt_evt)
+ CloseHandle (mt_evt);
if (ret)
__seterrno_from_win_error (ret);
cret = fhandler_dev_raw::close ();
@@ -1245,12 +1306,15 @@ fhandler_dev_tape::raw_read (void *ptr, size_t &ulen)
}
if (len > 0)
{
+ if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
+ debug_printf ("Creating event failed: %E");
size_t block_fit = !block_size ? len : rounddown(len, block_size);
if (block_fit)
{
debug_printf ("read %d bytes from tape (rest %d)",
block_fit, len - block_fit);
- ret = mt->drive (driveno ())->read (get_handle (), buf, block_fit);
+ ret = mt->drive (driveno ())->read (get_handle (), mt_evt, buf,
+ block_fit);
if (ret)
__seterrno_from_win_error (ret);
else if (block_fit)
@@ -1271,7 +1335,7 @@ fhandler_dev_tape::raw_read (void *ptr, size_t &ulen)
if (!ret && len > 0)
{
debug_printf ("read %d bytes from tape (one block)", block_size);
- ret = mt->drive (driveno ())->read (get_handle (), devbuf,
+ ret = mt->drive (driveno ())->read (get_handle (), mt_evt, devbuf,
block_size);
if (ret)
__seterrno_from_win_error (ret);
@@ -1297,7 +1361,9 @@ int
fhandler_dev_tape::raw_write (const void *ptr, size_t len)
{
lock (-1);
- int ret = mt->drive (driveno ())->write (get_handle (), ptr, len);
+ if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
+ debug_printf ("Creating event failed: %E");
+ int ret = mt->drive (driveno ())->write (get_handle (), mt_evt, ptr, len);
__seterrno_from_win_error (ret);
return unlock (len);
}
diff --git a/winsup/cygwin/mtinfo.h b/winsup/cygwin/mtinfo.h
index 4cf92bc..52dd6b2 100644
--- a/winsup/cygwin/mtinfo.h
+++ b/winsup/cygwin/mtinfo.h
@@ -9,7 +9,7 @@ Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#define MTINFO_MAGIC 0x179b2af0
-#define MTINFO_VERSION 1
+#define MTINFO_VERSION 2
/* Maximum number of supported partitions per drive. */
#define MAX_PARTITION_NUM 64
@@ -33,7 +33,8 @@ enum dirty_state
{
clean,
has_read,
- has_written
+ has_written,
+ async_write_pending
};
enum lock_state
@@ -67,9 +68,11 @@ class mtinfo_drive
lock_state lock;
TAPE_GET_DRIVE_PARAMETERS _dp;
TAPE_GET_MEDIA_PARAMETERS _mp;
+ OVERLAPPED ov;
struct status_flags
{
unsigned buffer_writes : 1;
+ unsigned async_writes : 1;
unsigned two_fm : 1;
unsigned fast_eom : 1;
unsigned auto_lock : 1;
@@ -101,6 +104,7 @@ class mtinfo_drive
int set_blocksize (HANDLE mt, long count);
int get_status (HANDLE mt, struct mtget *get);
int set_options (HANDLE mt, long options);
+ int async_wait (HANDLE mt, DWORD *bytes_written);
public:
void initialize (int num, bool first_time);
@@ -108,12 +112,13 @@ public:
int get_mp (HANDLE mt);
int open (HANDLE mt);
int close (HANDLE mt, bool rewind);
- int read (HANDLE mt, void *ptr, size_t &ulen);
- int write (HANDLE mt, const void *ptr, size_t &len);
+ int read (HANDLE mt, HANDLE mt_evt, void *ptr, size_t &ulen);
+ int write (HANDLE mt, HANDLE mt_evt, const void *ptr, size_t &len);
int ioctl (HANDLE mt, unsigned int cmd, void *buf);
int set_pos (HANDLE mt, int mode, long count, bool sfm_func);
IMPLEMENT_STATUS_FLAG (bool, buffer_writes)
+ IMPLEMENT_STATUS_FLAG (bool, async_writes)
IMPLEMENT_STATUS_FLAG (bool, two_fm)
IMPLEMENT_STATUS_FLAG (bool, fast_eom)
IMPLEMENT_STATUS_FLAG (bool, auto_lock)
diff --git a/winsup/cygwin/registry.cc b/winsup/cygwin/registry.cc
index 0a36b3a..bb47c48 100644
--- a/winsup/cygwin/registry.cc
+++ b/winsup/cygwin/registry.cc
@@ -241,7 +241,7 @@ load_registry_hive (PSID psid)
RegCloseKey (hkey);
return;
}
- set_process_privilege (SE_RESTORE_NAME);
+ enable_restore_privilege ();
if (get_registry_hive_path (psid, path))
{
strcat (path, "\\NTUSER.DAT");