* flock.cc (class inode_t): Add i_wait member and matching methods

wait(), unwait(), and waiting().
	(inode_t::inode_t): Initialize i_wait to 0.
	(fhandler_disk_file::lock): Only remove node if no other thread is
	waiting for a blocking lock.
	(lf_setlock): Manipulate node->i_wait to signal that a thread is
	waiting for a blocking lock in this node.
	(lf_findoverlap): Reinstantiate SELF test as in original code.
This commit is contained in:
Corinna Vinschen 2009-04-17 13:29:08 +00:00
parent 5bbd5ae0bb
commit a74869c027
2 changed files with 25 additions and 4 deletions

View File

@ -1,3 +1,14 @@
2009-04-17 Corinna Vinschen <corinna@vinschen.de>
* flock.cc (class inode_t): Add i_wait member and matching methods
wait(), unwait(), and waiting().
(inode_t::inode_t): Initialize i_wait to 0.
(fhandler_disk_file::lock): Only remove node if no other thread is
waiting for a blocking lock.
(lf_setlock): Manipulate node->i_wait to signal that a thread is
waiting for a blocking lock in this node.
(lf_findoverlap): Reinstantiate SELF test as in original code.
2009-04-16 Corinna Vinschen <corinna@vinschen.de> 2009-04-16 Corinna Vinschen <corinna@vinschen.de>
* dlfcn.cc (get_full_path_of_dll): Just return a bool value. Drop * dlfcn.cc (get_full_path_of_dll): Just return a bool value. Drop

View File

@ -1,6 +1,6 @@
/* flock.cc. NT specific implementation of advisory file locking. /* flock.cc. NT specific implementation of advisory file locking.
Copyright 2003, 2008 Red Hat, Inc. Copyright 2003, 2008, 2009 Red Hat, Inc.
This file is part of Cygwin. This file is part of Cygwin.
@ -267,6 +267,8 @@ class inode_t
private: private:
HANDLE i_dir; HANDLE i_dir;
HANDLE i_mtx; HANDLE i_mtx;
unsigned long i_wait; /* Number of blocked threads waiting for
a blocking lock. */
public: public:
inode_t (__dev32_t dev, __ino64_t ino); inode_t (__dev32_t dev, __ino64_t ino);
@ -282,6 +284,10 @@ class inode_t
void LOCK () { WaitForSingleObject (i_mtx, INFINITE); } void LOCK () { WaitForSingleObject (i_mtx, INFINITE); }
void UNLOCK () { ReleaseMutex (i_mtx); } void UNLOCK () { ReleaseMutex (i_mtx); }
void wait () { ++i_wait; }
void unwait () { if (i_wait > 0) --i_wait; }
bool waiting () { return i_wait > 0; }
lockf_t *get_all_locks_list (); lockf_t *get_all_locks_list ();
bool del_my_locks (long long id, HANDLE fhdl); bool del_my_locks (long long id, HANDLE fhdl);
@ -427,7 +433,7 @@ inode_t::get (__dev32_t dev, __ino64_t ino, bool create_if_missing)
} }
inode_t::inode_t (__dev32_t dev, __ino64_t ino) inode_t::inode_t (__dev32_t dev, __ino64_t ino)
: i_lockf (NULL), i_all_lf (NULL), i_dev (dev), i_ino (ino) : i_lockf (NULL), i_all_lf (NULL), i_dev (dev), i_ino (ino), i_wait (0L)
{ {
HANDLE parent_dir; HANDLE parent_dir;
WCHAR name[48]; WCHAR name[48];
@ -823,7 +829,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
delete lock; delete lock;
lock = n; lock = n;
} }
if (node->i_lockf == NULL) if (node->i_lockf == NULL && !node->waiting ())
{ {
INODE_LIST_LOCK (); INODE_LIST_LOCK ();
LIST_REMOVE (node, i_next); LIST_REMOVE (node, i_next);
@ -946,6 +952,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
return EDEADLK; return EDEADLK;
} }
HANDLE w4[3] = { obj, proc, signal_arrived }; HANDLE w4[3] = { obj, proc, signal_arrived };
node->wait ();
node->UNLOCK (); node->UNLOCK ();
ret = WaitForMultipleObjects (3, w4, FALSE, INFINITE); ret = WaitForMultipleObjects (3, w4, FALSE, INFINITE);
CloseHandle (proc); CloseHandle (proc);
@ -953,6 +960,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
else else
{ {
HANDLE w4[2] = { obj, signal_arrived }; HANDLE w4[2] = { obj, signal_arrived };
node->wait ();
node->UNLOCK (); node->UNLOCK ();
/* Unfortunately, since BSD flock locks are not attached to a /* Unfortunately, since BSD flock locks are not attached to a
specific process, we can't recognize an abandoned lock by specific process, we can't recognize an abandoned lock by
@ -965,6 +973,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
while (ret == WAIT_TIMEOUT && get_obj_handle_count (obj) > 1); while (ret == WAIT_TIMEOUT && get_obj_handle_count (obj) > 1);
} }
node->LOCK (); node->LOCK ();
node->unwait ();
NtClose (obj); NtClose (obj);
SetThreadPriority (GetCurrentThread (), old_prio); SetThreadPriority (GetCurrentThread (), old_prio);
switch (ret) switch (ret)
@ -1283,7 +1292,8 @@ lf_findoverlap (lockf_t *lf, lockf_t *lock, int type, lockf_t ***prev,
end = lock->lf_end; end = lock->lf_end;
while (lf != NOLOCKF) while (lf != NOLOCKF)
{ {
if (((type & OTHERS) && lf->lf_id == lock->lf_id) if (((type & SELF) && lf->lf_id != lock->lf_id)
|| ((type & OTHERS) && lf->lf_id == lock->lf_id)
/* As on Linux: POSIX locks and BSD flock locks don't interact. */ /* As on Linux: POSIX locks and BSD flock locks don't interact. */
|| (lf->lf_flags & (F_POSIX | F_FLOCK)) || (lf->lf_flags & (F_POSIX | F_FLOCK))
!= (lock->lf_flags & (F_POSIX | F_FLOCK))) != (lock->lf_flags & (F_POSIX | F_FLOCK)))