Rename native_mutex to fast_mutex throughout.
Rename pthread_key::save_key_to_buffer to pthread_key::_fixup_before_fork throughout. Rename pthread_key::recreate_key_from_buffer to pthread_key::_fixup_after_fork throughout. * thread.cc (native_mutex::init): Remove. (native_mutex::lock): Ditto. (native_mutex::unlock): Ditto. (pthread::push_cleanup_handler): InterlockedExchangePointer is not needed here. (pthread_rwlock::pthread_rwlock): Initialize readers list mutex. (pthread_rwlock::add_reader): Add reader via List_insert. (pthread_rwlock::lookup_reader): Lock list while walking through. (pthread_cond::init): Locking the init mutex is now void. (pthread_rwlock::init): Ditto. (pthread_mutex::init): Ditto. * thread.h: Include security.h. (fast_mutex): New class. Replacement for native_mutex. (List_insert): New template function. (List_remove): Ditto. (List::List): Initialize synchronising mutex. (List::fixup_after_fork): New method. (List::insert): Add node via List_insert. (List::remove): Remove node via List_remove. (List::pop): Remove. (List::for_each): Lock list while walking through. (List::mx_init): New method. (pthread_mutex::fixup_after_fork): Fixup mutex list after fork. (pthread::fixup_after_fork): Ditto. (pthread_conds::fixup_after_fork): Ditto. (pthread_rwlock::fixup_after_fork): Ditto. (semaphore::fixup_after_fork): Ditto. (pthread_rwlock::readers_mx): New member.
This commit is contained in:
parent
d138220cb0
commit
28194e813e
|
@ -1,3 +1,40 @@
|
|||
2003-10-24 Thomas Pfaff <tpfaff@gmx.net>
|
||||
|
||||
Rename native_mutex to fast_mutex throughout.
|
||||
Rename pthread_key::save_key_to_buffer to
|
||||
pthread_key::_fixup_before_fork throughout.
|
||||
Rename pthread_key::recreate_key_from_buffer to
|
||||
pthread_key::_fixup_after_fork throughout.
|
||||
|
||||
* thread.cc (native_mutex::init): Remove.
|
||||
(native_mutex::lock): Ditto.
|
||||
(native_mutex::unlock): Ditto.
|
||||
(pthread::push_cleanup_handler): InterlockedExchangePointer
|
||||
is not needed here.
|
||||
(pthread_rwlock::pthread_rwlock): Initialize readers list mutex.
|
||||
(pthread_rwlock::add_reader): Add reader via List_insert.
|
||||
(pthread_rwlock::lookup_reader): Lock list while walking through.
|
||||
(pthread_cond::init): Locking the init mutex is now void.
|
||||
(pthread_rwlock::init): Ditto.
|
||||
(pthread_mutex::init): Ditto.
|
||||
* thread.h: Include security.h.
|
||||
(fast_mutex): New class. Replacement for native_mutex.
|
||||
(List_insert): New template function.
|
||||
(List_remove): Ditto.
|
||||
(List::List): Initialize synchronising mutex.
|
||||
(List::fixup_after_fork): New method.
|
||||
(List::insert): Add node via List_insert.
|
||||
(List::remove): Remove node via List_remove.
|
||||
(List::pop): Remove.
|
||||
(List::for_each): Lock list while walking through.
|
||||
(List::mx_init): New method.
|
||||
(pthread_mutex::fixup_after_fork): Fixup mutex list after fork.
|
||||
(pthread::fixup_after_fork): Ditto.
|
||||
(pthread_conds::fixup_after_fork): Ditto.
|
||||
(pthread_rwlock::fixup_after_fork): Ditto.
|
||||
(semaphore::fixup_after_fork): Ditto.
|
||||
(pthread_rwlock::readers_mx): New member.
|
||||
|
||||
2003-10-24 Brian Ford <ford@vss.fsi.com>
|
||||
|
||||
* fhandler.cc (fhandler_base::fcntl): Don't clobber O_APPEND when
|
||||
|
|
|
@ -79,37 +79,6 @@ _reent_winsup ()
|
|||
return _r->_winsup;
|
||||
}
|
||||
|
||||
bool
|
||||
native_mutex::init ()
|
||||
{
|
||||
theHandle = CreateMutex (&sec_none_nih, FALSE, NULL);
|
||||
if (!theHandle)
|
||||
{
|
||||
debug_printf ("CreateMutex failed. %E");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
native_mutex::lock ()
|
||||
{
|
||||
DWORD waitResult = WaitForSingleObject (theHandle, INFINITE);
|
||||
if (waitResult != WAIT_OBJECT_0)
|
||||
{
|
||||
system_printf ("Received unexpected wait result %d on handle %p, %E", waitResult, theHandle);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
native_mutex::unlock ()
|
||||
{
|
||||
if (!ReleaseMutex (theHandle))
|
||||
system_printf ("Received a unexpected result releasing mutex. %E");
|
||||
}
|
||||
|
||||
inline LPCRITICAL_SECTION
|
||||
ResourceLocks::Lock (int _resid)
|
||||
{
|
||||
|
@ -720,7 +689,7 @@ pthread::push_cleanup_handler (__pthread_cleanup_handler *handler)
|
|||
// TODO: do it?
|
||||
api_fatal ("Attempt to push a cleanup handler across threads");
|
||||
handler->next = cleanup_stack;
|
||||
InterlockedExchangePointer (&cleanup_stack, handler);
|
||||
cleanup_stack = handler;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -830,7 +799,7 @@ pthread_condattr::~pthread_condattr ()
|
|||
List<pthread_cond> pthread_cond::conds;
|
||||
|
||||
/* This is used for cond creation protection within a single process only */
|
||||
native_mutex NO_COPY pthread_cond::cond_initialization_lock;
|
||||
fast_mutex NO_COPY pthread_cond::cond_initialization_lock;
|
||||
|
||||
/* We can only be called once.
|
||||
TODO: (no rush) use a non copied memory section to
|
||||
|
@ -1040,7 +1009,7 @@ pthread_rwlockattr::~pthread_rwlockattr ()
|
|||
List<pthread_rwlock> pthread_rwlock::rwlocks;
|
||||
|
||||
/* This is used for rwlock creation protection within a single process only */
|
||||
native_mutex NO_COPY pthread_rwlock::rwlock_initialization_lock;
|
||||
fast_mutex NO_COPY pthread_rwlock::rwlock_initialization_lock;
|
||||
|
||||
/* We can only be called once.
|
||||
TODO: (no rush) use a non copied memory section to
|
||||
|
@ -1055,12 +1024,19 @@ pthread_rwlock::init_mutex ()
|
|||
pthread_rwlock::pthread_rwlock (pthread_rwlockattr *attr) :
|
||||
verifyable_object (PTHREAD_RWLOCK_MAGIC),
|
||||
shared (0), waiting_readers (0), waiting_writers (0), writer (NULL),
|
||||
readers (NULL), mtx (NULL), cond_readers (NULL), cond_writers (NULL),
|
||||
readers (NULL), readers_mx (), mtx (NULL), cond_readers (NULL), cond_writers (NULL),
|
||||
next (NULL)
|
||||
{
|
||||
pthread_mutex *verifyable_mutex_obj = &mtx;
|
||||
pthread_cond *verifyable_cond_obj;
|
||||
|
||||
if (!readers_mx.init ())
|
||||
{
|
||||
thread_printf ("Internal rwlock synchronisation mutex is not valid. this %p", this);
|
||||
magic = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (attr)
|
||||
if (attr->shared != PTHREAD_PROCESS_PRIVATE)
|
||||
{
|
||||
|
@ -1265,34 +1241,28 @@ pthread_rwlock::unlock ()
|
|||
void
|
||||
pthread_rwlock::add_reader (struct RWLOCK_READER *rd)
|
||||
{
|
||||
rd->next = (struct RWLOCK_READER *)
|
||||
InterlockedExchangePointer (&readers, rd);
|
||||
List_insert (readers_mx, readers, rd);
|
||||
}
|
||||
|
||||
void
|
||||
pthread_rwlock::remove_reader (struct RWLOCK_READER *rd)
|
||||
{
|
||||
if (readers == rd)
|
||||
InterlockedExchangePointer (&readers, rd->next);
|
||||
else
|
||||
{
|
||||
struct RWLOCK_READER *temp = readers;
|
||||
while (temp->next && temp->next != rd)
|
||||
temp = temp->next;
|
||||
/* but there may be a race between the loop above and this statement */
|
||||
InterlockedExchangePointer (&temp->next, rd->next);
|
||||
}
|
||||
List_remove (readers_mx, readers, rd);
|
||||
}
|
||||
|
||||
struct pthread_rwlock::RWLOCK_READER *
|
||||
pthread_rwlock::lookup_reader (pthread_t thread)
|
||||
{
|
||||
struct RWLOCK_READER *temp = readers;
|
||||
readers_mx.lock ();
|
||||
|
||||
while (temp && temp->thread != thread)
|
||||
temp = temp->next;
|
||||
struct RWLOCK_READER *cur = readers;
|
||||
|
||||
return temp;
|
||||
while (cur && cur->thread != thread)
|
||||
cur = cur->next;
|
||||
|
||||
readers_mx.unlock ();
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1324,6 +1294,9 @@ pthread_rwlock::_fixup_after_fork ()
|
|||
waiting_readers = 0;
|
||||
waiting_writers = 0;
|
||||
|
||||
if (!readers_mx.init ())
|
||||
api_fatal ("pthread_rwlock::_fixup_after_fork () failed to recreate mutex");
|
||||
|
||||
/* Unlock eventually locked mutex */
|
||||
mtx.unlock ();
|
||||
/*
|
||||
|
@ -1395,13 +1368,13 @@ pthread_key::get () const
|
|||
}
|
||||
|
||||
void
|
||||
pthread_key::save_key_to_buffer ()
|
||||
pthread_key::_fixup_before_fork ()
|
||||
{
|
||||
fork_buf = get ();
|
||||
}
|
||||
|
||||
void
|
||||
pthread_key::recreate_key_from_buffer ()
|
||||
pthread_key::_fixup_after_fork ()
|
||||
{
|
||||
tls_index = TlsAlloc ();
|
||||
if (tls_index == TLS_OUT_OF_INDEXES)
|
||||
|
@ -1496,7 +1469,7 @@ pthread_mutex::can_be_unlocked (pthread_mutex_t const *mutex)
|
|||
List<pthread_mutex> pthread_mutex::mutexes;
|
||||
|
||||
/* This is used for mutex creation protection within a single process only */
|
||||
native_mutex NO_COPY pthread_mutex::mutex_initialization_lock;
|
||||
fast_mutex NO_COPY pthread_mutex::mutex_initialization_lock;
|
||||
|
||||
/* We can only be called once.
|
||||
TODO: (no rush) use a non copied memory section to
|
||||
|
@ -2452,8 +2425,8 @@ pthread_cond::init (pthread_cond_t *cond, const pthread_condattr_t *attr)
|
|||
{
|
||||
if (attr && !pthread_condattr::is_good_object (attr))
|
||||
return EINVAL;
|
||||
if (!cond_initialization_lock.lock ())
|
||||
return EINVAL;
|
||||
|
||||
cond_initialization_lock.lock ();
|
||||
|
||||
if (!is_good_initializer_or_bad_object (cond))
|
||||
{
|
||||
|
@ -2650,8 +2623,8 @@ pthread_rwlock::init (pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr
|
|||
{
|
||||
if (attr && !pthread_rwlockattr::is_good_object (attr))
|
||||
return EINVAL;
|
||||
if (!rwlock_initialization_lock.lock ())
|
||||
return EINVAL;
|
||||
|
||||
rwlock_initialization_lock.lock ();
|
||||
|
||||
if (!is_good_initializer_or_bad_object (rwlock))
|
||||
{
|
||||
|
@ -2844,8 +2817,8 @@ pthread_mutex::init (pthread_mutex_t *mutex,
|
|||
{
|
||||
if (attr && !pthread_mutexattr::is_good_object (attr) || check_valid_pointer (mutex))
|
||||
return EINVAL;
|
||||
if (!mutex_initialization_lock.lock ())
|
||||
return EINVAL;
|
||||
|
||||
mutex_initialization_lock.lock ();
|
||||
|
||||
if (!is_good_initializer_or_bad_object (mutex))
|
||||
{
|
||||
|
|
|
@ -44,6 +44,7 @@ extern "C"
|
|||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <security.h>
|
||||
#define _NOMNTENT_FUNCS
|
||||
#include <mntent.h>
|
||||
|
||||
|
@ -123,14 +124,46 @@ void AssertResourceOwner (int, int);
|
|||
#endif
|
||||
}
|
||||
|
||||
class native_mutex
|
||||
class fast_mutex
|
||||
{
|
||||
public:
|
||||
bool init ();
|
||||
bool lock ();
|
||||
void unlock ();
|
||||
fast_mutex () :
|
||||
lock_counter (0), win32_obj_id (0)
|
||||
{
|
||||
}
|
||||
|
||||
~fast_mutex ()
|
||||
{
|
||||
if(win32_obj_id)
|
||||
CloseHandle (win32_obj_id);
|
||||
}
|
||||
|
||||
bool init ()
|
||||
{
|
||||
win32_obj_id = ::CreateSemaphore (&sec_none_nih, 0, LONG_MAX, NULL);
|
||||
if (!win32_obj_id)
|
||||
{
|
||||
debug_printf ("CreateSemaphore failed. %E");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void lock ()
|
||||
{
|
||||
if (InterlockedIncrement ((long *)&lock_counter) != 1)
|
||||
WaitForSingleObject (win32_obj_id, INFINITE);
|
||||
}
|
||||
|
||||
void unlock ()
|
||||
{
|
||||
if (InterlockedDecrement ((long *)&lock_counter))
|
||||
::ReleaseSemaphore (win32_obj_id, 1, NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE theHandle;
|
||||
unsigned long lock_counter;
|
||||
HANDLE win32_obj_id;
|
||||
};
|
||||
|
||||
class per_process;
|
||||
|
@ -189,51 +222,85 @@ typedef enum
|
|||
verifyable_object_state verifyable_object_isvalid (void const *, long);
|
||||
verifyable_object_state verifyable_object_isvalid (void const *, long, void *);
|
||||
|
||||
template <class list_node> class List {
|
||||
public:
|
||||
template <class list_node> inline void
|
||||
List_insert (fast_mutex &mx, list_node *&head, list_node *node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
mx.lock ();
|
||||
node->next = head;
|
||||
head = node;
|
||||
mx.unlock ();
|
||||
}
|
||||
|
||||
template <class list_node> inline void
|
||||
List_remove (fast_mutex &mx, list_node *&head, list_node *node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
mx.lock ();
|
||||
if (node == head)
|
||||
head = head->next;
|
||||
else if (head)
|
||||
{
|
||||
list_node *cur = head;
|
||||
|
||||
while (cur->next && node != cur->next)
|
||||
cur = cur->next;
|
||||
if (node == cur->next)
|
||||
cur->next = cur->next->next;
|
||||
}
|
||||
mx.unlock ();
|
||||
}
|
||||
|
||||
|
||||
template <class list_node> class List
|
||||
{
|
||||
public:
|
||||
List() : head(NULL)
|
||||
{
|
||||
mx_init ();
|
||||
}
|
||||
|
||||
~List()
|
||||
{
|
||||
}
|
||||
|
||||
void fixup_after_fork ()
|
||||
{
|
||||
mx_init ();
|
||||
}
|
||||
|
||||
void insert (list_node *node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
node->next = (list_node *) InterlockedExchangePointer (&head, node);
|
||||
List_insert (mx, head, node);
|
||||
}
|
||||
|
||||
list_node *remove ( list_node *node)
|
||||
void remove (list_node *node)
|
||||
{
|
||||
if (!node || !head)
|
||||
return NULL;
|
||||
if (node == head)
|
||||
return pop ();
|
||||
|
||||
list_node *result_prev = head;
|
||||
while (result_prev && result_prev->next && !(node == result_prev->next))
|
||||
result_prev = result_prev->next;
|
||||
if (result_prev)
|
||||
return (list_node *)InterlockedExchangePointer (&result_prev->next, result_prev->next->next);
|
||||
return NULL;
|
||||
List_remove (mx, head, node);
|
||||
}
|
||||
|
||||
list_node *pop ()
|
||||
{
|
||||
return (list_node *) InterlockedExchangePointer (&head, head->next);
|
||||
}
|
||||
|
||||
/* poor mans generic programming. */
|
||||
void for_each (void (list_node::*callback) ())
|
||||
{
|
||||
list_node *node = head;
|
||||
while (node)
|
||||
mx.lock ();
|
||||
list_node *cur = head;
|
||||
while (cur)
|
||||
{
|
||||
(node->*callback) ();
|
||||
node = node->next;
|
||||
(cur->*callback) ();
|
||||
cur = cur->next;
|
||||
}
|
||||
mx.unlock ();
|
||||
}
|
||||
|
||||
protected:
|
||||
void mx_init ()
|
||||
{
|
||||
if (!mx.init ())
|
||||
api_fatal ("Could not create mutex for list synchronisation.");
|
||||
}
|
||||
|
||||
fast_mutex mx;
|
||||
list_node *head;
|
||||
};
|
||||
|
||||
|
@ -248,14 +315,15 @@ public:
|
|||
|
||||
pthread_key (void (*)(void *));
|
||||
~pthread_key ();
|
||||
static void fixup_before_fork()
|
||||
static void fixup_before_fork ()
|
||||
{
|
||||
keys.for_each (&pthread_key::save_key_to_buffer);
|
||||
keys.for_each (&pthread_key::_fixup_before_fork);
|
||||
}
|
||||
|
||||
static void fixup_after_fork()
|
||||
static void fixup_after_fork ()
|
||||
{
|
||||
keys.for_each (&pthread_key::recreate_key_from_buffer);
|
||||
keys.fixup_after_fork ();
|
||||
keys.for_each (&pthread_key::_fixup_after_fork);
|
||||
}
|
||||
|
||||
static void run_all_destructors ()
|
||||
|
@ -267,8 +335,8 @@ public:
|
|||
class pthread_key *next;
|
||||
private:
|
||||
static List<pthread_key> keys;
|
||||
void save_key_to_buffer ();
|
||||
void recreate_key_from_buffer ();
|
||||
void _fixup_before_fork ();
|
||||
void _fixup_after_fork ();
|
||||
void (*destructor) (void *);
|
||||
void run_destructor ();
|
||||
void *fork_buf;
|
||||
|
@ -361,6 +429,7 @@ public:
|
|||
class pthread_mutex * next;
|
||||
static void fixup_after_fork ()
|
||||
{
|
||||
mutexes.fixup_after_fork ();
|
||||
mutexes.for_each (&pthread_mutex::_fixup_after_fork);
|
||||
}
|
||||
|
||||
|
@ -373,7 +442,7 @@ private:
|
|||
void _fixup_after_fork ();
|
||||
|
||||
static List<pthread_mutex> mutexes;
|
||||
static native_mutex mutex_initialization_lock;
|
||||
static fast_mutex mutex_initialization_lock;
|
||||
};
|
||||
|
||||
#define WAIT_CANCELED (WAIT_OBJECT_0 + 1)
|
||||
|
@ -447,6 +516,7 @@ public:
|
|||
class pthread *next;
|
||||
static void fixup_after_fork ()
|
||||
{
|
||||
threads.fixup_after_fork ();
|
||||
threads.for_each (&pthread::_fixup_after_fork);
|
||||
}
|
||||
|
||||
|
@ -533,6 +603,7 @@ public:
|
|||
class pthread_cond * next;
|
||||
static void fixup_after_fork ()
|
||||
{
|
||||
conds.fixup_after_fork ();
|
||||
conds.for_each (&pthread_cond::_fixup_after_fork);
|
||||
}
|
||||
|
||||
|
@ -540,7 +611,7 @@ private:
|
|||
void _fixup_after_fork ();
|
||||
|
||||
static List<pthread_cond> conds;
|
||||
static native_mutex cond_initialization_lock;
|
||||
static fast_mutex cond_initialization_lock;
|
||||
};
|
||||
|
||||
class pthread_rwlockattr:public verifyable_object
|
||||
|
@ -573,6 +644,7 @@ public:
|
|||
struct RWLOCK_READER *next;
|
||||
pthread_t thread;
|
||||
} *readers;
|
||||
fast_mutex readers_mx;
|
||||
|
||||
int rdlock ();
|
||||
int tryrdlock ();
|
||||
|
@ -592,6 +664,7 @@ public:
|
|||
class pthread_rwlock * next;
|
||||
static void fixup_after_fork ()
|
||||
{
|
||||
rwlocks.fixup_after_fork ();
|
||||
rwlocks.for_each (&pthread_rwlock::_fixup_after_fork);
|
||||
}
|
||||
|
||||
|
@ -619,7 +692,7 @@ private:
|
|||
|
||||
void _fixup_after_fork ();
|
||||
|
||||
static native_mutex rwlock_initialization_lock;
|
||||
static fast_mutex rwlock_initialization_lock;
|
||||
};
|
||||
|
||||
class pthread_once
|
||||
|
@ -651,6 +724,7 @@ public:
|
|||
class semaphore * next;
|
||||
static void fixup_after_fork ()
|
||||
{
|
||||
semaphores.fixup_after_fork ();
|
||||
semaphores.for_each (&semaphore::_fixup_after_fork);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue