Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2012-05-23 17:13:56 +0400
committerCorinna Vinschen <corinna@vinschen.de>2012-05-23 17:13:56 +0400
commit2ca9ed527e8a18ff402e036174b2b003460fdf06 (patch)
treea023c3489333d615b1431194998003a1bf140bd9 /winsup/cygwin/fhandler.h
parent420b3469a759ab126ba2ade71559e70bbddfeb2d (diff)
* fhandler.h (refcnt): Add i interlocked. Explain why.
* winbase.h (ilockadd): New function. (InterlockedAdd): Define as ilockadd.
Diffstat (limited to 'winsup/cygwin/fhandler.h')
-rw-r--r--winsup/cygwin/fhandler.h6
1 files changed, 5 insertions, 1 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 18e829aa6..84f6e4c3f 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -185,7 +185,11 @@ class fhandler_base
long refcnt(long i = 0)
{
debug_only_printf ("%p, %s, i %d, refcnt %ld", this, get_name (), i, _refcnt + i);
- return _refcnt += i;
+ /* This MUST be an interlocked operation. If multiple threads access the
+ same descriptor in quick succession, a context switch can interrupt
+ the += operation and we wrongly end up with a refcnt of 0 in the
+ cygheap_fdget destructor. */
+ return i ? InterlockedAdd (&_refcnt, i) : _refcnt;
}
class fhandler_base *archetype;
int usecount;