Removed the unused pthread_model and thread_model modules.

Mostly commented out the unused stuff relating to ThreadErrs and MutexErrs,
which no longer exist.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6399
This commit is contained in:
Nicholas Nethercote 2006-12-14 02:55:58 +00:00
parent b1ca5a2804
commit 033e3bd4e9
9 changed files with 35 additions and 2089 deletions

View File

@ -112,7 +112,6 @@ noinst_HEADERS = \
pub_core_mallocfree.h \
pub_core_options.h \
pub_core_oset.h \
pub_core_pthreadmodel.h \
pub_core_redir.h \
pub_core_replacemalloc.h\
pub_core_scheduler.h \
@ -122,7 +121,6 @@ noinst_HEADERS = \
pub_core_stacktrace.h \
pub_core_syscall.h \
pub_core_syswrap.h \
pub_core_threadmodel.h \
pub_core_threadstate.h \
pub_core_tooliface.h \
pub_core_trampoline.h \
@ -177,13 +175,11 @@ COREGRIND_SOURCES_COMMON = \
m_mallocfree.c \
m_options.c \
m_oset.c \
m_pthreadmodel.c \
m_redir.c \
m_signals.c \
m_stacks.c \
m_stacktrace.c \
m_syscall.c \
m_threadmodel.c \
m_threadstate.c \
m_tooliface.c \
m_trampoline.S \

View File

@ -170,7 +170,10 @@ UInt VG_(get_n_errs_found)( void )
* effectively extend it by defining their own enums in the (0..) range. */
typedef
enum {
PThreadSupp = -1, /* Matches PThreadErr */
// Nb: thread errors are a relic of the time when Valgrind's core
// could detect them. This example is left commented-out as an
// example should new core errors ever be added.
ThreadSupp = -1, /* Matches ThreadErr */
}
CoreSuppKind;
@ -269,10 +272,10 @@ static Bool eq_Error ( VgRes res, Error* e1, Error* e2 )
return False;
switch (e1->ekind) {
// case ThreadErr:
// case MutexErr:
// vg_assert(VG_(needs).core_errors);
// return VG_(tm_error_equal)(res, e1, e2);
//(example code, see comment on CoreSuppKind above)
//case ThreadErr:
// vg_assert(VG_(needs).core_errors);
// return <something>
default:
if (VG_(needs).tool_errors) {
return VG_TDICT_CALL(tool_eq_Error, res, e1, e2);
@ -302,11 +305,11 @@ static void pp_Error ( Error* err )
}
switch (err->ekind) {
// case ThreadErr:
// case MutexErr:
// vg_assert(VG_(needs).core_errors);
// VG_(tm_error_print)(err);
// break;
//(example code, see comment on CoreSuppKind above)
//case ThreadErr:
// vg_assert(VG_(needs).core_errors);
// VG_(tm_error_print)(err);
// break;
default:
if (VG_(needs).tool_errors)
VG_TDICT_CALL( tool_pp_Error, err );
@ -420,10 +423,12 @@ static void gen_suppression(Error* err)
if (stop_at > VG_MAX_SUPP_CALLERS) stop_at = VG_MAX_SUPP_CALLERS;
vg_assert(stop_at > 0);
if (ThreadErr == err->ekind || MutexErr == err->ekind) {
VG_(printf)("{\n");
VG_(printf)(" <insert a suppression name here>\n");
VG_(printf)(" core:PThread\n");
//(example code, see comment on CoreSuppKind above)
if (0) {
//if (0) ThreadErr == err->ekind) {
// VG_(printf)("{\n");
// VG_(printf)(" <insert a suppression name here>\n");
// VG_(printf)(" core:Thread\n");
} else {
Char* name = VG_TDICT_CALL(tool_get_error_name, err);
@ -601,11 +606,11 @@ void VG_(maybe_record_error) ( ThreadId tid,
/* update 'extra' */
switch (ekind) {
// case ThreadErr:
// case MutexErr:
// vg_assert(VG_(needs).core_errors);
// extra_size = VG_(tm_error_update_extra)(p);
// break;
//(example code, see comment on CoreSuppKind above)
//case ThreadErr:
// vg_assert(VG_(needs).core_errors);
// extra_size = <something>
// break;
default:
vg_assert(VG_(needs).tool_errors);
extra_size = VG_TDICT_CALL(tool_update_extra, p);
@ -1013,9 +1018,10 @@ static void load_one_suppressions_file ( Char* filename )
if (VG_(needs).core_errors && tool_name_present("core", tool_names))
{
// A core suppression
if (VG_STREQ(supp_name, "PThread"))
supp->skind = PThreadSupp;
else
//(example code, see comment on CoreSuppKind above)
//if (VG_STREQ(supp_name, "Thread"))
// supp->skind = ThreadSupp;
//else
BOMB("unknown core suppression type");
}
else if (VG_(needs).tool_errors &&
@ -1120,8 +1126,9 @@ static
Bool supp_matches_error(Supp* su, Error* err)
{
switch (su->skind) {
case PThreadSupp:
return (err->ekind == ThreadErr || err->ekind == MutexErr);
//(example code, see comment on CoreSuppKind above)
//case ThreadSupp:
// return (err->ekind == ThreadErr);
default:
if (VG_(needs).tool_errors) {
return VG_TDICT_CALL(tool_error_matches_suppression, err, su);

View File

@ -1,604 +0,0 @@
/*--------------------------------------------------------------------*/
/*--- Pthreads library modelling. m_pthreadmodel.c ---*/
/*--------------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2005 Jeremy Fitzhardinge
jeremy@goop.org
This program 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 2 of the
License, or (at your option) any later version.
This program 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
The GNU General Public License is contained in the file COPYING.
*/
/*
This file wraps the client's use of libpthread functions and calls
on vg_threadmodel.c to model the state of the the client's threads.
The intent is to 1) look for problem's in the client's use of the
pthread API, and 2) tell tools which care about thread events (eg,
helgrind).
This file is intended to be implementation-independent. It assumes
that the client is using the same pthread.h as the one we include
here, but makes minimal assumptions about the actual structures
defined and so on (ie, the exact nature of pthread_t).
(For now we assume there's a 1:1 relationship between pthread_t's
and Valgrind-visible threads; N:M implementations will need further
work.)
The model is based on the pthread standard rather than any
particular implementation, in order to encourage portable use of
libpthread. On the other hand, we will probably need to implement
particular implementation extensions if they're widely used.
One tricky problem we need to solve is the mapping between
pthread_t identifiers and internal thread identifiers.
*/
#include "pub_core_basics.h"
#if 0
#define __USE_GNU
#define __USE_UNIX98
#include <pthread.h>
static const Bool debug = False;
static Bool check_wrappings(void);
#define ENTER(x) \
do { \
if (VG_(clo_trace_pthreads)) \
VG_(message)(Vg_DebugMsg, ">>> %d entering %s", \
VG_(get_running_tid)(), #x); \
} while(0)
static const Char *pp_retval(enum return_type rt, Word retval)
{
static Char buf[50];
switch(rt) {
case RT_RETURN:
VG_(sprintf)(buf, "return %d 0x%x", retval, retval);
return buf;
case RT_LONGJMP:
return "LONGJMPed out";
case RT_EXIT:
return "thread exit";
}
return "??";
}
#define LEAVE(x, rt, retval) \
do { \
if (VG_(clo_trace_pthreads)) \
VG_(message)(Vg_DebugMsg, "<<< %d leaving %s -> %s", \
VG_(get_running_tid)(), #x, pp_retval(rt, retval)); \
} while(0)
struct pthread_map
{
pthread_t id;
ThreadId tid;
};
static Int pthread_cmp(const void *v1, const void *v2)
{
const pthread_t *a = (const pthread_t *)v1;
const pthread_t *b = (const pthread_t *)v2;
return VG_(memcmp)(a, b, sizeof(*a));
}
static SkipList sk_pthread_map = VG_SKIPLIST_INIT(struct pthread_map, id, pthread_cmp,
NULL, VG_AR_CORE);
/* Find a ThreadId for a particular pthread_t; block until it becomes available */
static ThreadId get_pthread_mapping(pthread_t id)
{
/* Nasty little spin loop; revise if this turns out to be a
problem. This should only spin for as long as it takes for the
child thread to register the pthread_t. */
for(;;) {
struct pthread_map *m = VG_(SkipList_Find_Exact)(&sk_pthread_map, &id);
if (m && m->tid != VG_INVALID_THREADID)
return m->tid;
//VG_(printf)("find %x -> %p\n", id, m);
VG_(vg_yield)();
}
}
/* Create a mapping between a ThreadId and a pthread_t */
static void pthread_id_mapping(ThreadId tid, Addr idp, UInt idsz)
{
pthread_t id = *(pthread_t *)idp;
struct pthread_map *m = VG_(SkipList_Find_Exact)(&sk_pthread_map, &id);
if (debug)
VG_(printf)("Thread %d maps to %p\n", tid, id);
if (m == NULL) {
m = VG_(SkipNode_Alloc)(&sk_pthread_map);
m->id = id;
m->tid = tid;
VG_(SkipList_Insert)(&sk_pthread_map, m);
} else {
if (m->tid != VG_INVALID_THREADID && m->tid != tid)
VG_(message)(Vg_UserMsg, "Thread %d is creating duplicate mapping for pthread identifier %x; previously mapped to %d\n",
tid, (UInt)id, m->tid);
m->tid = tid;
}
}
static void check_thread_exists(ThreadId tid)
{
if (!VG_(tm_thread_exists)(tid)) {
if (debug)
VG_(printf)("creating thread %d\n", tid);
VG_(tm_thread_create)(VG_INVALID_THREADID, tid, False);
}
}
static Addr startfunc_wrapper = 0;
void VG_(pthread_startfunc_wrapper)(Addr wrapper)
{
startfunc_wrapper = wrapper;
}
struct pthread_create_nonce {
Bool detached;
pthread_t *threadid;
};
static void *before_pthread_create(va_list va)
{
pthread_t *threadp = va_arg(va, pthread_t *);
const pthread_attr_t *attr = va_arg(va, const pthread_attr_t *);
void *(*start)(void *) = va_arg(va, void *(*)(void *));
void *arg = va_arg(va, void *);
struct pthread_create_nonce *n;
struct vg_pthread_newthread_data *data;
ThreadState *tst;
if (!check_wrappings())
return NULL;
ENTER(pthread_create);
/* Data is in the client heap and is freed by the client in the
startfunc_wrapper. */
vg_assert(startfunc_wrapper != 0);
tst = VG_(get_ThreadState)(VG_(get_running_tid)());
// XXX: why use TL_(malloc)() here? What characteristics does this
// allocation require?
// [Possible: When using a tool that replaces malloc(), we want to call
// the replacement version. Otherwise, we want to use VG_(cli_malloc)().
// So we go via the default version of TL_(malloc)() in vg_default?]
tl_assert2(0, "read the comment in the code about this...");
// XXX: These three lines are going to have to change. They relied on
// TL_(malloc) being a weak symbol, and it just doesn't fit with the
// VG_(tdict) approach that we've switched to. The right way to do this
// will be to provide a function in the core that checks if
// VG_(tdict).malloc_malloc has been set; if so, it should
// call it, if not, it should call VG_(cli_malloc)().
// VG_(tl_malloc_called_deliberately) = True;
// data = TL_(malloc)(sizeof(*data));
// VG_(tl_malloc_called_deliberately) = False;
VG_TRACK(pre_mem_write, Vg_CorePThread, tst->tid, "new thread data",
(Addr)data, sizeof(*data));
data->startfunc = start;
data->arg = arg;
VG_TRACK(post_mem_write, (Addr)data, sizeof(*data));
/* Substitute arguments
XXX hack: need an API to do this. */
((Word *)tst->arch.m_esp)[3] = startfunc_wrapper;
((Word *)tst->arch.m_esp)[4] = (Word)data;
if (debug)
VG_(printf)("starting thread at wrapper %p\n", startfunc_wrapper);
n = VG_(arena_malloc)(VG_AR_CORE, sizeof(*n));
n->detached = attr && !!attr->__detachstate;
n->threadid = threadp;
return n;
}
static void after_pthread_create(void *nonce, enum return_type rt, Word retval)
{
struct pthread_create_nonce *n = (struct pthread_create_nonce *)nonce;
ThreadId tid = VG_(get_running_tid)();
if (n == NULL)
return;
if (rt == RT_RETURN && retval == 0) {
if (!VG_(tm_thread_exists)(tid))
VG_(tm_thread_create)(tid, get_pthread_mapping(*n->threadid),
n->detached);
else {
if (n->detached)
VG_(tm_thread_detach)(tid);
/* XXX set creator tid as well? */
}
}
VG_(arena_free)(VG_AR_CORE, n);
LEAVE(pthread_create, rt, retval);
}
static void *before_pthread_join(va_list va)
{
pthread_t pt_joinee = va_arg(va, pthread_t);
ThreadId joinee;
if (!check_wrappings())
return NULL;
ENTER(pthread_join);
joinee = get_pthread_mapping(pt_joinee);
VG_(tm_thread_join)(VG_(get_running_tid)(), joinee);
return NULL;
}
static void after_pthread_join(void *v, enum return_type rt, Word retval)
{
/* nothing to be done? */
if (!check_wrappings())
return;
LEAVE(pthread_join, rt, retval);
}
struct pthread_detach_data {
pthread_t id;
};
static void *before_pthread_detach(va_list va)
{
pthread_t id = va_arg(va, pthread_t);
struct pthread_detach_data *data;
if (!check_wrappings())
return NULL;
ENTER(pthread_detach);
data = VG_(arena_malloc)(VG_AR_CORE, sizeof(*data));
data->id = id;
return data;
}
static void after_pthread_detach(void *nonce, enum return_type rt, Word retval)
{
struct pthread_detach_data *data = (struct pthread_detach_data *)nonce;
ThreadId tid;
if (data == NULL)
return;
tid = get_pthread_mapping(data->id);
VG_(arena_free)(VG_AR_CORE, data);
if (rt == RT_RETURN && retval == 0)
VG_(tm_thread_detach)(tid);
LEAVE(pthread_detach, rt, retval);
}
static void *before_pthread_self(va_list va)
{
/* If pthread_t is a structure, then this might be passed a pointer
to the return value. On Linux/glibc, it's a simple scalar, so it is
returned normally. */
if (!check_wrappings())
return NULL;
ENTER(pthread_self);
check_thread_exists(VG_(get_running_tid)());
return NULL;
}
static void after_pthread_self(void *nonce, enum return_type rt, Word retval)
{
pthread_t ret = (pthread_t)retval;
if (!check_wrappings())
return;
pthread_id_mapping(VG_(get_running_tid)(), (Addr)&ret, sizeof(ret));
LEAVE(pthread_self, rt, retval);
}
/* If a mutex hasn't been initialized, check it against all the static
initializers to see if it appears to have been statically
initialized. */
static void check_mutex_init(ThreadId tid, pthread_mutex_t *mx)
{
static const pthread_mutex_t initializers[] = {
PTHREAD_MUTEX_INITIALIZER,
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP,
PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP,
PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP,
};
Int i;
if (VG_(tm_mutex_exists)((Addr)mx))
return;
VG_TRACK(pre_mem_read, Vg_CorePThread, tid, "pthread_mutex_t", (Addr)mx, sizeof(*mx));
for(i = 0; i < sizeof(initializers)/sizeof(*initializers); i++)
if (VG_(memcmp)(&initializers[i], mx, sizeof(*mx)) == 0) {
VG_(tm_mutex_init)(tid, (Addr)mx);
break;
}
}
static void *before_pthread_mutex_init(va_list va)
{
pthread_mutex_t *mx = va_arg(va, pthread_mutex_t *);
const pthread_mutexattr_t *attr = va_arg(va, const pthread_mutexattr_t *);
if (!check_wrappings())
return NULL;
ENTER(pthread_mutex_init);
/* XXX look for recursive mutex */
/* XXX look for non-process scope */
(void)attr;
return mx;
}
static void after_pthread_mutex_init(void *nonce, enum return_type rt, Word retval)
{
if (!check_wrappings())
return;
if (rt == RT_RETURN && retval == 0)
VG_(tm_mutex_init)(VG_(get_running_tid)(), (Addr)nonce);
LEAVE(pthread_mutex_init, rt, retval);
}
static void *before_pthread_mutex_destroy(va_list va)
{
pthread_mutex_t *mx = va_arg(va, pthread_mutex_t *);
if (!check_wrappings())
return NULL;
ENTER(pthread_mutex_destroy);
VG_(tm_mutex_destroy)(VG_(get_running_tid)(), (Addr)mx);
return NULL;
}
static void after_pthread_mutex_destroy(void *nonce, enum return_type rt, Word retval)
{
if (!check_wrappings())
return;
LEAVE(pthread_mutex_destroy, rt, retval);
}
static void *before_pthread_mutex_lock(va_list va)
{
pthread_mutex_t *mx = va_arg(va, pthread_mutex_t *);
if (!check_wrappings())
return NULL;
ENTER(pthread_mutex_lock);
if (debug)
VG_(printf)("%d locking %p\n", VG_(get_running_tid)(), mx);
check_thread_exists(VG_(get_running_tid)());
check_mutex_init(VG_(get_running_tid)(), mx); /* mutex might be statically initialized */
VG_(tm_mutex_trylock)(VG_(get_running_tid)(), (Addr)mx);
return mx;
}
static void after_pthread_mutex_lock(void *nonce, enum return_type rt, Word retval)
{
if (!check_wrappings())
return;
if (rt == RT_RETURN && retval == 0)
VG_(tm_mutex_acquire)(VG_(get_running_tid)(), (Addr)nonce);
else {
if (debug)
VG_(printf)("after mutex_lock failed: rt=%d ret=%d\n", rt, retval);
VG_(tm_mutex_giveup)(VG_(get_running_tid)(), (Addr)nonce);
}
LEAVE(pthread_mutex_lock, rt, retval);
}
static void *before_pthread_mutex_trylock(va_list va)
{
pthread_mutex_t *mx = va_arg(va, pthread_mutex_t *);
if (!check_wrappings())
return NULL;
ENTER(pthread_mutex_trylock);
if (debug)
VG_(printf)("%d trylocking %p\n", VG_(get_running_tid)(), mx);
check_thread_exists(VG_(get_running_tid)());
check_mutex_init(VG_(get_running_tid)(), mx); /* mutex might be statically initialized */
VG_(tm_mutex_trylock)(VG_(get_running_tid)(), (Addr)mx);
return mx;
}
static void after_pthread_mutex_trylock(void *nonce, enum return_type rt, Word retval)
{
if (nonce == NULL)
return;
if (rt == RT_RETURN && retval == 0)
VG_(tm_mutex_acquire)(VG_(get_running_tid)(), (Addr)nonce);
else {
if (debug)
VG_(printf)("after mutex_trylock failed: rt=%d ret=%d\n", rt, retval);
VG_(tm_mutex_giveup)(VG_(get_running_tid)(), (Addr)nonce);
}
LEAVE(pthread_mutex_trylock, rt, retval);
}
static void *before_pthread_mutex_unlock(va_list va)
{
pthread_mutex_t *mx = va_arg(va, pthread_mutex_t *);
if (!check_wrappings())
return NULL;
ENTER(pthread_mutex_unlock);
VG_(tm_mutex_tryunlock)(VG_(get_running_tid)(), (Addr)mx);
return mx;
}
static void after_pthread_mutex_unlock(void *nonce, enum return_type rt, Word retval)
{
if (nonce == NULL)
return;
if (rt == RT_RETURN && retval == 0)
VG_(tm_mutex_unlock)(VG_(get_running_tid)(), (Addr)nonce); /* complete unlock */
else
VG_(tm_mutex_acquire)(VG_(get_running_tid)(), (Addr)nonce); /* re-acquire */
LEAVE(pthread_mutex_unlock, rt, retval);
}
static struct pt_wraps {
const Char *name;
FuncWrapper wrapper;
const CodeRedirect *redir;
} wraps[] = {
#define WRAP(func, extra) { #func extra, { before_##func, after_##func } }
WRAP(pthread_create, "@@GLIBC_2.1"), /* XXX TODO: 2.0 ABI (?) */
WRAP(pthread_join, ""),
WRAP(pthread_detach, ""),
WRAP(pthread_self, ""),
WRAP(pthread_mutex_init, ""),
WRAP(pthread_mutex_destroy, ""),
WRAP(pthread_mutex_lock, ""),
WRAP(pthread_mutex_trylock, ""),
WRAP(pthread_mutex_unlock, ""),
#undef WRAP
};
/* Check to see if all the wrappers are resolved */
static Bool check_wrappings()
{
Int i;
static Bool ok = True;
static Bool checked = False;
if (checked)
return ok;
for(i = 0; i < sizeof(wraps)/sizeof(*wraps); i++) {
if (!VG_(is_resolved)(wraps[i].redir)) {
VG_(message)(Vg_DebugMsg, "Pthread wrapper for \"%s\" is not resolved",
wraps[i].name);
ok = False;
}
}
if (startfunc_wrapper == 0) {
VG_(message)(Vg_DebugMsg, "Pthread wrapper for thread start function is not resolved");
ok = False;
}
if (!ok)
VG_(message)(Vg_DebugMsg, "Missing intercepts; model disabled");
checked = True;
return ok;
}
/*
Set up all the wrappers for interesting functions.
*/
void VG_(pthread_init)()
{
Int i;
for(i = 0; i < sizeof(wraps)/sizeof(*wraps); i++) {
//VG_(printf)("adding pthread wrapper for %s\n", wraps[i].name);
wraps[i].redir = VG_(add_wrapper)("soname:libpthread.so.0",
wraps[i].name, &wraps[i].wrapper);
}
VG_(tm_init)();
VG_(tm_thread_create)(VG_INVALID_THREADID, VG_(master_tid), True);
}
#else /* !0 */
/* Stubs for now */
//:: void VG_(pthread_init)()
//:: {
//:: }
//::
//:: void VG_(pthread_startfunc_wrapper)(Addr wrapper)
//:: {
//:: }
#endif /* 0 */
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/

File diff suppressed because it is too large Load Diff

View File

@ -39,12 +39,13 @@
#include "pub_tool_errormgr.h"
// XXX: should this be in pthreadmodel.c?
// These must be negative, so as to not overlap with tool error kinds.
typedef
enum {
ThreadErr = -1, // Thread error
MutexErr = -2, // Mutex error
// Nb: thread errors are a relic of the time when Valgrind's core
// could detect them. This example is left as an example should new
// core errors ever be added.
ThreadErr = -1,
}
CoreErrorKind;

View File

@ -1,50 +0,0 @@
/*--------------------------------------------------------------------*/
/*--- Pthread modelling. pub_core_pthreadmodel.h ---*/
/*--------------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2005 Jeremy Fitzhardinge
jeremy@goop.org
This program 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 2 of the
License, or (at your option) any later version.
This program 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
The GNU General Public License is contained in the file COPYING.
*/
#ifndef __PUB_CORE_PTHREADMODEL_H
#define __PUB_CORE_PTHREADMODEL_H
//--------------------------------------------------------------------
// PURPOSE: This module does pthread modelling stuff...
//--------------------------------------------------------------------
//extern void VG_(pthread_init) ();
//extern void VG_(pthread_startfunc_wrapper)(Addr wrapper);
//
//struct vg_pthread_newthread_data {
// void *(*startfunc)(void *arg);
// void *arg;
//};
#endif // __PUB_CORE_PTHREADMODEL_H
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/

View File

@ -1,70 +0,0 @@
/*--------------------------------------------------------------------*/
/*--- Thread modelling. pub_core_threadmodel.h ---*/
/*--------------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2005 Jeremy Fitzhardinge
jeremy@goop.org
This program 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 2 of the
License, or (at your option) any later version.
This program 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
The GNU General Public License is contained in the file COPYING.
*/
#ifndef __PUB_CORE_THREADMODEL_H
#define __PUB_CORE_THREADMODEL_H
//--------------------------------------------------------------------
// PURPOSE: This module does thread modelling stuff...
//--------------------------------------------------------------------
extern void VG_(tm_thread_create) (ThreadId creator, ThreadId tid, Bool detached);
extern void VG_(tm_thread_exit) (ThreadId tid);
extern Bool VG_(tm_thread_exists) (ThreadId tid);
extern void VG_(tm_thread_detach) (ThreadId tid);
extern void VG_(tm_thread_join) (ThreadId joiner, ThreadId joinee);
extern void VG_(tm_thread_switchto)(ThreadId tid);
extern void VG_(tm_mutex_init) (ThreadId tid, Addr mutexp);
extern void VG_(tm_mutex_destroy)(ThreadId tid, Addr mutexp);
extern void VG_(tm_mutex_trylock)(ThreadId tid, Addr mutexp);
extern void VG_(tm_mutex_giveup) (ThreadId tid, Addr mutexp);
extern void VG_(tm_mutex_acquire)(ThreadId tid, Addr mutexp);
extern void VG_(tm_mutex_tryunlock)(ThreadId tid, Addr mutexp);
extern void VG_(tm_mutex_unlock) (ThreadId tid, Addr mutexp);
extern Bool VG_(tm_mutex_exists) (Addr mutexp);
extern UInt VG_(tm_error_update_extra) (Error *err);
extern Bool VG_(tm_error_equal) (VgRes res, Error *e1, Error *e2);
extern void VG_(tm_error_print) (Error *err);
extern void VG_(tm_init) (void);
extern void VG_(tm_cond_init) (ThreadId tid, Addr condp);
extern void VG_(tm_cond_destroy) (ThreadId tid, Addr condp);
extern void VG_(tm_cond_wait) (ThreadId tid, Addr condp, Addr mutexp);
extern void VG_(tm_cond_wakeup) (ThreadId tid, Addr condp, Addr mutexp);
extern void VG_(tm_cond_signal) (ThreadId tid, Addr condp);
#endif // __PUB_CORE_THREADMODEL_H
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/

View File

@ -229,31 +229,6 @@
fun:_dl_open
}
#-------- Threading bugs?
# glibc 'knows' that destroying a locked mutex will unlock it
{
pthread_error/pthread_mutex_destroy/__closedir
core:PThread
fun:pthread_error
fun:pthread_mutex_destroy
fun:__closedir
}
{
pthread_error/pthread_mutex_destroy/_IO_default_finish
core:PThread
fun:pthread_error
fun:pthread_mutex_destroy
fun:_IO_default_finish*
}
{
pthread_mutex_unlock/_IO_funlockfile
core:PThread
fun:pthread_mutex_unlock
fun:_IO_funlockfile
}
# even more glibc suppressions ?
{
libc-2.2.4.so/libc-2.2.4.so/libc-2.2.4.so(Cond)

View File

@ -183,31 +183,6 @@
fun:__libc_start_main
}
#-------- Threading bugs?
# glibc 'knows' that destroying a locked mutex will unlock it
{
pthread_error/pthread_mutex_destroy/__closedir
core:PThread
fun:pthread_error
fun:pthread_mutex_destroy
fun:__closedir
}
{
pthread_error/pthread_mutex_destroy/_IO_default_finish
core:PThread
fun:pthread_error
fun:pthread_mutex_destroy
fun:_IO_default_finish*
}
{
pthread_mutex_unlock/_IO_funlockfile
core:PThread
fun:pthread_mutex_unlock
fun:_IO_funlockfile
}
##----------------------------------------------------------------------##
## Bugs in helper library supplied with Intel Icc 7.0 (65)
## in /opt/intel/compiler70/ia32/lib/libcxa.so.3