+2004-04-22 Dick Porter <dick@ximian.com>
+
+ * handles.c:
+ * handles-private.h: Reference the handle when it is locked, so
+ that another thread can't blow it away while we're waiting for it
+ to become signalled.
+
+ * wait.c:
+ * timed-thread.c:
+ * threads.c:
+ * sockets.c:
+ * semaphores.c:
+ * mutexes.c:
+ * mono-mutex.c:
+ * io.c:
+ * handles.c:
+ * handles-private.h:
+ * events.c:
+ * error.c:
+ * daemon-messages.c:
+ * critical-sections.c:
+ * atomic.c: Added pthreads cleanup handlers and error asserts
+
+ * shared.c:
+ * handles.c: Fixed the gcc "variable might be used uninitialised"
+ warnings. They can't happen, but gcc doesn't know that
+ g_assert()s don't return.
+
+ Fixed the declaration of _wapi_handle_process_kill() so that it
+ expects the correct type for the pid.
+
+ * threads.c: Removed the TLS_PTHREAD_MUTEX style locking that
+ hasn't been used in ages and just made the code more complex.
+
2004-04-17 Zoltan Varga <vargaz@freemail.hu>
* processes.c: Include <signal.h> for SIGKILL and SIGILL + fix some
#endif
#else
-static pthread_mutex_t spin;
+static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
static mono_once_t spin_once=MONO_ONCE_INIT;
static void spin_init(void)
{
- pthread_mutex_init(&spin, 0);
g_warning("Using non-atomic functions!");
}
gint32 comp)
{
gint32 old;
+ int ret;
mono_once(&spin_once, spin_init);
- pthread_mutex_lock(&spin);
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&spin);
+ ret = pthread_mutex_lock(&spin);
+ g_assert (ret == 0);
old= *dest;
if(old==comp) {
*dest=exch;
}
- pthread_mutex_unlock(&spin);
+ ret = pthread_mutex_unlock(&spin);
+ g_assert (ret == 0);
+
+ pthread_cleanup_pop (0);
return(old);
}
gpointer exch, gpointer comp)
{
gpointer old;
+ int ret;
mono_once(&spin_once, spin_init);
- pthread_mutex_lock(&spin);
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&spin);
+ ret = pthread_mutex_lock(&spin);
+ g_assert (ret == 0);
old= *dest;
if(old==comp) {
*dest=exch;
}
- pthread_mutex_unlock(&spin);
+ ret = pthread_mutex_unlock(&spin);
+ g_assert (ret == 0);
+
+ pthread_cleanup_pop (0);
return(old);
}
gint32 InterlockedIncrement(volatile gint32 *dest)
{
gint32 ret;
+ int thr_ret;
mono_once(&spin_once, spin_init);
- pthread_mutex_lock(&spin);
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&spin);
+ thr_ret = pthread_mutex_lock(&spin);
+ g_assert (thr_ret == 0);
*dest++;
ret= *dest;
- pthread_mutex_unlock(&spin);
+ thr_ret = pthread_mutex_unlock(&spin);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
return(ret);
}
gint32 InterlockedDecrement(volatile gint32 *dest)
{
gint32 ret;
+ int thr_ret;
mono_once(&spin_once, spin_init);
- pthread_mutex_lock(&spin);
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&spin);
+ thr_ret = pthread_mutex_lock(&spin);
+ g_assert (thr_ret == 0);
*dest--;
ret= *dest;
- pthread_mutex_unlock(&spin);
+ thr_ret = pthread_mutex_unlock(&spin);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
return(ret);
}
gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
{
gint32 ret;
+ int thr_ret;
mono_once(&spin_once, spin_init);
- pthread_mutex_lock(&spin);
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&req_mutex);
+ thr_ret = pthread_mutex_lock(&spin);
+ g_assert (thr_ret == 0);
ret=*dest;
*dest=exch;
- pthread_mutex_unlock(&spin);
+ thr_ret = pthread_mutex_unlock(&spin);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
return(ret);
}
gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
{
gpointer ret;
+ int thr_ret;
mono_once(&spin_once, spin_init);
- pthread_mutex_lock(&spin);
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&spin);
+ thr_ret = pthread_mutex_lock(&spin);
+ g_assert (thr_ret == 0);
ret=*dest;
*dest=exch;
- pthread_mutex_unlock(&spin);
+ thr_ret = pthread_mutex_unlock(&spin);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
return(ret);
}
gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
{
gint32 ret;
+ int thr_ret;
mono_once(&spin_once, spin_init);
- pthread_mutex_lock(&spin);
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&spin);
+ thr_ret = pthread_mutex_lock(&spin);
+ g_assert (thr_ret == 0);
ret= *dest;
*dest+=add;
- pthread_mutex_unlock(&spin);
-
+ thr_ret = pthread_mutex_unlock(&spin);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
+
return(ret);
}
static void attr_init(void)
{
- mono_mutexattr_init(&attr);
- mono_mutexattr_settype(&attr, MONO_MUTEX_RECURSIVE);
+ int ret;
+
+ ret = mono_mutexattr_init(&attr);
+ g_assert (ret == 0);
+
+ ret = mono_mutexattr_settype(&attr, MONO_MUTEX_RECURSIVE);
+ g_assert (ret == 0);
}
/**
*/
void InitializeCriticalSection(WapiCriticalSection *section)
{
+ int ret;
+
mono_once(&attr_key_once, attr_init);
- mono_mutex_init(§ion->mutex, &attr);
+ ret = mono_mutex_init(§ion->mutex, &attr);
+ g_assert (ret == 0);
}
/**
*/
void DeleteCriticalSection(WapiCriticalSection *section)
{
- mono_mutex_destroy(§ion->mutex);
+ int ret;
+
+ ret = mono_mutex_destroy(§ion->mutex);
+ g_assert (ret == 0);
}
/**
*/
void LeaveCriticalSection(WapiCriticalSection *section)
{
- mono_mutex_unlock(§ion->mutex);
+ int ret;
+
+ ret = mono_mutex_unlock(§ion->mutex);
+ g_assert (ret == 0);
}
* rely on request turnaround time being minimal anyway, so
* performance shouldnt suffer from the mutex.
*/
- pthread_mutex_lock (&req_mutex);
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&req_mutex);
+ ret = pthread_mutex_lock (&req_mutex);
+ g_assert (ret == 0);
#ifdef HAVE_MSG_NOSIGNAL
ret=sendmsg (fd, msg, MSG_NOSIGNAL);
}
}
- pthread_mutex_unlock (&req_mutex);
+ ret = pthread_mutex_unlock (&req_mutex);
+ g_assert (ret == 0);
+
+ pthread_cleanup_pop (0);
}
/* Send request on fd with filedescriptors, wait for response (called
static void error_init(void)
{
- pthread_key_create(&error_key, NULL);
+ int ret;
+
+ ret = pthread_key_create(&error_key, NULL);
+ g_assert (ret == 0);
}
/**
*/
void SetLastError(guint32 code)
{
+ int ret;
+
/* Set the thread-local error code */
mono_once(&error_key_once, error_init);
- pthread_setspecific(error_key, GUINT_TO_POINTER(code));
+ ret = pthread_setspecific(error_key, GUINT_TO_POINTER(code));
+ g_assert (ret == 0);
}
guint32
struct _WapiHandle_event *event_handle;
gpointer handle;
gboolean ok;
+ gpointer ret = NULL;
+ int thr_ret;
mono_once (&event_ops_once, event_ops_init);
return(NULL);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
(gpointer *)&event_handle, NULL);
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error looking up event handle %p", handle);
- _wapi_handle_unlock_handle (handle);
- return(NULL);
+ goto cleanup;
}
+ ret = handle;
event_handle->manual=manual;
handle);
#endif
- _wapi_handle_unlock_handle (handle);
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
- return(handle);
+ pthread_cleanup_pop (0);
+
+ return(ret);
}
/**
{
struct _WapiHandle_event *event_handle;
gboolean ok;
+ int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
(gpointer *)&event_handle, NULL);
return(FALSE);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION ": Pulsing event handle %p", handle);
_wapi_handle_set_signal_state (handle, TRUE, FALSE);
}
- _wapi_handle_unlock_handle (handle);
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
if(event_handle->manual==TRUE) {
/* For a manual-reset event, we're about to try and
": Obtained write lock on event handle %p", handle);
#endif
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle, handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
_wapi_handle_set_signal_state (handle, FALSE, FALSE);
- _wapi_handle_unlock_handle (handle);
+
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
}
return(TRUE);
{
struct _WapiHandle_event *event_handle;
gboolean ok;
+ int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
(gpointer *)&event_handle, NULL);
handle);
#endif
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
if(_wapi_handle_issignalled (handle)==FALSE) {
-
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION
": No need to reset event handle %p", handle);
#endif
-
- _wapi_handle_unlock_handle (handle);
- return(TRUE);
- }
-
+ } else {
#ifdef DEBUG
- g_message(G_GNUC_PRETTY_FUNCTION
- ": Obtained write lock on event handle %p", handle);
+ g_message(G_GNUC_PRETTY_FUNCTION
+ ": Obtained write lock on event handle %p", handle);
#endif
- _wapi_handle_set_signal_state (handle, FALSE, FALSE);
-
- _wapi_handle_unlock_handle (handle);
+ _wapi_handle_set_signal_state (handle, FALSE, FALSE);
+ }
+
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
return(TRUE);
}
{
struct _WapiHandle_event *event_handle;
gboolean ok;
+ int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_EVENT,
(gpointer *)&event_handle, NULL);
return(FALSE);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION ": Setting event handle %p", handle);
_wapi_handle_set_signal_state (handle, TRUE, FALSE);
}
- _wapi_handle_unlock_handle (handle);
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
return(TRUE);
}
gpointer *thread_handle,
guint32 *pid, guint32 *tid);
-extern gboolean _wapi_handle_process_kill (gpointer process_handle,
- guint32 signo,
+extern gboolean _wapi_handle_process_kill (pid_t pid, guint32 signo,
gint *err);
static inline struct _WapiHandleShared_list *_wapi_handle_get_shared_segment (guint32 segment)
{
struct _WapiHandleShared_list *shared;
+ int thr_ret;
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&_wapi_shared_mutex);
+ thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
+ g_assert (thr_ret == 0);
- pthread_mutex_lock (&_wapi_shared_mutex);
shared=_wapi_shared_data[segment];
- pthread_mutex_unlock (&_wapi_shared_mutex);
+
+ thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
return(shared);
}
static inline struct _WapiHandlePrivate_list *_wapi_handle_get_private_segment (guint32 segment)
{
struct _WapiHandlePrivate_list *priv;
+ int thr_ret;
+
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&_wapi_shared_mutex);
+ thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
+ g_assert (thr_ret == 0);
- pthread_mutex_lock (&_wapi_shared_mutex);
priv=_wapi_private_data[segment];
- pthread_mutex_unlock (&_wapi_shared_mutex);
+
+ thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
return(priv);
}
static inline void _wapi_handle_ensure_mapped (guint32 segment)
{
+ int thr_ret;
+
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": checking segment %d is mapped",
segment);
return;
}
- pthread_mutex_lock (&_wapi_shared_mutex);
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&_wapi_shared_mutex);
+ thr_ret = pthread_mutex_lock (&_wapi_shared_mutex);
+ g_assert (thr_ret == 0);
if(segment>=_wapi_shm_mapped_segments) {
/* Need to extend the arrays. We can't use g_renew
}
}
- pthread_mutex_unlock (&_wapi_shared_mutex);
+ thr_ret = pthread_mutex_unlock (&_wapi_shared_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
}
static inline void _wapi_handle_segment (gpointer handle, guint32 *segment,
guint32 idx;
guint32 segment;
struct _WapiHandleShared *shared_handle;
+ int thr_ret;
_wapi_handle_segment (handle, &segment, &idx);
shared_handle=&_wapi_handle_get_shared_segment (segment)->handles[idx];
shared_handle->signalled=state;
if(broadcast==TRUE) {
- pthread_cond_broadcast (&shared_handle->signal_cond);
+ thr_ret = pthread_cond_broadcast (&shared_handle->signal_cond);
+ g_assert (thr_ret == 0);
} else {
- pthread_cond_signal (&shared_handle->signal_cond);
+ thr_ret = pthread_cond_signal (&shared_handle->signal_cond);
+ g_assert (thr_ret == 0);
}
/* Tell everyone blocking on multiple handles that something
#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
{
struct _WapiHandleShared_list *segment0=_wapi_handle_get_shared_segment (0);
- mono_mutex_lock (&segment0->signal_mutex);
- pthread_cond_broadcast (&segment0->signal_cond);
- mono_mutex_unlock (&segment0->signal_mutex);
+
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
+ thr_ret = mono_mutex_lock (&segment0->signal_mutex);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
}
#else
{
g_message (G_GNUC_PRETTY_FUNCTION ": lock global signal mutex");
#endif
- mono_mutex_lock (&segment0->signal_mutex);
- pthread_cond_broadcast (&segment0->signal_cond);
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup, (void *)&segment0->signal_mutex);
+ thr_ret = mono_mutex_lock (&segment0->signal_mutex);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_broadcast (&segment0->signal_cond);
+ g_assert (thr_ret == 0);
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
#endif
- mono_mutex_unlock (&segment0->signal_mutex);
+ thr_ret = mono_mutex_unlock (&segment0->signal_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
}
#endif /* _POSIX_THREAD_PROCESS_SHARED */
} else {
#endif /* _POSIX_THREAD_PROCESS_SHARED */
}
-static inline int _wapi_handle_unlock_signal_mutex (void)
+/* the parameter makes it easier to call from a pthread cleanup handler */
+static inline int _wapi_handle_unlock_signal_mutex (void *unused)
{
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": unlock global signal mutex");
g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
#endif
+ _wapi_handle_ref (handle);
+
_wapi_handle_segment (handle, &segment, &idx);
return(mono_mutex_lock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
{
guint32 idx;
guint32 segment;
+ int ret;
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
_wapi_handle_segment (handle, &segment, &idx);
- return(mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex));
+ ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+
+ _wapi_handle_unref (handle);
+
+ return(ret);
}
#endif /* _WAPI_HANDLES_PRIVATE_H_ */
struct sockaddr_un shared_socket_address;
gboolean tried_once=FALSE;
int ret;
-
+ int thr_ret;
+
_wapi_shared_data=g_new0 (struct _WapiHandleShared_list *, 1);
_wapi_private_data=g_new0 (struct _WapiHandlePrivate_list *, 1);
_wapi_private_data[0]=g_new0 (struct _WapiHandlePrivate_list, 1);
_wapi_shm_mapped_segments=1;
- pthread_mutexattr_init (&mutex_shared_attr);
- pthread_condattr_init (&cond_shared_attr);
-
+ thr_ret = pthread_mutexattr_init (&mutex_shared_attr);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_condattr_init (&cond_shared_attr);
+ g_assert (thr_ret == 0);
+
#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- pthread_mutexattr_setpshared (&mutex_shared_attr,
- PTHREAD_PROCESS_SHARED);
- pthread_condattr_setpshared (&cond_shared_attr,
- PTHREAD_PROCESS_SHARED);
+ thr_ret = pthread_mutexattr_setpshared (&mutex_shared_attr,
+ PTHREAD_PROCESS_SHARED);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_condattr_setpshared (&cond_shared_attr,
+ PTHREAD_PROCESS_SHARED);
+ g_assert (thr_ret == 0);
#else
- pthread_cond_init(&_wapi_private_data[0]->signal_cond, NULL);
- mono_mutex_init(&_wapi_private_data[0]->signal_mutex, NULL);
+ thr_ret = pthread_cond_init(&_wapi_private_data[0]->signal_cond, NULL);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_mutex_init(&_wapi_private_data[0]->signal_mutex, NULL);
+ g_assert (thr_ret == 0);
#endif
}
guint32 segment, idx;
guint32 i, j;
static guint32 last=1;
+ int thr_ret;
/* A linear scan should be fast enough. Start from the last
* allocation, assuming that handles are allocated more often
shared->type=type;
shared->signalled=FALSE;
#if defined(_POSIX_THREAD_PROCESS_SHARED) && _POSIX_THREAD_PROCESS_SHARED != -1
- mono_mutex_init (&shared->signal_mutex, &mutex_shared_attr);
- pthread_cond_init (&shared->signal_cond, &cond_shared_attr);
+ thr_ret = mono_mutex_init (&shared->signal_mutex, &mutex_shared_attr);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_init (&shared->signal_cond, &cond_shared_attr);
+ g_assert (thr_ret == 0);
#else
- pthread_cond_init(&shared->signal_cond, NULL);
- mono_mutex_init(&shared->signal_mutex, NULL);
+ thr_ret = pthread_cond_init(&shared->signal_cond, NULL);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_mutex_init(&shared->signal_mutex, NULL);
+ g_assert (thr_ret == 0);
#endif
return(_wapi_handle_index (i, j));
{
static mono_once_t shared_init_once = MONO_ONCE_INIT;
static pthread_mutex_t scan_mutex=PTHREAD_MUTEX_INITIALIZER;
- guint32 handle_idx, idx, segment;
+ guint32 handle_idx = 0, idx, segment;
gpointer handle;
WapiHandleRequest new={0};
WapiHandleResponse new_resp={0};
#if HAVE_BOEHM_GC
gboolean tried_collect=FALSE;
#endif
+ int thr_ret;
mono_once (&shared_init_once, shared_init);
g_assert_not_reached ();
}
} else {
- pthread_mutex_lock (&scan_mutex);
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&scan_mutex);
+ thr_ret = pthread_mutex_lock (&scan_mutex);
+ g_assert (thr_ret == 0);
+
handle_idx=_wapi_handle_new_internal (type);
if(handle_idx==0) {
/* Try and get a new segment, and have another go */
_wapi_handle_segment (GUINT_TO_POINTER (handle_idx), &segment, &idx);
_wapi_handle_get_shared_segment (segment)->handles[idx].ref++;
- pthread_mutex_unlock (&scan_mutex);
+
+ thr_ret = pthread_mutex_unlock (&scan_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
}
if(handle_idx==0) {
}
#if !defined(_POSIX_THREAD_PROCESS_SHARED) || _POSIX_THREAD_PROCESS_SHARED == -1
- mono_mutex_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex, &mutex_shared_attr);
- pthread_cond_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, &cond_shared_attr);
+ thr_ret = mono_mutex_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex, &mutex_shared_attr);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_init (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond, &cond_shared_attr);
+ g_assert (thr_ret == 0);
#endif
handle=GUINT_TO_POINTER (handle_idx);
gpointer *shared, gpointer *private)
{
struct _WapiHandleShared *shared_handle_data;
- struct _WapiHandlePrivate *private_handle_data;
+ struct _WapiHandlePrivate *private_handle_data = NULL;
guint32 idx;
guint32 segment;
}
}
+/* The handle must not be locked on entry to this function */
void _wapi_handle_unref (gpointer handle)
{
guint32 idx, segment;
- gboolean destroy;
-
+ gboolean destroy = FALSE;
+ int thr_ret;
+
_wapi_handle_segment (handle, &segment, &idx);
if(shared==TRUE) {
if(shared==FALSE) {
_wapi_handle_ops_close_shared (handle);
- mono_mutex_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
- pthread_cond_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond);
memset (&_wapi_handle_get_shared_segment (segment)->handles[idx].u, '\0', sizeof(_wapi_handle_get_shared_segment (segment)->handles[idx].u));
-
- }
- else {
- mono_mutex_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
- pthread_cond_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond);
}
_wapi_handle_ops_close_private (handle);
_wapi_handle_get_shared_segment (segment)->handles[idx].type=WAPI_HANDLE_UNUSED;
+
+ /* Destroy the mutex and cond var. We hope nobody
+ * tried to grab them between the handle unlock and
+ * now, but pthreads doesn't have a
+ * "unlock_and_destroy" atomic function.
+ */
+ thr_ret = mono_mutex_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_destroy (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_cond);
+ g_assert (thr_ret == 0);
}
}
static guint32 _wapi_handle_scratch_locate_space (guint32 bytes)
{
guint32 idx=0, last_idx=0;
- struct _WapiScratchHeader *hdr, *last_hdr;
+ struct _WapiScratchHeader *hdr, *last_hdr = NULL;
gboolean last_was_free=FALSE;
guchar *storage=_wapi_shared_scratch->scratch_data;
guint32 _wapi_handle_scratch_store (gconstpointer data, guint32 bytes)
{
- guint32 idx, store_bytes;
+ guint32 idx = 0, store_bytes;
gboolean remap;
-
+ int thr_ret;
+ guint32 ret = 0;
+
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": storing %d bytes", bytes);
#endif
/* Align bytes to 32 bits (needed for sparc at least) */
store_bytes = (((bytes) + 3) & (~3));
- pthread_mutex_lock (&_wapi_scratch_mutex);
-
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&_wapi_scratch_mutex);
+ thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
+ g_assert (thr_ret == 0);
+
if(shared==TRUE) {
WapiHandleRequest scratch={0};
WapiHandleResponse scratch_resp={0};
idx=_wapi_handle_scratch_store_internal (store_bytes, &remap);
if(idx==0) {
/* Failed to allocate space */
- pthread_mutex_unlock (&_wapi_scratch_mutex);
- return(0);
+ goto cleanup;
}
}
-
+ ret = idx;
+
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION
": stored [%s] at %d (len %d, aligned len %d)",
memcpy (&_wapi_shared_scratch->scratch_data[idx], data, bytes);
- pthread_mutex_unlock (&_wapi_scratch_mutex);
+cleanup:
+ thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
- return(idx);
+ return(ret);
}
guint32 _wapi_handle_scratch_store_string_array (gchar **data)
struct _WapiScratchHeader *hdr;
gpointer ret;
guchar *storage;
+ int thr_ret;
if(idx < HDRSIZE || idx > _wapi_shared_scratch->data_len) {
return(NULL);
}
- pthread_mutex_lock (&_wapi_scratch_mutex);
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&_wapi_scratch_mutex);
+ thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
+ g_assert (thr_ret == 0);
storage=_wapi_shared_scratch->scratch_data;
ret=g_malloc0 (hdr->length+1);
memcpy (ret, &storage[idx], hdr->length);
- pthread_mutex_unlock (&_wapi_scratch_mutex);
+ thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
return(ret);
}
{
struct _WapiScratchHeader *hdr;
guchar *storage;
+ int thr_ret;
if(idx < HDRSIZE || idx > _wapi_shared_scratch->data_len) {
return;
}
- pthread_mutex_lock (&_wapi_scratch_mutex);
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&_wapi_scratch_mutex);
+ thr_ret = pthread_mutex_lock (&_wapi_scratch_mutex);
+ g_assert (thr_ret == 0);
storage=_wapi_shared_scratch->scratch_data;
* free, but the _store() function will do that anyway.
*/
- pthread_mutex_unlock (&_wapi_scratch_mutex);
+ thr_ret = pthread_mutex_unlock (&_wapi_scratch_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
}
void _wapi_handle_scratch_delete (guint32 idx)
{
guint32 count, i, iter=0;
gboolean ret;
+ int thr_ret;
/* Lock all the handles, with backoff */
again:
while(i--) {
_wapi_handle_segment (handles[i], &segment, &idx);
- mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+ thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+ g_assert (thr_ret == 0);
}
/* If iter ever reaches 100 the nanosleep will
for(i=0; i<numhandles; i++) {
guint32 idx, segment;
+ _wapi_handle_ref (handles[i]);
+
_wapi_handle_segment (handles[i], &segment, &idx);
#ifdef DEBUG
void _wapi_handle_unlock_handles (guint32 numhandles, gpointer *handles)
{
guint32 i;
+ int thr_ret;
for(i=0; i<numhandles; i++) {
guint32 idx, segment;
handles[i]);
#endif
- mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+ thr_ret = mono_mutex_unlock (&_wapi_handle_get_shared_segment (segment)->handles[idx].signal_mutex);
+ g_assert (thr_ret == 0);
+
+ _wapi_handle_unref (handles[i]);
}
}
}
gboolean
-_wapi_handle_process_kill (gpointer process, guint32 signo, gint *errnum)
+_wapi_handle_process_kill (pid_t process, guint32 signo, gint *errnum)
{
WapiHandleRequest killproc = {0};
WapiHandleResponse killprocresp = {0};
}
killproc.type = WapiHandleRequestType_ProcessKill;
- killproc.u.process_kill.pid = GPOINTER_TO_UINT (process);
+ killproc.u.process_kill.pid = process;
killproc.u.process_kill.signo = signo;
_wapi_daemon_request_response (daemon_sock, &killproc, &killprocresp);
mode_t perms=convert_perms(sharemode);
gchar *filename;
int ret;
-
+ int thr_ret;
+ gpointer cf_ret = INVALID_HANDLE_VALUE;
+
mono_once (&io_ops_once, io_ops_init);
if(name==NULL) {
return(INVALID_HANDLE_VALUE);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
(gpointer *)&file_handle,
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error looking up file handle %p", handle);
- _wapi_handle_unlock_handle (handle);
- g_free (filename);
-
- return(INVALID_HANDLE_VALUE);
+ goto cleanup;
}
+ cf_ret = handle;
file_private_handle->fd=ret;
file_private_handle->assigned=TRUE;
file_private_handle->fd);
#endif
- _wapi_handle_unlock_handle (handle);
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
g_free (filename);
- return(handle);
+ return(cf_ret);
}
/**
struct _WapiHandle_file *file_handle;
struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
- gpointer handle;
+ gpointer handle, ret = NULL;
int flags;
+ int thr_ret;
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION ": creating standard handle type %s",
return(NULL);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_CONSOLE,
(gpointer *)&file_handle,
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error looking up console handle %p", handle);
- _wapi_handle_unlock_handle (handle);
- return(NULL);
+ goto cleanup;
}
+ ret = handle;
file_private_handle->fd=fd;
file_private_handle->assigned=TRUE;
handle, file_private_handle->fd);
#endif
- _wapi_handle_unlock_handle (handle);
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
- return(handle);
+ return(ret);
}
static void stdhandle_init (void)
static void file_once_init (void)
{
- pthread_key_create (&file_key, NULL);
+ int ret;
+
+ ret = pthread_key_create (&file_key, NULL);
+ g_assert (ret == 0);
}
static int file_select (const struct dirent *dir)
gpointer FindFirstFile (const gunichar2 *pattern, WapiFindData *find_data)
{
struct _WapiHandlePrivate_find *find_handle;
- gpointer handle;
+ gpointer handle, find_ret = INVALID_HANDLE_VALUE;
gboolean ok;
gchar *utf8_pattern = NULL, *dir_part, *entry_part;
int result;
+ int thr_ret;
+ gboolean unref = FALSE;
mono_once (&file_key_once, file_once_init);
return(INVALID_HANDLE_VALUE);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
(gpointer *)&find_handle);
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error looking up find handle %p", handle);
- _wapi_handle_unlock_handle (handle);
g_free (utf8_pattern);
-
- return(INVALID_HANDLE_VALUE);
+ goto cleanup;
}
/* The pattern can specify a directory or a set of files.
}
g_free (dir_part);
- _wapi_handle_unlock_handle (handle);
- _wapi_handle_unref (handle);
- return(INVALID_HANDLE_VALUE);
+
+ unref = TRUE;
+
+ goto cleanup;
}
#ifdef DEBUG
find_handle->num = result;
find_handle->count = 0;
- if (!FindNextFile (handle, find_data)) {
- _wapi_handle_unlock_handle (handle);
+ find_ret = handle;
+
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ /* FindNextFile has to be called after unlocking the handle,
+ * because it wants to lock the handle itself
+ */
+ if (find_ret != INVALID_HANDLE_VALUE &&
+ !FindNextFile (handle, find_data)) {
FindClose (handle);
SetLastError (ERROR_NO_MORE_FILES);
- return(INVALID_HANDLE_VALUE);
}
- _wapi_handle_unlock_handle (handle);
-
- return (handle);
+ /* Must not call _wapi_handle_unref() with the handle already
+ * locked
+ */
+ if (unref) {
+ _wapi_handle_unref (handle);
+ }
+
+ return (find_ret);
}
gboolean FindNextFile (gpointer handle, WapiFindData *find_data)
gunichar2 *utf16_basename;
time_t create_time;
glong bytes;
+ int thr_ret;
+ gboolean ret = FALSE;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
(gpointer *)&find_handle);
return(FALSE);
}
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
retry:
if (find_handle->count >= find_handle->num) {
SetLastError (ERROR_NO_MORE_FILES);
- return FALSE;
+ goto cleanup;
}
/* stat next match */
#endif
g_free (filename);
- SetLastError (ERROR_NO_MORE_FILES);
- return FALSE;
+ goto retry;
}
/* Check for dangling symlinks, and ignore them (principle of
g_free (utf8_filename);
goto retry;
}
-
+ ret = TRUE;
+
/* utf16 is 2 * utf8 */
bytes *= 2;
g_free (utf8_filename);
g_free (utf16_basename);
- return TRUE;
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ return(ret);
}
/**
struct _WapiHandlePrivate_find *find_handle;
gboolean ok;
int i;
+ int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_FIND, NULL,
(gpointer *)&find_handle);
SetLastError (ERROR_INVALID_HANDLE);
return(FALSE);
}
+
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
for(i = 0; i < find_handle->num; i++) {
free (find_handle->namelist[i]);
}
free (find_handle->namelist);
g_free (find_handle->dir_part);
+
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
_wapi_handle_unref (handle);
-
- return TRUE;
+
+ return(TRUE);
}
/**
gboolean ok;
int filedes[2];
int ret;
+ int thr_ret;
+ gboolean unref_read = FALSE, unref_write = FALSE;
+ gboolean cp_ret = FALSE;
mono_once (&io_ops_once, io_ops_init);
return(FALSE);
}
- _wapi_handle_lock_handle (read_handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ read_handle);
+ thr_ret = _wapi_handle_lock_handle (read_handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (read_handle, WAPI_HANDLE_PIPE,
(gpointer *)&pipe_read_handle,
(gpointer *)&pipe_read_private_handle);
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle);
- _wapi_handle_unlock_handle (read_handle);
close (filedes[0]);
close (filedes[1]);
- return(FALSE);
+ goto cleanup;
}
write_handle=_wapi_handle_new (WAPI_HANDLE_PIPE);
if(write_handle==_WAPI_HANDLE_INVALID) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error creating pipe write handle");
- _wapi_handle_unlock_handle (read_handle);
- _wapi_handle_unref (read_handle);
+ unref_read = TRUE;
close (filedes[0]);
close (filedes[1]);
- return(FALSE);
+ goto cleanup;
}
- _wapi_handle_lock_handle (write_handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ write_handle);
+ thr_ret = _wapi_handle_lock_handle (write_handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (write_handle, WAPI_HANDLE_PIPE,
(gpointer *)&pipe_write_handle,
(gpointer *)&pipe_write_private_handle);
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION ": error looking up pipe handle %p", read_handle);
- _wapi_handle_unlock_handle (read_handle);
- _wapi_handle_unref (read_handle);
- _wapi_handle_unlock_handle (write_handle);
+ unref_read = TRUE;
+ unref_write = TRUE;
+
close (filedes[0]);
close (filedes[1]);
- return(FALSE);
+ goto write_cleanup;
}
+ cp_ret = TRUE;
pipe_read_private_handle->fd=filedes[0];
pipe_read_private_handle->assigned=TRUE;
*writepipe=write_handle;
- _wapi_handle_unlock_handle (read_handle);
- _wapi_handle_unlock_handle (write_handle);
-
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION
": Returning pipe: read handle %p, write handle %p",
read_handle, write_handle);
#endif
- return(TRUE);
+write_cleanup:
+ thr_ret =_wapi_handle_unlock_handle (write_handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+cleanup:
+ thr_ret =_wapi_handle_unlock_handle (read_handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ /* Must not call _wapi_handle_unref() with the handle already
+ * locked
+ */
+ if (unref_read) {
+ _wapi_handle_unref (read_handle);
+ }
+ if (unref_write) {
+ _wapi_handle_unref (write_handle);
+ }
+
+ return(cp_ret);
}
guint32 GetTempPath (guint32 len, gunichar2 *buf)
struct _WapiHandle_file *file_handle;
struct _WapiHandlePrivate_file *file_private_handle;
gboolean ok;
+ int thr_ret;
+ gboolean ret = FALSE;
ok = _wapi_lookup_handle (handle, WAPI_HANDLE_FILE,
(gpointer *) &file_handle,
return FALSE;
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
+
if (file_private_handle->callback != NULL) {
SetLastError (ERROR_INVALID_PARAMETER);
- return FALSE;
+ goto cleanup;
}
-
+ ret = TRUE;
+
file_private_handle->callback = callback;
- _wapi_handle_unlock_handle (handle);
- return TRUE;
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ return(ret);
}
int
mono_once (mono_once_t *once, void (*once_init) (void))
{
+ int thr_ret;
+
if (!once->complete) {
- pthread_mutex_lock (&once->mutex);
+ pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+ (void *)&once->mutex);
+ thr_ret = pthread_mutex_lock (&once->mutex);
+ g_assert (thr_ret == 0);
+
if (!once->complete) {
once_init ();
once->complete = TRUE;
}
- pthread_mutex_unlock (&once->mutex);
+ thr_ret = pthread_mutex_unlock (&once->mutex);
+ g_assert (thr_ret == 0);
+
+ pthread_cleanup_pop (0);
}
return 0;
int
mono_mutex_init (mono_mutex_t *mutex, const mono_mutexattr_t *attr)
{
+ int ret;
+ int thr_ret;
+
mutex->waiters = 0;
mutex->depth = 0;
mutex->owner = MONO_THREAD_NONE;
if (!attr || attr->type == MONO_MUTEX_NORMAL) {
mutex->type = MONO_MUTEX_NORMAL;
- pthread_mutex_init (&mutex->mutex, NULL);
+ ret = pthread_mutex_init (&mutex->mutex, NULL);
} else {
mutex->type = MONO_MUTEX_RECURSIVE;
- pthread_mutex_init (&mutex->mutex, NULL);
- pthread_cond_init (&mutex->cond, NULL);
+ ret = pthread_mutex_init (&mutex->mutex, NULL);
+ thr_ret = pthread_cond_init (&mutex->cond, NULL);
+ g_assert (thr_ret == 0);
}
- return 0;
+ return(ret);
}
int
break;
} else {
mutex->waiters++;
- if (pthread_cond_wait (&mutex->cond, &mutex->mutex) == -1)
+ if (pthread_cond_wait (&mutex->cond, &mutex->mutex) != 0)
return EINVAL;
mutex->waiters--;
}
int
mono_mutex_unlock (mono_mutex_t *mutex)
{
+ int thr_ret;
+
switch (mutex->type) {
case MONO_MUTEX_NORMAL:
return pthread_mutex_unlock (&mutex->mutex);
mutex->depth--;
if (mutex->depth == 0) {
mutex->owner = MONO_THREAD_NONE;
- if (mutex->waiters > 0)
- pthread_cond_signal (&mutex->cond);
+ if (mutex->waiters > 0) {
+ thr_ret = pthread_cond_signal (&mutex->cond);
+ g_assert (thr_ret == 0);
+ }
}
return pthread_mutex_unlock (&mutex->mutex);
mono_mutex_destroy (mono_mutex_t *mutex)
{
int ret = 0;
+ int thr_ret;
switch (mutex->type) {
case MONO_MUTEX_NORMAL:
break;
case MONO_MUTEX_RECURSIVE:
if ((ret = pthread_mutex_destroy (&mutex->mutex)) == 0) {
- pthread_cond_destroy (&mutex->cond);
+ thr_ret = pthread_cond_destroy (&mutex->cond);
+ g_assert (thr_ret == 0);
}
}
#endif /* USE_MONO_MUTEX */
+/* This is a function so it can be passed to pthread_cleanup_push -
+ * that is a macro and giving it a macro as a parameter breaks.
+ */
+static inline int mono_mutex_unlock_in_cleanup (mono_mutex_t *mutex)
+{
+ return(mono_mutex_unlock (mutex));
+}
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
gpointer handle;
gboolean ok;
gchar *utf8_name;
+ int thr_ret;
+ gpointer ret = NULL;
mono_once (&mutex_ops_once, mutex_ops_init);
+ /* w32 seems to guarantee that opening named mutexes can't
+ * race each other
+ */
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&named_mutex_mutex);
+ thr_ret = mono_mutex_lock (&named_mutex_mutex);
+ g_assert (thr_ret == 0);
+
if(name!=NULL) {
utf8_name=g_utf16_to_utf8 (name, -1, NULL, NULL, NULL);
- /* w32 seems to guarantee that opening named mutexes can't
- * race each other
- */
- mono_mutex_lock (&named_mutex_mutex);
} else {
utf8_name=NULL;
}
* object.
*/
g_free (utf8_name);
- mono_mutex_unlock (&named_mutex_mutex);
SetLastError (ERROR_INVALID_HANDLE);
- return(NULL);
+ goto cleanup;
} else if (handle!=NULL) {
g_free (utf8_name);
- mono_mutex_unlock (&named_mutex_mutex);
_wapi_handle_ref (handle);
- return(handle);
+ ret = handle;
+ goto cleanup;
}
/* Otherwise fall through to create the mutex. */
}
if(utf8_name!=NULL) {
g_free (utf8_name);
}
- if(name!=NULL) {
- mono_mutex_unlock (&named_mutex_mutex);
- }
-
- return(NULL);
+ goto cleanup;
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
(gpointer *)&mutex_handle, NULL);
g_free (utf8_name);
}
- if(name!=NULL) {
- mono_mutex_unlock (&named_mutex_mutex);
- }
-
- _wapi_handle_unlock_handle (handle);
- return(NULL);
+ goto handle_cleanup;
}
-
+ ret = handle;
+
if(utf8_name!=NULL) {
mutex_handle->sharedns.name=_wapi_handle_scratch_store (
utf8_name, strlen (utf8_name));
handle);
#endif
- _wapi_handle_unlock_handle (handle);
-
if(utf8_name!=NULL) {
g_free (utf8_name);
}
+
+handle_cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
- if(name!=NULL) {
- mono_mutex_unlock (&named_mutex_mutex);
- }
-
- return(handle);
+cleanup:
+ thr_ret = mono_mutex_unlock (&named_mutex_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ return(ret);
}
/**
gboolean ok;
pthread_t tid=pthread_self();
pid_t pid=getpid ();
+ int thr_ret;
+ gboolean ret = FALSE;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_MUTEX,
(gpointer *)&mutex_handle, NULL);
return(FALSE);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION ": Releasing mutex handle %p",
g_message(G_GNUC_PRETTY_FUNCTION ": We don't own mutex handle %p (owned by %d:%ld, me %d:%ld)", handle, mutex_handle->pid, mutex_handle->tid, pid, tid);
#endif
- _wapi_handle_unlock_handle (handle);
- return(FALSE);
+ goto cleanup;
}
-
+ ret = TRUE;
+
/* OK, we own this mutex */
mutex_handle->recursion--;
_wapi_handle_set_signal_state (handle, TRUE, FALSE);
}
- _wapi_handle_unlock_handle (handle);
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
- return(TRUE);
+ return(ret);
}
struct _WapiHandle_sem *sem_handle;
gpointer handle;
gboolean ok;
+ int thr_ret;
+ gpointer ret = NULL;
mono_once (&sem_ops_once, sem_ops_init);
return(NULL);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
(gpointer *)&sem_handle, NULL);
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error lookup up semaphore handle %p", handle);
- _wapi_handle_unlock_handle (handle);
- return(NULL);
+ goto cleanup;
}
-
+ ret = handle;
+
sem_handle->val=initial;
sem_handle->max=max;
initial, max);
#endif
- _wapi_handle_unlock_handle (handle);
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
- return(handle);
+ return(ret);
}
/**
struct _WapiHandle_sem *sem_handle;
gboolean ok;
gboolean ret=FALSE;
+ int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SEM,
(gpointer *)&sem_handle, NULL);
return(FALSE);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION ": sem %p val %d count %d",
#endif
end:
- _wapi_handle_unlock_handle (handle);
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
return(ret);
}
guchar *_wapi_shm_file (_wapi_shm_t type, guint32 segment)
{
static guchar file[_POSIX_PATH_MAX];
- guchar *name, *filename, *dir, *wapi_dir;
+ guchar *name = NULL, *filename, *dir, *wapi_dir;
gchar machine_name[256];
if (gethostname(machine_name, sizeof(machine_name)) != 0)
{
int fd;
struct stat statbuf;
- guint32 wanted_size;
+ guint32 wanted_size = 0;
if(created) {
*created=FALSE;
static void error_init(void)
{
- pthread_key_create(&error_key, NULL);
+ int ret;
+
+ ret = pthread_key_create(&error_key, NULL);
+ g_assert (ret == 0);
}
void WSASetLastError(int error)
{
+ int ret;
+
mono_once(&error_key_once, error_init);
- pthread_setspecific(error_key, GINT_TO_POINTER(error));
+ ret = pthread_setspecific(error_key, GINT_TO_POINTER(error));
+ g_assert (ret == 0);
}
int WSAGetLastError(void)
gpointer new_handle;
gboolean ok;
int fd;
+ int thr_ret;
+ guint32 ret = INVALID_SOCKET;
if(startup_count==0) {
WSASetLastError(WSANOTINITIALISED);
return(INVALID_SOCKET);
}
- _wapi_handle_lock_handle (new_handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ new_handle);
+ thr_ret = _wapi_handle_lock_handle (new_handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
(gpointer *)&new_socket_private_handle);
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error looking up socket handle 0x%x", handle);
- _wapi_handle_unlock_handle (new_handle);
- return(INVALID_SOCKET);
+ goto cleanup;
}
+ ret = GPOINTER_TO_UINT (new_handle);
new_socket_private_handle->fd=fd;
new_handle, new_socket_private_handle->fd);
#endif
- _wapi_handle_unlock_handle (new_handle);
-
- return(GPOINTER_TO_UINT (new_handle));
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (new_handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ return(ret);
}
int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen)
gpointer handle;
gboolean ok;
int fd;
+ int thr_ret;
+ guint32 ret = INVALID_SOCKET;
fd=socket(domain, type, protocol);
if (fd==-1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) {
return(INVALID_SOCKET);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
(gpointer *)&socket_private_handle);
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error looking up socket handle %p", handle);
- _wapi_handle_unlock_handle (handle);
- return(INVALID_SOCKET);
+ goto cleanup;
}
+ ret = GPOINTER_TO_UINT (handle);
socket_private_handle->fd=fd;
socket_private_handle->fd);
#endif
- _wapi_handle_unlock_handle (handle);
-
- return(GPOINTER_TO_UINT (handle));
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+ return(ret);
}
struct hostent *_wapi_gethostbyname(const char *hostname)
#include <mono/io-layer/timed-thread.h>
-extern const struct _WapiHandleOps _wapi_thread_ops;
+extern struct _WapiHandleOps _wapi_thread_ops;
typedef enum {
THREAD_STATE_START,
#undef DEBUG
#undef TLS_DEBUG
-#undef TLS_PTHREAD_MUTEX
/* Hash threads with tids. I thought of using TLS for this, but that
static void thread_close_private (gpointer handle);
static void thread_own (gpointer handle);
-const struct _WapiHandleOps _wapi_thread_ops = {
+struct _WapiHandleOps _wapi_thread_ops = {
NULL, /* close_shared */
thread_close_private, /* close_private */
NULL, /* signal */
struct _WapiHandle_thread *thread_handle;
struct _WapiHandlePrivate_thread *thread_private_handle;
gboolean ok;
+ int thr_ret;
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
(gpointer *)&thread_handle,
return;
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
#ifdef DEBUG
g_message (G_GNUC_PRETTY_FUNCTION
thread_handle->state=THREAD_STATE_EXITED;
_wapi_handle_set_signal_state (handle, TRUE, TRUE);
- _wapi_handle_unlock_handle (handle);
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION
#endif
/* Remove this thread from the hash */
- mono_mutex_lock(&thread_hash_mutex);
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&thread_hash_mutex);
+ thr_ret = mono_mutex_lock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
+
g_hash_table_remove(thread_hash, &thread_private_handle->thread->id);
- mono_mutex_unlock(&thread_hash_mutex);
+
+ thr_ret = mono_mutex_unlock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
/* The thread is no longer active, so unref it */
_wapi_handle_unref (handle);
gpointer handle;
gboolean ok;
int ret;
+ int thr_ret;
+ int i, unrefs = 0;
+ gpointer ct_ret = NULL;
mono_once(&thread_hash_once, thread_hash_init);
mono_once (&thread_ops_once, thread_ops_init);
return(NULL);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
(gpointer *)&thread_handle,
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error looking up thread handle %p", handle);
- _wapi_handle_unlock_handle (handle);
- return(NULL);
+ goto cleanup;
}
/* Hold a reference while the thread is active, because we use
/* Lock around the thread create, so that the new thread cant
* race us to look up the thread handle in GetCurrentThread()
*/
- mono_mutex_lock(&thread_hash_mutex);
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&thread_hash_mutex);
+ thr_ret = mono_mutex_lock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
/* Set a 2M stack size. This is the default on Linux, but BSD
* needs it. (The original bug report from Martin Dvorak <md@9ll.cz>
* set the size to 2M-4k. I don't know why it's short by 4k, so
* I'm leaving it as 2M until I'm told differently.)
*/
- pthread_attr_init(&attr);
+ thr_ret = pthread_attr_init(&attr);
+ g_assert (thr_ret == 0);
+
/* defaults of 2Mb for 32bits and 4Mb for 64bits */
if (stacksize == 0)
stacksize = (SIZEOF_VOID_P / 2) * 1024 *1024;
#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
- pthread_attr_setstacksize(&attr, stacksize);
+ thr_ret = pthread_attr_setstacksize(&attr, stacksize);
+ g_assert (thr_ret == 0);
#endif
ret=_wapi_timed_thread_create(&thread_private_handle->thread, &attr,
g_message(G_GNUC_PRETTY_FUNCTION ": Thread create error: %s",
strerror(ret));
#endif
- mono_mutex_unlock(&thread_hash_mutex);
- _wapi_handle_unlock_handle (handle);
- _wapi_handle_unref (handle);
-
- /* And again, because of the reference we took above */
- _wapi_handle_unref (handle);
- return(NULL);
+ /* Two, because of the reference we took above */
+ unrefs = 2;
+ goto thread_hash_cleanup;
}
-
+ ct_ret = handle;
+
g_hash_table_insert(thread_hash, &thread_private_handle->thread->id,
handle);
- mono_mutex_unlock(&thread_hash_mutex);
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION
#endif
}
- _wapi_handle_unlock_handle (handle);
+thread_hash_cleanup:
+ thr_ret = mono_mutex_unlock (&thread_hash_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
- return(handle);
+ /* Must not call _wapi_handle_unref() with the handle already
+ * locked
+ */
+ for (i = 0; i < unrefs; i++) {
+ _wapi_handle_unref (handle);
+ }
+
+ return(ct_ret);
}
gpointer OpenThread (guint32 access G_GNUC_UNUSED, gboolean inherit G_GNUC_UNUSED, guint32 tid)
{
gpointer ret=NULL;
+ int thr_ret;
mono_once(&thread_hash_once, thread_hash_init);
mono_once (&thread_ops_once, thread_ops_init);
g_message (G_GNUC_PRETTY_FUNCTION ": looking up thread %d", tid);
#endif
- mono_mutex_lock(&thread_hash_mutex);
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&thread_hash_mutex);
+ thr_ret = mono_mutex_lock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
ret=g_hash_table_lookup(thread_hash, &tid);
- mono_mutex_unlock(&thread_hash_mutex);
+
+ thr_ret = mono_mutex_unlock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
if(ret!=NULL) {
_wapi_handle_ref (ret);
gpointer handle;
gboolean ok;
int ret;
-
+ int thr_ret;
+ int i, unrefs = 0;
+ gpointer ta_ret = NULL;
+
mono_once(&thread_hash_once, thread_hash_init);
mono_once (&thread_ops_once, thread_ops_init);
return(NULL);
}
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
ok=_wapi_lookup_handle (handle, WAPI_HANDLE_THREAD,
(gpointer *)&thread_handle,
if(ok==FALSE) {
g_warning (G_GNUC_PRETTY_FUNCTION
": error looking up thread handle %p", handle);
- _wapi_handle_unlock_handle (handle);
- return(NULL);
+ goto cleanup;
}
/* Hold a reference while the thread is active, because we use
/* Lock around the thread create, so that the new thread cant
* race us to look up the thread handle in GetCurrentThread()
*/
- mono_mutex_lock(&thread_hash_mutex);
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&thread_hash_mutex);
+ thr_ret = mono_mutex_lock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
ret=_wapi_timed_thread_attach(&thread_private_handle->thread,
thread_exit, handle);
g_message(G_GNUC_PRETTY_FUNCTION ": Thread attach error: %s",
strerror(ret));
#endif
- mono_mutex_unlock(&thread_hash_mutex);
- _wapi_handle_unlock_handle (handle);
- _wapi_handle_unref (handle);
+ /* Two, because of the reference we took above */
+ unrefs = 2;
- /* And again, because of the reference we took above */
- _wapi_handle_unref (handle);
- return(NULL);
+ goto thread_hash_cleanup;
}
-
+ ta_ret = handle;
+
g_hash_table_insert(thread_hash, &thread_private_handle->thread->id,
handle);
- mono_mutex_unlock(&thread_hash_mutex);
#ifdef DEBUG
g_message(G_GNUC_PRETTY_FUNCTION
#endif
}
- _wapi_handle_unlock_handle (handle);
+thread_hash_cleanup:
+ thr_ret = mono_mutex_unlock (&thread_hash_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
+cleanup:
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
- return(handle);
+ /* Must not call _wapi_handle_unref() with the handle already
+ * locked
+ */
+ for (i = 0; i < unrefs; i++) {
+ _wapi_handle_unref (handle);
+ }
+
+ return(ta_ret);
}
/**
{
gpointer ret=NULL;
guint32 tid;
+ int thr_ret;
mono_once(&thread_hash_once, thread_hash_init);
mono_once (&thread_ops_once, thread_ops_init);
tid=GetCurrentThreadId();
- mono_mutex_lock(&thread_hash_mutex);
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&thread_hash_mutex);
+ thr_ret = mono_mutex_lock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
ret=g_hash_table_lookup(thread_hash, &tid);
- mono_mutex_unlock(&thread_hash_mutex);
+
+ thr_ret = mono_mutex_unlock(&thread_hash_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
if (!ret) {
ret = thread_attach (NULL);
static pthread_key_t TLS_keys[TLS_MINIMUM_AVAILABLE];
static gboolean TLS_used[TLS_MINIMUM_AVAILABLE]={FALSE};
-#ifdef TLS_PTHREAD_MUTEX
-static mono_mutex_t TLS_mutex=MONO_MUTEX_INITIALIZER;
-#else
static guint32 TLS_spinlock=0;
-#endif
/**
* TlsAlloc:
guint32 TlsAlloc(void)
{
guint32 i;
+ int thr_ret;
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_lock(&TLS_mutex);
-#else
MONO_SPIN_LOCK (TLS_spinlock);
-#endif
for(i=0; i<TLS_MINIMUM_AVAILABLE; i++) {
if(TLS_used[i]==FALSE) {
TLS_used[i]=TRUE;
- pthread_key_create(&TLS_keys[i], NULL);
+ thr_ret = pthread_key_create(&TLS_keys[i], NULL);
+ g_assert (thr_ret == 0);
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_unlock(&TLS_mutex);
-#else
MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
#ifdef TLS_DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": returning key %d",
}
}
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_unlock(&TLS_mutex);
-#else
MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
#ifdef TLS_DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": out of indices");
*/
gboolean TlsFree(guint32 idx)
{
+ int thr_ret;
+
#ifdef TLS_DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": freeing key %d", idx);
#endif
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_lock(&TLS_mutex);
-#else
MONO_SPIN_LOCK (TLS_spinlock);
-#endif
if(TLS_used[idx]==FALSE) {
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_unlock(&TLS_mutex);
-#else
MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
+
return(FALSE);
}
TLS_used[idx]=FALSE;
- pthread_key_delete(TLS_keys[idx]);
+ thr_ret = pthread_key_delete(TLS_keys[idx]);
+ g_assert (thr_ret == 0);
#if HAVE_BOEHM_GC
mono_g_hash_table_remove (tls_gc_hash, MAKE_GC_ID (idx));
#endif
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_unlock(&TLS_mutex);
-#else
MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
return(TRUE);
}
value);
#endif
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_lock(&TLS_mutex);
-#else
MONO_SPIN_LOCK (TLS_spinlock);
-#endif
if(TLS_used[idx]==FALSE) {
#ifdef TLS_DEBUG
g_message (G_GNUC_PRETTY_FUNCTION ": key %d unused", idx);
#endif
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_unlock(&TLS_mutex);
-#else
MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
+
return(FALSE);
}
": pthread_setspecific error: %s", strerror (ret));
#endif
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_unlock(&TLS_mutex);
-#else
MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
+
return(FALSE);
}
mono_g_hash_table_insert (tls_gc_hash, MAKE_GC_ID (idx), value);
#endif
-#ifdef TLS_PTHREAD_MUTEX
- mono_mutex_unlock(&TLS_mutex);
-#else
MONO_SPIN_UNLOCK (TLS_spinlock);
-#endif
return(TRUE);
}
static void timed_thread_init(void)
{
- pthread_key_create(&timed_thread_key, NULL);
+ int thr_ret;
+
+ thr_ret = pthread_key_create(&timed_thread_key, NULL);
+ g_assert (thr_ret == 0);
}
void _wapi_timed_thread_exit(guint32 exitstatus)
{
TimedThread *thread;
void *specific;
+ int thr_ret;
if((specific = pthread_getspecific(timed_thread_key)) == NULL) {
/* Handle cases which won't happen with correct usage.
thread=(TimedThread *)specific;
- mono_mutex_lock(&thread->join_mutex);
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&thread->join_mutex);
+ thr_ret = mono_mutex_lock(&thread->join_mutex);
+ g_assert (thr_ret == 0);
/* Tell a joiner that we're exiting.
*/
thread->exit_routine(exitstatus, thread->exit_userdata);
}
- pthread_cond_signal(&thread->exit_cond);
- mono_mutex_unlock(&thread->join_mutex);
+ thr_ret = pthread_cond_signal(&thread->exit_cond);
+ g_assert (thr_ret == 0);
+
+ thr_ret = mono_mutex_unlock(&thread->join_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
/* Call pthread_exit() to call destructors and really exit the
* thread.
static void *timed_thread_start_routine(gpointer args)
{
TimedThread *thread = (TimedThread *)args;
+ int thr_ret;
mono_once(&timed_thread_once, timed_thread_init);
- pthread_setspecific(timed_thread_key, (void *)thread);
+ thr_ret = pthread_setspecific(timed_thread_key, (void *)thread);
+ g_assert (thr_ret == 0);
/* This used to be pthread_detach(thread->id);
*
* This was 100% reproducible on Debian Woody with gcc 2.95.4,
* and on Red Hat 9 with gcc 3.2.2.
*/
- pthread_detach(pthread_self ());
+ thr_ret = pthread_detach(pthread_self ());
+ g_assert (thr_ret == 0);
if(thread->create_flags & CREATE_SUSPENDED) {
thread->suspend_count = 1;
{
TimedThread *thread;
int result;
+ int thr_ret;
thread=(TimedThread *)g_new0(TimedThread, 1);
- mono_mutex_init(&thread->join_mutex, NULL);
- pthread_cond_init(&thread->exit_cond, NULL);
+ thr_ret = mono_mutex_init(&thread->join_mutex, NULL);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_init(&thread->exit_cond, NULL);
+ g_assert (thr_ret == 0);
+
thread->create_flags = create_flags;
MONO_SEM_INIT (&thread->suspend_sem, 0);
MONO_SEM_INIT (&thread->suspended_sem, 0);
gpointer exit_userdata)
{
TimedThread *thread;
-
+ int thr_ret;
+
thread=(TimedThread *)g_new0(TimedThread, 1);
- mono_mutex_init(&thread->join_mutex, NULL);
- pthread_cond_init(&thread->exit_cond, NULL);
- sem_init (&thread->suspend_sem, 0, 0);
- sem_init (&thread->suspended_sem, 0, 0);
+ thr_ret = mono_mutex_init(&thread->join_mutex, NULL);
+ g_assert (thr_ret == 0);
+
+ thr_ret = pthread_cond_init(&thread->exit_cond, NULL);
+ g_assert (thr_ret == 0);
+
+ thr_ret = sem_init (&thread->suspend_sem, 0, 0);
+ g_assert (thr_ret != -1);
+
+ thr_ret = sem_init (&thread->suspended_sem, 0, 0);
+ g_assert (thr_ret != -1);
+
thread->exit_routine = exit_routine;
thread->exit_userdata = exit_userdata;
thread->exitstatus = 0;
* called)
*/
mono_once(&timed_thread_once, timed_thread_init);
- pthread_setspecific(timed_thread_key, (void *)thread);
+ thr_ret = pthread_setspecific(timed_thread_key, (void *)thread);
+ g_assert (thr_ret == 0);
*threadp = thread;
guint32 *exitstatus)
{
int result;
+ int thr_ret;
+
+ pthread_cleanup_push ((void(*)(void *))mono_mutex_unlock_in_cleanup,
+ (void *)&thread->join_mutex);
+ thr_ret = mono_mutex_lock(&thread->join_mutex);
+ g_assert (thr_ret == 0);
- mono_mutex_lock(&thread->join_mutex);
result=0;
/* Wait until the thread announces that it's exiting, or until
}
}
- mono_mutex_unlock(&thread->join_mutex);
+ thr_ret = mono_mutex_unlock(&thread->join_mutex);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
if(result == 0 && thread->exiting) {
if(exitstatus!=NULL) {
*exitstatus = thread->exitstatus;
{
guint32 ret, waited;
struct timespec abstime;
+ int thr_ret;
if(_wapi_handle_test_capabilities (handle,
WAPI_HANDLE_CAP_WAIT)==FALSE) {
g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", handle);
#endif
- _wapi_handle_lock_handle (handle);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ handle);
+ thr_ret = _wapi_handle_lock_handle (handle);
+ g_assert (thr_ret == 0);
if(_wapi_handle_test_capabilities (handle,
WAPI_HANDLE_CAP_OWN)==TRUE) {
g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", handle);
#endif
- _wapi_handle_unlock_handle (handle);
+ thr_ret = _wapi_handle_unlock_handle (handle);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
+
return(ret);
}
{
guint32 ret, waited;
struct timespec abstime;
+ int thr_ret;
if(_wapi_handle_test_capabilities (signal_handle,
WAPI_HANDLE_CAP_SIGNAL)==FALSE) {
g_message (G_GNUC_PRETTY_FUNCTION ": locking handle %p", wait);
#endif
- _wapi_handle_lock_handle (wait);
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
+ wait);
+ thr_ret = _wapi_handle_lock_handle (wait);
+ g_assert (thr_ret == 0);
_wapi_handle_ops_signal (signal_handle);
g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handle %p", wait);
#endif
- _wapi_handle_unlock_handle (wait);
+ thr_ret = _wapi_handle_unlock_handle (wait);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
if(alertable==TRUE) {
/* Deal with queued APC or IO completion routines */
return(ret);
}
+struct handle_cleanup_data
+{
+ guint32 numobjects;
+ gpointer *handles;
+};
+
+static void handle_cleanup (void *data)
+{
+ struct handle_cleanup_data *handles = (struct handle_cleanup_data *)data;
+
+ _wapi_handle_unlock_handles (handles->numobjects, handles->handles);
+}
+
+static gboolean test_and_own (guint32 numobjects, gpointer *handles,
+ gboolean waitall, guint32 *count,
+ guint32 *lowest)
+{
+ struct handle_cleanup_data cleanup_data;
+ gboolean done;
+ int i;
+
+#ifdef DEBUG
+ g_message (G_GNUC_PRETTY_FUNCTION ": locking handles");
+#endif
+ cleanup_data.numobjects = numobjects;
+ cleanup_data.handles = handles;
+
+ pthread_cleanup_push (handle_cleanup, (void *)&cleanup_data);
+ done = _wapi_handle_count_signalled_handles (numobjects, handles,
+ waitall, count, lowest);
+ if (done == TRUE) {
+ for (i = 0; i < numobjects; i++) {
+ _wapi_handle_ops_own (handles[i]);
+ }
+ }
+
+#ifdef DEBUG
+ g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
+#endif
+
+ /* calls the unlock function */
+ pthread_cleanup_pop (1);
+
+ return(done);
+}
+
+
+
/**
* WaitForMultipleObjects:
* @numobjects: The number of objects in @handles. The maximum allowed
struct timespec abstime;
guint i;
guint32 ret;
+ int thr_ret;
if(numobjects>MAXIMUM_WAIT_OBJECTS) {
#ifdef DEBUG
return(WAIT_FAILED);
}
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": locking handles");
-#endif
-
- done=_wapi_handle_count_signalled_handles (numobjects, handles,
- waitall, &count, &lowest);
+ done=test_and_own (numobjects, handles, waitall, &count, &lowest);
if(done==TRUE) {
- for(i=0; i<numobjects; i++) {
- _wapi_handle_ops_own (handles[i]);
- }
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
-#endif
-
- _wapi_handle_unlock_handles (numobjects, handles);
return(WAIT_OBJECT_0+lowest);
}
/* Have to wait for some or all handles to become signalled
*/
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
-#endif
-
- _wapi_handle_unlock_handles (numobjects, handles);
-
if(timeout!=INFINITE) {
_wapi_calc_timeout (&abstime, timeout);
}
g_message (G_GNUC_PRETTY_FUNCTION ": locking signal mutex");
#endif
- _wapi_handle_lock_signal_mutex ();
-
+ pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_signal_mutex, NULL);
+ thr_ret = _wapi_handle_lock_signal_mutex ();
+ g_assert (thr_ret == 0);
+
if(timeout==INFINITE) {
ret=_wapi_handle_wait_signal ();
} else {
g_message (G_GNUC_PRETTY_FUNCTION ": unlocking signal mutex");
#endif
- _wapi_handle_unlock_signal_mutex ();
+ thr_ret = _wapi_handle_unlock_signal_mutex (NULL);
+ g_assert (thr_ret == 0);
+ pthread_cleanup_pop (0);
if(ret==0) {
/* Something was signalled ... */
- done=_wapi_handle_count_signalled_handles (numobjects,
- handles,
- waitall,
- &count,
- &lowest);
+ done = test_and_own (numobjects, handles, waitall,
+ &count, &lowest);
if(done==TRUE) {
- for(i=0; i<numobjects; i++) {
- _wapi_handle_ops_own (handles[i]);
- }
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
-#endif
-
- _wapi_handle_unlock_handles (numobjects,
- handles);
-
return(WAIT_OBJECT_0+lowest);
}
-
-#ifdef DEBUG
- g_message (G_GNUC_PRETTY_FUNCTION ": unlocking handles");
-#endif
-
- _wapi_handle_unlock_handles (numobjects, handles);
} else {
/* Timeout or other error */
#ifdef DEBUG