* 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>
* 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.
Copyright 2003, 2008 Red Hat, Inc.
Copyright 2003, 2008, 2009 Red Hat, Inc.
This file is part of Cygwin.
@ -267,6 +267,8 @@ class inode_t
private:
HANDLE i_dir;
HANDLE i_mtx;
unsigned long i_wait; /* Number of blocked threads waiting for
a blocking lock. */
public:
inode_t (__dev32_t dev, __ino64_t ino);
@ -282,6 +284,10 @@ class inode_t
void LOCK () { WaitForSingleObject (i_mtx, INFINITE); }
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 ();
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)
: 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;
WCHAR name[48];
@ -823,7 +829,7 @@ fhandler_disk_file::lock (int a_op, struct __flock64 *fl)
delete lock;
lock = n;
}
if (node->i_lockf == NULL)
if (node->i_lockf == NULL && !node->waiting ())
{
INODE_LIST_LOCK ();
LIST_REMOVE (node, i_next);
@ -946,6 +952,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
return EDEADLK;
}
HANDLE w4[3] = { obj, proc, signal_arrived };
node->wait ();
node->UNLOCK ();
ret = WaitForMultipleObjects (3, w4, FALSE, INFINITE);
CloseHandle (proc);
@ -953,6 +960,7 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
else
{
HANDLE w4[2] = { obj, signal_arrived };
node->wait ();
node->UNLOCK ();
/* Unfortunately, since BSD flock locks are not attached to a
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);
}
node->LOCK ();
node->unwait ();
NtClose (obj);
SetThreadPriority (GetCurrentThread (), old_prio);
switch (ret)
@ -1283,7 +1292,8 @@ lf_findoverlap (lockf_t *lf, lockf_t *lock, int type, lockf_t ***prev,
end = lock->lf_end;
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. */
|| (lf->lf_flags & (F_POSIX | F_FLOCK))
!= (lock->lf_flags & (F_POSIX | F_FLOCK)))