From f8af64be8716333f179a1d240ef42fab5188b607 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Sat, 13 Mar 2010 19:34:35 +0000 Subject: [PATCH] * spinlock.h: New file. (spinlock): New class. * shared.cc: Include spinlock.h. (memory_init): Use new spinlock methods rather than roll-your-own. Time out after ten seconds if shared_mem_inited is not initialized. * sync.h: Update copyright. Remove vanity attribution. * sigproc.cc (sigproc_terminate): Avoid attempts to kill the signal thread while we're still initializing or suffer a deadlock. --- winsup/cygwin/ChangeLog | 13 ++++++++++ winsup/cygwin/shared.cc | 53 ++++++++++++++++------------------------ winsup/cygwin/sigproc.cc | 4 ++- winsup/cygwin/spinlock.h | 40 ++++++++++++++++++++++++++++++ winsup/cygwin/sync.h | 4 +-- 5 files changed, 78 insertions(+), 36 deletions(-) create mode 100644 winsup/cygwin/spinlock.h diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index e476c7e4f..c5713914c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,16 @@ +2010-03-13 Christopher Faylor + + * spinlock.h: New file. + (spinlock): New class. + * shared.cc: Include spinlock.h. + (memory_init): Use new spinlock methods rather than roll-your-own. + Time out after ten seconds if shared_mem_inited is not initialized. + + * sync.h: Update copyright. Remove vanity attribution. + + * sigproc.cc (sigproc_terminate): Avoid attempts to kill the signal + thread while we're still initializing or suffer a deadlock. + 2010-03-12 Christopher Faylor Throughout change all calls of low_priority_sleep (0) to yield (). diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index fcca6f40f..6e166f3fa 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -23,6 +23,7 @@ details. */ #include "registry.h" #include "cygwin_version.h" #include "pwdgrp.h" +#include "spinlock.h" #include "ntdll.h" #include #include @@ -418,40 +419,28 @@ memory_init (bool init_cygheap) } /* Initialize general shared memory under spinlock control */ - for (;;) - { - LONG smi = InterlockedExchange (&shared_mem_inited, -1); - if (smi < 0) - { - yield (); - continue; - } + { + spinlock smi (shared_mem_inited, 10000); + if (!smi) + init_installation_root (); /* Initialize installation root dir */ - if (!smi) - /* Initialize installation root dir */ - init_installation_root (); + cygwin_shared = (shared_info *) open_shared (L"shared", + CYGWIN_VERSION_SHARED_DATA, + cygwin_shared_h, + sizeof (*cygwin_shared), + SH_CYGWIN_SHARED); + heap_init (); - cygwin_shared = (shared_info *) open_shared (L"shared", - CYGWIN_VERSION_SHARED_DATA, - cygwin_shared_h, - sizeof (*cygwin_shared), - SH_CYGWIN_SHARED); - heap_init (); - - if (!smi) - { - cygwin_shared->initialize (); - /* Defer debug output printing the installation root and installation key - up to this point. Debug output except for system_printf requires - the global shared memory to exist. */ - debug_printf ("Installation root: <%W> key: <%S>", - installation_root, &installation_key); - smi = 1; - } - - InterlockedExchange (&shared_mem_inited, smi); - break; - } + if (!smi) + { + cygwin_shared->initialize (); + /* Defer debug output printing the installation root and installation key + up to this point. Debug output except for system_printf requires + the global shared memory to exist. */ + debug_printf ("Installation root: <%W> key: <%S>", + installation_root, &installation_key); + } + } user_shared_create (false); } diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 9408b0c6d..e84690320 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -494,7 +494,9 @@ sigproc_terminate (exit_states es) { exit_states prior_exit_state = exit_state; exit_state = es; - if (prior_exit_state >= ES_FINAL) + if (!cygwin_finished_initializing) + sigproc_printf ("don't worry about signal thread"); + else if (prior_exit_state >= ES_FINAL) sigproc_printf ("already performed"); else { diff --git a/winsup/cygwin/spinlock.h b/winsup/cygwin/spinlock.h new file mode 100644 index 000000000..abf723acc --- /dev/null +++ b/winsup/cygwin/spinlock.h @@ -0,0 +1,40 @@ +/* spinlock.h: Header file for cygwin time-sensitive synchronization primitive. + + Copyright 2010 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _SPINLOCK_H +#define _SPINLOCK_H + +#include "hires.h" + +class spinlock +{ + LONG *locker; + LONG val; +public: + spinlock (LONG& locktest, LONGLONG timeout): + locker (&locktest) + { + if ((val = locktest) == 1) + return; + LONGLONG then = gtod.msecs (); + for (;;) + { + if ((val = InterlockedExchange (locker, -1)) != -1 + || (gtod.msecs () - then) >= timeout) + break; + yield (); + } + } + ~spinlock () {InterlockedExchange (locker, 1);} + operator LONG () const {return val;} +}; + +#endif /*_SPINLOCK_H*/ + diff --git a/winsup/cygwin/sync.h b/winsup/cygwin/sync.h index dfe2c3921..5d66b97af 100644 --- a/winsup/cygwin/sync.h +++ b/winsup/cygwin/sync.h @@ -1,8 +1,6 @@ /* sync.h: Header file for cygwin synchronization primitives. - Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. - - Written by Christopher Faylor + Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. This file is part of Cygwin.