From: Philippe Waroquiers Date: Mon, 28 Nov 2016 18:16:27 +0000 (+0000) Subject: Addition of helgrind client request VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN X-Git-Tag: svn/VALGRIND_3_13_0~263 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed9721f0f4a58f733eb65b7f193632cdd89c49d4;p=thirdparty%2Fvalgrind.git Addition of helgrind client request VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN See helgrind.h for description git-svn-id: svn://svn.valgrind.org/valgrind/trunk@16158 --- diff --git a/NEWS b/NEWS index 25f94a9426..3ff733d3b1 100644 --- a/NEWS +++ b/NEWS @@ -47,6 +47,8 @@ X86/MacOSX 10.11/12, AMD64/MacOSX 10.11/12 and TILEGX/Linux. - Support for --xtree-memory and 'xtmemory []>'. + - addition of client request VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN, + useful for Ada gnat compiled applications. * ==================== OTHER CHANGES ==================== diff --git a/helgrind/helgrind.h b/helgrind/helgrind.h index d194c4473d..f560a4db91 100644 --- a/helgrind/helgrind.h +++ b/helgrind/helgrind.h @@ -133,7 +133,8 @@ typedef _VG_USERREQ__HG_PTHREAD_COND_SIGNAL_POST, /* pth_cond_t* */ _VG_USERREQ__HG_PTHREAD_COND_BROADCAST_POST,/* pth_cond_t* */ _VG_USERREQ__HG_RTLD_BIND_GUARD, /* int flags */ - _VG_USERREQ__HG_RTLD_BIND_CLEAR /* int flags */ + _VG_USERREQ__HG_RTLD_BIND_CLEAR, /* int flags */ + _VG_USERREQ__HG_GNAT_DEPENDENT_MASTER_JOIN /* void*d, void*m */ } Vg_TCheckClientRequest; @@ -424,6 +425,37 @@ typedef _res; \ })) +/* End-user request for Ada applications compiled with GNAT. + Helgrind understands the Ada concept of Ada task dependencies and + terminations. See Ada Reference Manual section 9.3 "Task Dependence + - Termination of Tasks". + However, in some cases, the master of (terminated) tasks completes + only when the application exits. An example of this is dynamically + allocated tasks with an access type defined at Library Level. + By default, the state of such tasks in Helgrind will be 'exited but + join not done yet'. Many tasks in such a state are however causing + Helgrind CPU and memory to increase significantly. + VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN can be used to indicate + to Helgrind that a not yet completed master has however already + 'seen' the termination of a dependent : this is conceptually the + same as a pthread_join and causes the cleanup of the dependent + as done by Helgrind when a master completes. + This allows to avoid the overhead in helgrind caused by such tasks. + A typical usage for a master to indicate it has done conceptually a join + with a dependent task before the master completes is: + while not Dep_Task'Terminated loop + ... do whatever to wait for Dep_Task termination. + end loop; + VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN + (Dep_Task'Identity, + Ada.Task_Identification.Current_Task); + Note that VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN should be a binding + to a C function built with the below macro. */ +#define VALGRIND_HG_GNAT_DEPENDENT_MASTER_JOIN(_qzz_dep, _qzz_master) \ + DO_CREQ_v_WW(_VG_USERREQ__HG_GNAT_DEPENDENT_MASTER_JOIN, \ + void*,(_qzz_dep), \ + void*,(_qzz_master)) + /*----------------------------------------------------------------*/ /*--- ---*/ /*--- ThreadSanitizer-compatible requests ---*/ diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c index 8a75a84b46..a0724d1b51 100644 --- a/helgrind/hg_main.c +++ b/helgrind/hg_main.c @@ -4883,7 +4883,7 @@ typedef Word master_level; // level of dependency between master and dependent Thread* hg_dependent; // helgrind Thread* for dependent task. } - GNAT_dmml; + GNAT_dmml; // (d)ependent (m)aster (m)aster_(l)evel. static XArray* gnat_dmmls; /* of GNAT_dmml */ static void gnat_dmmls_INIT (void) { @@ -5107,6 +5107,41 @@ Bool hg_handle_client_request ( ThreadId tid, UWord* args, UWord* ret) *ret = -1; break; + /* This thread (tid) (a master) is informing us that it has + seen the termination of a dependent task, and that this should + be considered as a join between master and dependent. */ + case _VG_USERREQ__HG_GNAT_DEPENDENT_MASTER_JOIN: { + Word n; + const Thread *stayer = map_threads_maybe_lookup( tid ); + const void *dependent = (void*)args[1]; + const void *master = (void*)args[2]; + + if (0) + VG_(printf)("HG_GNAT_DEPENDENT_MASTER_JOIN (tid %d): " + "self_id = %p Thread* = %p dependent %p\n", + (Int)tid, master, stayer, dependent); + + gnat_dmmls_INIT(); + /* Similar loop as for master completed hook below, but stops at + the first matching occurence, only comparing master and + dependent. */ + for (n = VG_(sizeXA) (gnat_dmmls) - 1; n >= 0; n--) { + GNAT_dmml *dmml = (GNAT_dmml*) VG_(indexXA)(gnat_dmmls, n); + if (dmml->master == master + && dmml->dependent == dependent) { + if (0) + VG_(printf)("quitter %p dependency to stayer %p (join)\n", + dmml->hg_dependent->hbthr, stayer->hbthr); + tl_assert(dmml->hg_dependent->hbthr != stayer->hbthr); + generate_quitter_stayer_dependence (dmml->hg_dependent->hbthr, + stayer->hbthr); + VG_(removeIndexXA) (gnat_dmmls, n); + break; + } + } + break; + } + /* --- --- Client requests for Helgrind's use only --- --- */ /* Some thread is telling us its pthread_t value. Record the