aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorRobert Collins <rbtcollins@hotmail.com>2001-09-11 08:15:39 +0000
committerRobert Collins <rbtcollins@hotmail.com>2001-09-11 08:15:39 +0000
commitf9229ef74bf3ad334534609a17165a4958322ae8 (patch)
tree70cf5ee10cfa40d85271f6a6fed2918c8b9dd349 /winsup
parentc4b7e16dd99c068b307da9115497df5dd8b7fb9a (diff)
downloadnewlib-f9229ef74bf3ad334534609a17165a4958322ae8.zip
newlib-f9229ef74bf3ad334534609a17165a4958322ae8.tar.gz
newlib-f9229ef74bf3ad334534609a17165a4958322ae8.tar.bz2
Tue Sep 11 18:15:00 2001 Robert Collins <rbtcollins@hotmail.com>
* dcrt0.cc (cygwin_finished_initializing): Copy _mtinterf on fork; * fork.cc (fork_child): fixup thread-related structures after fork; * thread.cc (MTinterface::Init): Initialise the new mutex, condition and semaphore lists. (MTinterface::fixup_after_fork): Iterate through each list and fixup the objects. (pthread_cond::pthread_cond): Add this to the condition list. (pthread_cond::~pthread_cond): Remove this from the condition list. (pthread_cond::fixup_after_fork): Recreate as best we can the pre-fork state. (pthread_mutex::pthread_mutex): Add this to the mutex list. (pthread_mutex::~pthread_mutex): Remove this from the mutex list. (pthread_mutex::fixup_after_fork): Recreate as best we can the pre-fork state. (semaphore::semaphore): Store the initial value, and add this to the semaphore list. (semaphore::~semaphore): Remove this from the semaphore list. (semaphore::Post): Increment the current semaphore value. (semaphore::TryWait): Decrement the current semaphore value. (semaphore::Wait): Ditto. (semaphote::fixup_after_fork): Recreate the pre-fork state as best we can. * thread.h (pthread_mutex): New members to allow fixup_after_fork. (pthread_cond): Ditto. (semaphore): Ditto. (MTinterface): New list heads for tracking conds and semaphores.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog23
-rw-r--r--winsup/cygwin/dcrt0.cc2
-rw-r--r--winsup/cygwin/fork.cc2
-rw-r--r--winsup/cygwin/thread.cc136
-rw-r--r--winsup/cygwin/thread.h10
5 files changed, 162 insertions, 11 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 6bdc2fa..8474745 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,26 @@
+Tue Sep 11 18:15:00 2001 Robert Collins <rbtcollins@hotmail.com>
+
+ * dcrt0.cc (cygwin_finished_initializing): Copy _mtinterf on fork;
+ * fork.cc (fork_child): fixup thread-related structures after fork;
+ * thread.cc (MTinterface::Init): Initialise the new mutex, condition and semaphore lists.
+ (MTinterface::fixup_after_fork): Iterate through each list and fixup the objects.
+ (pthread_cond::pthread_cond): Add this to the condition list.
+ (pthread_cond::~pthread_cond): Remove this from the condition list.
+ (pthread_cond::fixup_after_fork): Recreate as best we can the pre-fork state.
+ (pthread_mutex::pthread_mutex): Add this to the mutex list.
+ (pthread_mutex::~pthread_mutex): Remove this from the mutex list.
+ (pthread_mutex::fixup_after_fork): Recreate as best we can the pre-fork state.
+ (semaphore::semaphore): Store the initial value, and add this to the semaphore list.
+ (semaphore::~semaphore): Remove this from the semaphore list.
+ (semaphore::Post): Increment the current semaphore value.
+ (semaphore::TryWait): Decrement the current semaphore value.
+ (semaphore::Wait): Ditto.
+ (semaphote::fixup_after_fork): Recreate the pre-fork state as best we can.
+ * thread.h (pthread_mutex): New members to allow fixup_after_fork.
+ (pthread_cond): Ditto.
+ (semaphore): Ditto.
+ (MTinterface): New list heads for tracking conds and semaphores.
+
Sun Sep 9 22:11:27 2001 Christopher Faylor <cgf@cygnus.com>
* dtable.cc (dtable::fixup_after_fork): Use SetStdHandle appropriately
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 4f278ce..ef03386 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -70,7 +70,7 @@ int cygwin_finished_initializing;
unsigned NO_COPY int signal_shift_subtract = 1;
ResourceLocks _reslock NO_COPY;
-MTinterface _mtinterf NO_COPY;
+MTinterface _mtinterf;
bool NO_COPY _cygwin_testing;
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 3a63e39..ccfc2aa 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -309,6 +309,8 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
if ((*t)->clear_on_fork ())
(*t)->set ();
+ user_data->threadinterface->fixup_after_fork ();
+
/* Initialize signal/process handling */
sigproc_init ();
__pthread_atforkchild ();
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index f05d441..c4d6c05 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -302,6 +302,10 @@ MTinterface::Init (int forked)
if (forked)
return;
+ mutexs = NULL;
+ conds = NULL;
+ semaphores = NULL;
+
/*possible the atfork lists should be inited here as well */
#if 0
@@ -313,6 +317,33 @@ MTinterface::Init (int forked)
#endif
}
+/* This function is called from a single threaded process */
+void
+MTinterface::fixup_after_fork (void)
+{
+ pthread_mutex *mutex = mutexs;
+ debug_printf("mutexs is %x\n",mutexs);
+ while (mutex)
+ {
+ mutex->fixup_after_fork ();
+ mutex = mutex->next;
+ }
+ pthread_cond *cond = conds;
+ debug_printf("conds is %x\n",conds);
+ while (cond)
+ {
+ cond->fixup_after_fork ();
+ cond = cond->next;
+ }
+ semaphore *sem = semaphores;
+ debug_printf("semaphores is %x\n",semaphores);
+ while (sem)
+ {
+ sem->fixup_after_fork ();
+ sem = sem->next;
+ }
+}
+
pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
cancelstate (0), canceltype (0)
{
@@ -402,6 +433,8 @@ pthread_cond::pthread_cond (pthread_condattr *attr):verifyable_object (PTHREAD_C
if (!this->win32_obj_id)
magic = 0;
+ /* threadsafe addition is easy */
+ next = (pthread_cond *)InterlockedExchangePointer (&MT_INTERFACE->conds, this);
}
pthread_cond::~pthread_cond ()
@@ -409,6 +442,17 @@ pthread_cond::~pthread_cond ()
if (win32_obj_id)
CloseHandle (win32_obj_id);
pthread_mutex_destroy (&cond_access);
+ /* I'm not 100% sure the next bit is threadsafe. I think it is... */
+ if (MT_INTERFACE->conds == this)
+ MT_INTERFACE->conds = (pthread_cond *)InterlockedExchangePointer (&MT_INTERFACE->conds, this->next);
+ else
+ {
+ pthread_cond *tempcond = MT_INTERFACE->conds;
+ while (tempcond->next && tempcond->next != this)
+ tempcond = tempcond->next;
+ /* but there may be a race between the loop above and this statement */
+ tempcond->next = (pthread_cond *)InterlockedExchangePointer (&tempcond->next, this->next);
+ }
}
void
@@ -478,6 +522,21 @@ pthread_cond::TimedWait (DWORD dwMilliseconds)
}
}
+void
+pthread_cond::fixup_after_fork ()
+{
+ debug_printf("cond %x in fixup_after_fork\n", this);
+ if (shared != PTHREAD_PROCESS_PRIVATE)
+ api_fatal("doesn't understand PROCESS_SHARED condition variables\n");
+ /* FIXME: duplicate code here and in the constructor. */
+ this->win32_obj_id =::CreateEvent (&sec_none_nih, false, false, NULL);
+ if (!win32_obj_id)
+ api_fatal("failed to create new win32 mutex\n");
+ if (waiting)
+ api_fatal("Forked() while a condition variable has waiting threads.\nReport to cygwin@cygwin.com\n");
+}
+
+
pthread_key::pthread_key (void (*destructor) (void *)):verifyable_object (PTHREAD_KEY_MAGIC)
{
dwTlsIndex = TlsAlloc ();
@@ -536,6 +595,13 @@ pthread_key::get ()
*Isn't duplicated, it's reopened.
*/
+/*FIXME: implement InterlockExchangePointer and get rid of the silly typecasts in pthread_atfork
+ */
+#ifndef InterlockedExchangePointer
+#define InterlockedExchangePointer InterlockedExchange
+#endif
+
+
pthread_mutex::pthread_mutex (pthread_mutexattr *attr):verifyable_object (PTHREAD_MUTEX_MAGIC)
{
/*attr checked in the C call */
@@ -552,6 +618,8 @@ pthread_mutex::pthread_mutex (pthread_mutexattr *attr):verifyable_object (PTHREA
magic = 0;
condwaits = 0;
pshared = PTHREAD_PROCESS_PRIVATE;
+ /* threadsafe addition is easy */
+ next = (pthread_mutex *)InterlockedExchangePointer (&MT_INTERFACE->mutexs, this);
}
pthread_mutex::~pthread_mutex ()
@@ -559,6 +627,17 @@ pthread_mutex::~pthread_mutex ()
if (win32_obj_id)
CloseHandle (win32_obj_id);
win32_obj_id = NULL;
+ /* I'm not 100% sure the next bit is threadsafe. I think it is... */
+ if (MT_INTERFACE->mutexs == this)
+ MT_INTERFACE->mutexs = (pthread_mutex *)InterlockedExchangePointer (&MT_INTERFACE->mutexs, this->next);
+ else
+ {
+ pthread_mutex *tempmutex = MT_INTERFACE->mutexs;
+ while (tempmutex->next && tempmutex->next != this)
+ tempmutex = tempmutex->next;
+ /* but there may be a race between the loop above and this statement */
+ tempmutex->next = (pthread_mutex *)InterlockedExchangePointer (&tempmutex->next, this->next);
+ }
}
int
@@ -579,6 +658,21 @@ pthread_mutex::UnLock ()
return ReleaseMutex (win32_obj_id);
}
+void
+pthread_mutex::fixup_after_fork ()
+{
+ debug_printf("mutex %x in fixup_after_fork\n", this);
+ if (pshared != PTHREAD_PROCESS_PRIVATE)
+ api_fatal("pthread_mutex::fixup_after_fork () doesn'tunderstand PROCESS_SHARED mutex's\n");
+ /* FIXME: duplicate code here and in the constructor. */
+ this->win32_obj_id =::CreateMutex (&sec_none_nih, false, NULL);
+
+ if (!win32_obj_id)
+ api_fatal("pthread_mutex::fixup_after_fork() failed to create new win32 mutex\n");
+ if (condwaits)
+ api_fatal("Forked() while a mutex has condition variables waiting on it.\nReport to cygwin@cygwin.com\n");
+}
+
pthread_mutexattr::pthread_mutexattr ():verifyable_object (PTHREAD_MUTEXATTR_MAGIC),
pshared (PTHREAD_PROCESS_PRIVATE), mutextype (PTHREAD_MUTEX_DEFAULT)
{
@@ -595,19 +689,34 @@ semaphore::semaphore (int pshared, unsigned int value):verifyable_object (SEM_MA
if (!this->win32_obj_id)
magic = 0;
this->shared = pshared;
+ currentvalue = value;
+ /* threadsafe addition is easy */
+ next = (semaphore *)InterlockedExchangePointer (&MT_INTERFACE->semaphores, this);
}
semaphore::~semaphore ()
{
if (win32_obj_id)
CloseHandle (win32_obj_id);
+ /* I'm not 100% sure the next bit is threadsafe. I think it is... */
+ if (MT_INTERFACE->semaphores == this)
+ MT_INTERFACE->semaphores = (semaphore *)InterlockedExchangePointer (&MT_INTERFACE->semaphores, this->next);
+ else
+ {
+ semaphore *tempsem = MT_INTERFACE->semaphores;
+ while (tempsem->next && tempsem->next != this)
+ tempsem = tempsem->next;
+ /* but there may be a race between the loop above and this statement */
+ tempsem->next = (semaphore *)InterlockedExchangePointer (&tempsem->next, this->next);
+ }
}
void
semaphore::Post ()
{
- long pc;
- ReleaseSemaphore (win32_obj_id, 1, &pc);
+ /* we can't use the currentvalue, because the wait functions don't let us access it */
+ ReleaseSemaphore (win32_obj_id, 1, NULL);
+ currentvalue++;
}
int
@@ -618,14 +727,27 @@ semaphore::TryWait ()
*/
if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)
return EAGAIN;
- else
- return 0;
+ currentvalue--;
+ return 0;
}
void
semaphore::Wait ()
{
WaitForSingleObject (win32_obj_id, INFINITE);
+ currentvalue--;
+}
+
+void
+semaphore::fixup_after_fork ()
+{
+ debug_printf("sem %x in fixup_after_fork\n", this);
+ if (shared != PTHREAD_PROCESS_PRIVATE)
+ api_fatal("doesn't understand PROCESS_SHARED semaphores variables\n");
+ /* FIXME: duplicate code here and in the constructor. */
+ this->win32_obj_id =::CreateSemaphore (&sec_none_nih, currentvalue, LONG_MAX, NULL);
+ if (!win32_obj_id)
+ api_fatal("failed to create new win32 semaphore\n");
}
verifyable_object::verifyable_object (long verifyer):
@@ -1052,12 +1174,6 @@ __pthread_atforkchild (void)
}
}
-/*FIXME: implement InterlockExchangePointer and get rid of the silly typecasts below
- */
-#ifndef InterlockedExchangePointer
-#define InterlockedExchangePointer InterlockedExchange
-#endif
-
/*Register a set of functions to run before and after fork.
*prepare calls are called in LI-FC order.
*parent and child calls are called in FI-FC order.
diff --git a/winsup/cygwin/thread.h b/winsup/cygwin/thread.h
index d027830..e810530 100644
--- a/winsup/cygwin/thread.h
+++ b/winsup/cygwin/thread.h
@@ -270,10 +270,12 @@ public:
HANDLE win32_obj_id;
LONG condwaits;
int pshared;
+ class pthread_mutex * next;
int Lock ();
int TryLock ();
int UnLock ();
+ void fixup_after_fork ();
pthread_mutex (unsigned short);
pthread_mutex (pthread_mutexattr *);
@@ -299,9 +301,11 @@ public:
/* to allow atomic behaviour for cond_broadcast */
pthread_mutex_t cond_access;
HANDLE win32_obj_id;
+ class pthread_cond * next;
int TimedWait (DWORD dwMilliseconds);
void BroadCast ();
void Signal ();
+ void fixup_after_fork ();
pthread_cond (pthread_condattr *);
~pthread_cond ();
@@ -319,10 +323,13 @@ class semaphore:public verifyable_object
{
public:
HANDLE win32_obj_id;
+ class semaphore * next;
int shared;
+ long currentvalue;
void Wait ();
void Post ();
int TryWait ();
+ void fixup_after_fork ();
semaphore (int, unsigned int);
~semaphore ();
@@ -358,8 +365,11 @@ public:
// list of mutex's. USE THREADSAFE INSERTS AND DELETES.
class pthread_mutex * mutexs;
+ class pthread_cond * conds;
+ class semaphore * semaphores;
void Init (int);
+ void fixup_after_fork (void);
MTinterface ():reent_index (0), indexallocated (0), threadcount (1)
{