|
From: Konstantin S. <kon...@gm...> - 2009-08-14 11:42:35
|
Cool!!!
[comments below]
On Fri, Aug 14, 2009 at 3:08 PM, <sv...@va...> wrote:
> Author: sewardj
> Date: 2009-08-14 12:08:24 +0100 (Fri, 14 Aug 2009)
> New Revision: 10810
>
> Log:
> Skeletal support for TSan-compatible annotations.
>
>
> Modified:
> trunk/helgrind/helgrind.h
> trunk/helgrind/hg_main.c
>
>
> Modified: trunk/helgrind/helgrind.h
> ===================================================================
> --- trunk/helgrind/helgrind.h 2009-08-14 10:19:26 UTC (rev 10809)
> +++ trunk/helgrind/helgrind.h 2009-08-14 11:08:24 UTC (rev 10810)
> @@ -60,6 +60,10 @@
>
> #include "valgrind.h"
>
> +/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
> + This enum comprises an ABI exported by Valgrind to programs
> + which use client requests. DO NOT CHANGE THE ORDER OF THESE
> + ENTRIES, NOR DELETE ANY -- add new ones at the end. */
> typedef
> enum {
> VG_USERREQ__HG_CLEAN_MEMORY = VG_USERREQ_TOOL_BASE('H','G'),
> @@ -100,20 +104,389 @@
> _VG_USERREQ__HG_PTHREAD_SPIN_INIT_OR_UNLOCK_POST, /* pth_slk_t* */
> _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_PRE, /* pth_slk_t* */
> _VG_USERREQ__HG_PTHREAD_SPIN_LOCK_POST, /* pth_slk_t* */
> - _VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE /* pth_slk_t* */
> + _VG_USERREQ__HG_PTHREAD_SPIN_DESTROY_PRE, /* pth_slk_t* */
> + _VG_USERREQ__HG_CLIENTREQ_UNIMP, /* char* */
> + _VG_USERREQ__HG_USERSO_SEND_PRE, /* arbitrary UWord SO-tag */
> + _VG_USERREQ__HG_USERSO_RECV_POST, /* arbitrary UWord SO-tag */
> + _VG_USERREQ__HG_RESERVED1, /* Do not use */
> + _VG_USERREQ__HG_RESERVED2 /* Do not use */
>
> } Vg_TCheckClientRequest;
>
> +
> +/*----------------------------------------------------------------*/
> +/*--- An implementation-only request -- not for end user use ---*/
> +/*----------------------------------------------------------------*/
> +
> +#define _HG_CLIENTREQ_UNIMP(_qzz_str) \
> + do { \
> + unsigned long _qzz_res; \
> + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
> + _VG_USERREQ__HG_CLIENTREQ_UNIMP, \
> + _qzz_str, 0, 0, 0, 0); \
> + (void)0; \
> + } while(0)
> +
> +
> +/*----------------------------------------------------------------*/
> +/*--- Misc requests ---*/
> +/*----------------------------------------------------------------*/
> +
> /* Clean memory state. This makes Helgrind forget everything it knew
> - about the specified memory range, and resets it to New. This is
> - particularly useful for memory allocators that wish to recycle
> - memory. */
> -#define VALGRIND_HG_CLEAN_MEMORY(_qzz_start, _qzz_len) \
> - do { \
> - unsigned long _qzz_res; \
> - VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__HG_CLEAN_MEMORY, \
> - _qzz_start, _qzz_len, 0, 0, 0); \
> - (void)0; \
> + about the specified memory range. Effectively this announces that
> + the specified memory range now "belongs" to the calling thread, so
> + that: (1) the calling thread can access it safely without
> + synchronisation, and (2) all other threads must sync with this one
> + to access it safely. This is particularly useful for memory
> + allocators that wish to recycle memory. */
> +#define VALGRIND_HG_CLEAN_MEMORY(_qzz_start, _qzz_len) \
> + do { \
> + unsigned long _qzz_res; \
> + VALGRIND_DO_CLIENT_REQUEST( \
> + (_qzz_res), 0, VG_USERREQ__HG_CLEAN_MEMORY, \
> + (_qzz_start), (_qzz_len), 0, 0, 0 \
> + ); \
> + (void)0; \
> } while(0)
>
> +
> +/*----------------------------------------------------------------*/
> +/*--- ThreadSanitizer-compatible requests ---*/
> +/*----------------------------------------------------------------*/
> +
> +/* A quite-broad set of annotations, as used in the ThreadSanitizer
> + project. This implementation aims to be a (source-level)
> + compatible implementation of the macros defined in:
> +
> + http://code.google.com/p/google-perftools/source \
> + /browse/trunk/src/base/dynamic_annotations.h
> +
> + (some of the comments below are taken from the above file)
> +
> + The implementation here is very incomplete, and intended as a
> + starting point. Many of the macros are unimplemented. Rather than
> + allowing unimplemented macros to silently do nothing, they cause an
> + assertion. Intention is to implement them on demand.
> +
> + The major use of these macros is to make visible to race detectors,
> + the behaviour (effects) of user-implemented synchronisation
> + primitives, that the detectors could not otherwise deduce from the
> + normal observation of pthread etc calls.
> +
> + Some of the macros are no-ops in Helgrind. That's because Helgrind
> + is a pure happens-before detector, whereas ThreadSanitizer uses a
> + hybrid lockset and happens-before scheme, which requires more
> + accurate annotations for correct operation.
Correct.
> +
> + The macros are listed in the same order as in dynamic_annotations.h
> + (URL just above).
> +
> + I should point out that I am less than clear about the intended
> + semantics of quite a number of them. Comments and clarifications
> + welcomed!
> +*/
> +
> +/* ----------------------------------------------------------------
> + These four allow description of user-level condition variables,
> + apparently in the style of POSIX's pthread_cond_t. Currently
> + unimplemented and will assert.
> + ----------------------------------------------------------------
> +*/
> +/* Report that wait on the condition variable at address CV has
> + succeeded and the lock at address LOCK is now held. CV and LOCK
> + are completely arbitrary memory addresses which presumably mean
> + something to the application, but are meaningless to Helgrind. */
> +#define ANNOTATE_CONDVAR_LOCK_WAIT(cv, lock) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_CONDVAR_LOCK_WAIT")
> +
> +/* Report that wait on the condition variable at CV has succeeded.
> + Variant w/o lock. */
> +#define ANNOTATE_CONDVAR_WAIT(cv) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_CONDVAR_WAIT")
> +
> +/* Report that we are about to signal on the condition variable at
> + address CV. */
> +#define ANNOTATE_CONDVAR_SIGNAL(cv) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_CONDVAR_SIGNAL")
> +
> +/* Report that we are about to signal_all on the condition variable at
> + CV. */
> +#define ANNOTATE_CONDVAR_SIGNAL_ALL(cv) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_CONDVAR_SIGNAL_ALL")
> +
> +
> +/* ----------------------------------------------------------------
> + Create completely arbitrary happens-before edges between threads.
> + If thread T1 does ANNOTATE_HAPPENS_BEFORE(obj) and later (w.r.t.
> + some notional global clock for the computation) thread T2 does
> + ANNOTATE_HAPPENS_AFTER(obj), then Helgrind will regard all memory
> + accesses done by T1 before the ..BEFORE.. call as happening-before
> + all memory accesses done by T2 after the ..AFTER.. call. Hence
> + Helgrind won't complain about races if T2's accesses afterwards are
> + to the same locations as T1's accesses before.
> +
> + OBJ is a machine word (unsigned long, or void*), is completely
> + arbitrary, and denotes the identity of some synchronisation object
> + you're modelling.
> +
> + You must do the _BEFORE call just before the real sync event on the
> + signaller's side, and _AFTER just after the real sync event on the
> + waiter's side.
> +
> + If none of the rest of these macros make sense to you, at least
> + take the time to understand these two. They form the very essence
> + of describing arbitrary inter-thread synchronisation events to
> + Helgrind. You can get a long way just with them alone.
Brilliant comment! These are indeed the two key annotations.
> + ----------------------------------------------------------------
> +*/
> +#define ANNOTATE_HAPPENS_BEFORE(obj) \
> + do { \
> + unsigned long _qzz_res; \
> + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
> + _VG_USERREQ__HG_USERSO_SEND_PRE, \
> + obj, 0, 0, 0, 0); \
> + (void)0; \
> + } while (0)
> +
> +#define ANNOTATE_HAPPENS_AFTER(obj) \
> + do { \
> + unsigned long _qzz_res; \
> + VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
> + _VG_USERREQ__HG_USERSO_RECV_POST, \
> + obj, 0, 0, 0, 0); \
> + (void)0; \
> + } while (0)
> +
> +
> +/* ----------------------------------------------------------------
> + Memory publishing. The TSan sources say:
> +
> + Report that the bytes in the range [pointer, pointer+size) are about
> + to be published safely. The race checker will create a happens-before
> + arc from the call ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) to
> + subsequent accesses to this memory.
> +
> + I'm not sure I understand what this means exactly, nor whether it
> + is relevant for a pure h-b detector. Leaving unimplemented for
> + now.
So far we used this macro only to address the most frequent false
positive of a hybrid detector.
So, you can say that this annotation is irrelevant to a pure h-b detector.
On the other hand, this annotation may be used to annotate a lockfree
object publishing code, in which case it will become relevant to pure
h-b as well.
> + ----------------------------------------------------------------
> +*/
> +#define ANNOTATE_PUBLISH_MEMORY_RANGE(pointer, size) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_PUBLISH_MEMORY_RANGE")
> +
> +
> +/* ----------------------------------------------------------------
> + TSan sources say:
> +
> + Instruct the tool to create a happens-before arc between
> + MU->Unlock() and MU->Lock(). This annotation may slow down the
> + race detector; normally it is used only when it would be
> + difficult to annotate each of the mutex's critical sections
> + individually using the annotations above.
> +
> + If MU is a posix pthread_mutex_t then Helgrind will do this anyway.
> + In any case, leave as unimp for now. I'm unsure about the intended
> + behaviour.
This annotation makes the hybrid tool behave as a pure h-b for this
particular mutex.
For a pure h-b detector this is a no-op. (the name of the annotation
sucks, I know).
> + ----------------------------------------------------------------
> +*/
> +#define ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(mu) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_MUTEX_IS_USED_AS_CONDVAR")
> +
> +
> +/* ----------------------------------------------------------------
> + TSan sources say:
> +
> + Annotations useful when defining memory allocators, or when
> + memory that was protected in one way starts to be protected in
> + another.
> +
> + Report that a new memory at "address" of size "size" has been
> + allocated. This might be used when the memory has been retrieved
> + from a free list and is about to be reused, or when a the locking
> + discipline for a variable changes.
> +
> + AFAICS this is the same as VALGRIND_HG_CLEAN_MEMORY.
Correct (more or less)
> + ----------------------------------------------------------------
> +*/
> +#define ANNOTATE_NEW_MEMORY(address, size) \
> + VALGRIND_HG_CLEAN_MEMORY((address), (size))
> +
> +
> +/* ----------------------------------------------------------------
> + TSan sources say:
> +
> + Annotations useful when defining FIFO queues that transfer data
> + between threads.
> +
> + All unimplemented. Am not claiming to understand this (yet).
Consider you have a FIFO queue that passes messages between threads.
If it is based on locks, you have a trouble with a hybrid detector.
If it is lockfree, pure h-b is in trouble as well.
You need to create h-b arcs between queue.put() and queue.get().
You can do it with ANNOTATE_HAPPENS_{BEFORE,AFTER}.
You can do it using ANNOTATE_PCQ_*.
The second could be implemented in the detector faster and will loose
less real races (because it will not create any unnecessary h-b arcs).
> + ----------------------------------------------------------------
> +*/
> +
> +/* Report that the producer-consumer queue object at address PCQ has
> + been created. The ANNOTATE_PCQ_* annotations should be used only
> + for FIFO queues. For non-FIFO queues use ANNOTATE_HAPPENS_BEFORE
> + (for put) and ANNOTATE_HAPPENS_AFTER (for get). */
> +#define ANNOTATE_PCQ_CREATE(pcq) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_PCQ_CREATE")
> +
> +/* Report that the queue at address PCQ is about to be destroyed. */
> +#define ANNOTATE_PCQ_DESTROY(pcq) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_PCQ_DESTROY")
> +
> +/* Report that we are about to put an element into a FIFO queue at
> + address PCQ. */
> +#define ANNOTATE_PCQ_PUT(pcq) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_PCQ_PUT")
> +
> +/* Report that we've just got an element from a FIFO queue at address
> + PCQ. */
> +#define ANNOTATE_PCQ_GET(pcq) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_PCQ_GET")
> +
> +
> +/* ----------------------------------------------------------------
> + Annotations that suppress errors. It is usually better to express
> + the program's synchronization using the other annotations, but
> + these can be used when all else fails.
> +
> + Currently these are all unimplemented. I can't think of a simple
> + way to implement them without at least some performance overhead.
ANNOTATE_BENIGN_RACE does not affect performance of the detector since
it is checked only when the detector prints the report.
ANNOTATE_IGNORE_* does slowdown the fast path slightly. Very slightly.
> + ----------------------------------------------------------------
> +*/
> +
> +/* Report that we may have a benign race on ADDRESS. Insert at the
> + point where ADDRESS has been allocated, preferably close to the
> + point where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
> +
> + XXX: what's this actually supposed to do?
The detector will not print the error message. That's all.
> And what's the type of
> + DESCRIPTION?
const char *
> When does the annotation stop having an effect?
When the memory location is freed.
> +*/
> +#define ANNOTATE_BENIGN_RACE(address, description) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_BENIGN_RACE")
> +
> +
> +/* Request the analysis tool to ignore all reads in the current thread
> + until ANNOTATE_IGNORE_READS_END is called. Useful to ignore
> + intentional racey reads, while still checking other reads and all
> + writes. */
> +#define ANNOTATE_IGNORE_READS_BEGIN() \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_IGNORE_READS_BEGIN")
> +
> +/* Stop ignoring reads. */
> +#define ANNOTATE_IGNORE_READS_END() \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_IGNORE_READS_END")
> +
> +/* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes. */
> +#define ANNOTATE_IGNORE_WRITES_BEGIN() \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_IGNORE_WRITES_BEGIN")
> +
> +/* Stop ignoring writes. */
> +#define ANNOTATE_IGNORE_WRITES_END() \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_IGNORE_WRITES_END")
> +
> +/* Start ignoring all memory accesses (reads and writes). */
> +#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
> + do { \
> + ANNOTATE_IGNORE_READS_BEGIN(); \
> + ANNOTATE_IGNORE_WRITES_BEGIN(); \
> + } while (0)
> +
> +/* Stop ignoring all memory accesses. */
> +#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
> + do { \
> + ANNOTATE_IGNORE_WRITES_END(); \
> + ANNOTATE_IGNORE_READS_END(); \
> + } while (0)
> +
> +
> +/* ----------------------------------------------------------------
> + Annotations useful for debugging.
> +
> + Again, so for unimplemented, partly for performance reasons.
> + ----------------------------------------------------------------
> +*/
> +
> +/* Request to trace every access to ADDRESS. */
> +#define ANNOTATE_TRACE_MEMORY(address) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_TRACE_MEMORY")
> +
> +/* Report the current thread name to a race detector. */
This is *very* useful for debugging if the program actually calls it.
--kcc
> +#define ANNOTATE_THREAD_NAME(name) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_THREAD_NAME")
> +
> +
> +/* ----------------------------------------------------------------
> + Annotations for describing behaviour of user-implemented lock
> + primitives. In all cases, the LOCK argument is a completely
> + arbitrary machine word (unsigned long, or void*) and can be any
> + value which gives a unique identity to the lock objects being
> + modelled.
> +
> + We just pretend they're ordinary posix rwlocks. That'll probably
> + give some rather confusing wording in error messages, claiming that
> + the arbitrary LOCK values are pthread_rwlock_t*'s, when in fact
> + they are not. Ah well.
> + ----------------------------------------------------------------
> +*/
> +/* Report that a lock has just been created at address LOCK. */
> +#define ANNOTATE_RWLOCK_CREATE(lock) \
> + do { \
> + unsigned long _qzz_res; \
> + VALGRIND_DO_CLIENT_REQUEST( \
> + _qzz_res, 0, _VG_USERREQ__HG_PTHREAD_RWLOCK_INIT_POST, \
> + lock, 0, 0, 0, 0 \
> + ); \
> + (void)0; \
> + } while(0)
> +
> +/* Report that the lock at address LOCK is about to be destroyed. */
> +#define ANNOTATE_RWLOCK_DESTROY(lock) \
> + do { \
> + unsigned long _qzz_res; \
> + VALGRIND_DO_CLIENT_REQUEST( \
> + _qzz_res, 0, _VG_USERREQ__HG_PTHREAD_RWLOCK_DESTROY_PRE, \
> + lock, 0, 0, 0, 0 \
> + ); \
> + (void)0; \
> + } while(0)
> +
> +/* Report that the lock at address LOCK has just been acquired.
> + is_w=1 for writer lock, is_w=0 for reader lock. */
> +#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
> + do { \
> + unsigned long _qzz_res; \
> + VALGRIND_DO_CLIENT_REQUEST( \
> + _qzz_res, 0, _VG_USERREQ__HG_PTHREAD_RWLOCK_LOCK_POST, \
> + lock, is_w ? 1 : 0, 0, 0, 0 \
> + ); \
> + (void)0; \
> + } while(0)
> +
> +/* Report that the lock at address LOCK is about to be released. */
> + #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
> + do { \
> + unsigned long _qzz_res; \
> + VALGRIND_DO_CLIENT_REQUEST( \
> + _qzz_res, 0, _VG_USERREQ__HG_PTHREAD_RWLOCK_UNLOCK_PRE, \
> + lock, 0, 0, 0, 0 \
> + ); \
> + (void)0; \
> + } while(0)
> +
> +
> +/* ----------------------------------------------------------------
> + Annotations useful for testing race detectors.
> + ----------------------------------------------------------------
> +*/
> +
> +/* Report that we expect a race on the variable at ADDRESS. Use only
> + in unit tests for a race detector. */
> +#define ANNOTATE_EXPECT_RACE(address, description) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_EXPECT_RACE")
> +
> +/* A no-op. Insert where you like to test the interceptors. */
> +#define ANNOTATE_NO_OP(arg) \
> + _HG_CLIENTREQ_UNIMP("ANNOTATE_NO_OP")
> +
> +
> #endif /* __HELGRIND_H */
>
> Modified: trunk/helgrind/hg_main.c
> ===================================================================
> --- trunk/helgrind/hg_main.c 2009-08-14 10:19:26 UTC (rev 10809)
> +++ trunk/helgrind/hg_main.c 2009-08-14 11:08:24 UTC (rev 10810)
> @@ -2966,6 +2966,107 @@
> }
>
>
> +/* ----------------------------------------------------- */
> +/* ----- events to do with user-specified HB edges ----- */
> +/* ----------------------------------------------------- */
> +
> +/* A mapping from arbitrary UWord tag to the SO associated with it.
> + The UWord tags are meaningless to us, interpreted only by the
> + user. */
> +
> +
> +
> +/* UWord -> SO* */
> +static WordFM* map_usertag_to_SO = NULL;
> +
> +static void map_usertag_to_SO_INIT ( void ) {
> + if (UNLIKELY(map_usertag_to_SO == NULL)) {
> + map_usertag_to_SO = VG_(newFM)( HG_(zalloc),
> + "hg.mutS.1", HG_(free), NULL );
> + tl_assert(map_usertag_to_SO != NULL);
> + }
> +}
> +
> +static SO* map_usertag_to_SO_lookup_or_alloc ( UWord usertag ) {
> + UWord key, val;
> + map_usertag_to_SO_INIT();
> + if (VG_(lookupFM)( map_usertag_to_SO, &key, &val, usertag )) {
> + tl_assert(key == (UWord)usertag);
> + return (SO*)val;
> + } else {
> + SO* so = libhb_so_alloc();
> + VG_(addToFM)( map_usertag_to_SO, usertag, (UWord)so );
> + return so;
> + }
> +}
> +
> +// If it's ever needed (XXX check before use)
> +//static void map_usertag_to_SO_delete ( UWord usertag ) {
> +// UWord keyW, valW;
> +// map_usertag_to_SO_INIT();
> +// if (VG_(delFromFM)( map_usertag_to_SO, &keyW, &valW, usertag )) {
> +// SO* so = (SO*)valW;
> +// tl_assert(keyW == usertag);
> +// tl_assert(so);
> +// libhb_so_dealloc(so);
> +// }
> +//}
> +
> +
> +static
> +void evh__HG_USERSO_SEND_PRE ( ThreadId tid, UWord usertag )
> +{
> + /* TID is just about to notionally sent a message on a notional
> + abstract synchronisation object whose identity is given by
> + USERTAG. Bind USERTAG to a real SO if it is not already so
> + bound, and do a 'strong send' on the SO. This is later used by
> + other thread(s) which successfully 'receive' from the SO,
> + thereby acquiring a dependency on this signalling event. */
> + Thread* thr;
> + SO* so;
> +
> + if (SHOW_EVENTS >= 1)
> + VG_(printf)("evh__HG_USERSO_SEND_PRE(ctid=%d, usertag=%#lx)\n",
> + (Int)tid, usertag );
> +
> + thr = map_threads_maybe_lookup( tid );
> + tl_assert(thr); /* cannot fail - Thread* must already exist */
> +
> + so = map_usertag_to_SO_lookup_or_alloc( usertag );
> + tl_assert(so);
> +
> + libhb_so_send( thr->hbthr, so, True/*strong_send*/ );
> +}
> +
> +static
> +void evh__HG_USERSO_RECV_POST ( ThreadId tid, UWord usertag )
> +{
> + /* TID has just notionally received a message from a notional
> + abstract synchronisation object whose identity is given by
> + USERTAG. Bind USERTAG to a real SO if it is not already so
> + bound. If the SO has at some point in the past been 'sent' on,
> + to a 'strong receive' on it, thereby acquiring a dependency on
> + the sender. */
> + Thread* thr;
> + SO* so;
> +
> + if (SHOW_EVENTS >= 1)
> + VG_(printf)("evh__HG_USERSO_RECV_POST(ctid=%d, usertag=%#lx)\n",
> + (Int)tid, usertag );
> +
> + thr = map_threads_maybe_lookup( tid );
> + tl_assert(thr); /* cannot fail - Thread* must already exist */
> +
> + so = map_usertag_to_SO_lookup_or_alloc( usertag );
> + tl_assert(so);
> +
> + /* Acquire a dependency on it. If the SO has never so far been
> + sent on, then libhb_so_recv will do nothing. So we're safe
> + regardless of SO's history. */
> + libhb_so_recv( thr->hbthr, so, True/*strong_recv*/ );
> +}
> +
> +
> /*--------------------------------------------------------------*/
> /*--- Lock acquisition order monitoring ---*/
> /*--------------------------------------------------------------*/
> @@ -4242,6 +4343,30 @@
> evh__HG_PTHREAD_SPIN_DESTROY_PRE( tid, (void*)args[1] );
> break;
>
> + case _VG_USERREQ__HG_CLIENTREQ_UNIMP: {
> + /* char* who */
> + HChar* who = (HChar*)args[1];
> + HChar buf[50 + 50];
> + Thread* thr = map_threads_maybe_lookup( tid );
> + tl_assert( thr ); /* I must be mapped */
> + tl_assert( who );
> + tl_assert( VG_(strlen)(who) <= 50 );
> + VG_(sprintf)(buf, "Unimplemented client request macro \"%s\"", who );
> + /* record_error_Misc strdup's buf, so this is safe: */
> + HG_(record_error_Misc)( thr, buf );
> + break;
> + }
> +
> + case _VG_USERREQ__HG_USERSO_SEND_PRE:
> + /* UWord arbitrary-SO-tag */
> + evh__HG_USERSO_SEND_PRE( tid, args[1] );
> + break;
> +
> + case _VG_USERREQ__HG_USERSO_RECV_POST:
> + /* UWord arbitrary-SO-tag */
> + evh__HG_USERSO_RECV_POST( tid, args[1] );
> + break;
> +
> default:
> /* Unhandled Helgrind client request! */
> tl_assert2(0, "unhandled Helgrind client request 0x%lx",
>
>
> ------------------------------------------------------------------------------
> Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
> trial. Simplify your report design, integration and deployment - and focus on
> what you do best, core application coding. Discover what's new with
> Crystal Reports now. http://p.sf.net/sfu/bobj-july
> _______________________________________________
> Valgrind-developers mailing list
> Val...@li...
> https://lists.sourceforge.net/lists/listinfo/valgrind-developers
>
|