This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [v3] libstdc++/46455 - fix mutex and condvar leaks
On 18 November 2010 02:42, Jonathan Wakely wrote:
> This change adds destructors to the mutex types in the library, it's
> not trivial and could do with more testing on platforms where thread
> model != posix. ?I hacked the gthr headers to reproduce leaks under
> valgrind and think I've tested all the code paths, but I don't have
> anything suitable to add to the testsuite.
Attached is a modified gthr header I've been testing with, it might
prove useful to someone else one day. Save this as
$foo/bits/gthr-default.h then compile with -I$foo to turn un-destroyed
mutexes into memory leaks, easily detected by valgrind. Use -DWINSTYLE
to exercise the win32 case.
/* Threads compatibility routines for libgcc2 and libobjc. */
/* Compile this one with gcc. */
/* Copyright (C) 2010 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef GCC_GTHR_JWTEST_H
#define GCC_GTHR_JWTEST_H
// prevent real file from being included
#define GCC_GTHR_POSIX_H
#define __GTHREADS 1
#include <pthread.h>
#undef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
#undef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
#include <malloc.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct timespec __gthread_time_t;
typedef pthread_key_t __gthread_key_t;
typedef pthread_once_t __gthread_once_t;
struct __gthread_mutex_t {
long counter;
void *sema;
};
static inline pthread_mutex_t* get(__gthread_mutex_t* m)
{ return (pthread_mutex_t*)m->sema; }
#ifdef WINSTYLE
struct __gthread_recursive_mutex_t {
long counter;
long depth;
unsigned long owner;
void *sema;
};
static inline pthread_mutex_t* getr(__gthread_recursive_mutex_t* m)
{ return (pthread_mutex_t*)m->sema; }
#else /* ! WINSTYLE */
struct __gthread_recursive_mutex_t {
__gthread_mutex_t actual;
};
static inline pthread_mutex_t* getr(__gthread_recursive_mutex_t* m)
{ return get(&m->actual); }
#endif /* !WINSTYLE */
#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \
__gthread_recursive_mutex_init_function
static inline int
__gthread_active_p (void)
{
return 1;
}
static inline int
__gthread_once (__gthread_once_t *__once, void (*__func) (void))
{
return pthread_once(__once, __func);
}
static inline int
__gthread_key_create (__gthread_key_t *__key,
void (*__dtor) (void *) )
{
return pthread_key_create(__key, __dtor);
}
static inline int
__gthread_key_delete (__gthread_key_t __key)
{
return pthread_key_delete(__key);
}
static inline void *
__gthread_getspecific (__gthread_key_t __key)
{
return pthread_getspecific(__key);
}
static inline int
__gthread_setspecific (__gthread_key_t __key, const void *__ptr)
{
return pthread_setspecific(__key, __ptr);
}
static inline void
__gthread_mutex_init_function (__gthread_mutex_t *__mutex)
{
__mutex->counter = -1;
__mutex->sema = malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(get(__mutex), NULL);
}
static inline void
__gthread_mutex_destroy (__gthread_mutex_t *__mutex)
{
pthread_mutex_destroy(get(__mutex));
free(__mutex->sema);
}
static inline int
__gthread_mutex_lock (__gthread_mutex_t *__mutex)
{
if (__gthread_active_p ())
return pthread_mutex_lock (get(__mutex));
else
return 0;
}
static inline int
__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
{
if (__gthread_active_p ())
return pthread_mutex_trylock (get(__mutex));
else
return 0;
}
static inline int
__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
{
if (__gthread_active_p ())
return pthread_mutex_unlock (get(__mutex));
else
return 0;
}
static inline void
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
{
#ifdef WINSTYLE
__mutex->counter = -1;
__mutex->depth = 0;
__mutex->owner = 0;
__mutex->sema = malloc(sizeof(pthread_mutex_t));
#else
__mutex->actual.counter = -1;
__mutex->actual.sema = malloc(sizeof(pthread_mutex_t));
#endif
pthread_mutexattr_t a;
pthread_mutexattr_init(&a);
pthread_mutexattr_settype(&a, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(getr(__mutex), &a);
pthread_mutexattr_destroy(&a);
}
static inline int
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
return pthread_mutex_lock (getr(__mutex));
else
return 0;
}
static inline int
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
return pthread_mutex_trylock (getr(__mutex));
else
return 0;
}
static inline int
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
{
if (__gthread_active_p ())
return pthread_mutex_unlock (getr(__mutex));
else
return 0;
}
static inline int
__gthread_mutex_timedlock (__gthread_mutex_t *__mutex,
const __gthread_time_t *__abs_timeout)
{
if (__gthread_active_p ())
return pthread_mutex_timedlock (get(__mutex), __abs_timeout);
else
return 0;
}
static inline int
__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex,
const __gthread_time_t *__abs_timeout)
{
if (__gthread_active_p ())
return pthread_mutex_timedlock (getr(__mutex), __abs_timeout);
else
return 0;
}
#ifdef __cplusplus
}
#endif
#endif /* ! GCC_GTHR_JWTEST_H */