summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_tape.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2011-05-04 12:23:00 +0000
committerCorinna Vinschen <corinna@vinschen.de>2011-05-04 12:23:00 +0000
commit412693ab6529ecd163630785064f2c989db9ad4a (patch)
tree6b1bf781ccade8e009eafe465d385c47676b3b8c /winsup/cygwin/fhandler_tape.cc
parent5152a53adeaa86135dd7ca1ce3ae64e7353b3729 (diff)
downloadcygnal-412693ab6529ecd163630785064f2c989db9ad4a.tar.gz
cygnal-412693ab6529ecd163630785064f2c989db9ad4a.tar.bz2
cygnal-412693ab6529ecd163630785064f2c989db9ad4a.zip
* fhandler.h (fhandler_dev_tape::_lock): Add bool parameter.
* fhandler_tape.cc (lock): Call _lock with false argument. (_lock): Take bool cancelable parameter. Handle O_NONBLOCK. Make cancelable if cancelabe parameter is true. (fhandler_dev_tape::raw_read): Call _lock with true argument. (fhandler_dev_tape::raw_write): Ditto.
Diffstat (limited to 'winsup/cygwin/fhandler_tape.cc')
-rw-r--r--winsup/cygwin/fhandler_tape.cc40
1 files changed, 30 insertions, 10 deletions
diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc
index ff7e84aab..97e5d6010 100644
--- a/winsup/cygwin/fhandler_tape.cc
+++ b/winsup/cygwin/fhandler_tape.cc
@@ -2,7 +2,7 @@
classes.
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2010 Red Hat, Inc.
+ 2008, 2010, 2011 Red Hat, Inc.
This file is part of Cygwin.
@@ -1136,19 +1136,38 @@ mtinfo::initialize ()
#define mt (cygwin_shared->mt)
-#define lock(err_ret_val) if (!_lock ()) return err_ret_val;
+#define lock(err_ret_val) if (!_lock (false)) return (err_ret_val);
inline bool
-fhandler_dev_tape::_lock ()
+fhandler_dev_tape::_lock (bool cancelable)
{
- HANDLE obj[2] = { mt_mtx, signal_arrived };
- BOOL ret = WaitForMultipleObjects (2, obj, FALSE, INFINITE) == WAIT_OBJECT_0;
- if (!ret)
+ HANDLE w4[3] = { mt_mtx, signal_arrived, NULL };
+ DWORD cnt = 2;
+ if (cancelable && (w4[2] = pthread::get_cancel_event ()) != NULL)
+ cnt = 3;
+ /* O_NONBLOCK is only valid in a read or write call. Only those are
+ cancelable. */
+ DWORD timeout = cancelable && is_nonblocking () ? 0 : INFINITE;
+restart:
+ switch (WaitForMultipleObjects (cnt, w4, FALSE, timeout))
{
- debug_printf ("signal_arrived"); \
+ case WAIT_OBJECT_0:
+ return true;
+ case WAIT_OBJECT_0 + 1:
+ if (_my_tls.call_signal_handler ())
+ goto restart;
set_errno (EINTR);
+ return false;
+ case WAIT_OBJECT_0 + 2:
+ pthread::static_cancel_self ();
+ /*NOTREACHED*/
+ case WAIT_TIMEOUT:
+ set_errno (EAGAIN);
+ return false;
+ default:
+ __seterrno ();
+ return false;
}
- return ret;
}
inline int
@@ -1248,7 +1267,7 @@ fhandler_dev_tape::raw_read (void *ptr, size_t &ulen)
ulen = 0;
return;
}
- if (!_lock ())
+ if (!_lock (true))
{
ulen = (size_t) -1;
return;
@@ -1336,7 +1355,8 @@ fhandler_dev_tape::raw_read (void *ptr, size_t &ulen)
ssize_t __stdcall
fhandler_dev_tape::raw_write (const void *ptr, size_t len)
{
- lock (-1);
+ if (!_lock (true))
+ return -1;
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);