[m-rev.] For post-commit review: ThreadScope updates.
Paul Bone
pbone at csse.unimelb.edu.au
Sat Apr 2 16:48:06 AEDT 2011
ThreadScope updates.
Introduce some new threadscope events for profiling the use of futures.
Update mercury's threadscope runtime so that it conforms with changes to
ghc-events (the threadscope event library).
runtime/mercury_threadscope.h:
Add some new typedefs.
runtime/mercury_threadscope.c:
Conform to changes in the threadscope eventlog format, in particular which
event IDs belong to which events.
Support the capset[3] events created by Duncan Coutts. Within Mercury we
refer to capsets as "engine sets".
Remove our runtime type event and use the capset runtime identifier event
which takes a string rather than an integer.
Use #define'd constants rather than magic numbers for the sizes of event
attributes.
Make the sparking event a Mercury specific event. It appears that GHC
won't use this, even in the future[1, 2].
runtime/mercury_threadscope.h:
runtime/mercury_threadscope.c:
Add support for new threadscope events:
New Future - A future is being created, the context of this event tells
us which parallel conjunction the future belongs to.
Wait on Future - Attempt to wait on the production of a future, both
with and without suspending the current thread because
the future may already be available.
Signal future - After producing a value for a future signal that that value is now available.
Note that waking up after suspending on a future is available already via
THREAD_RUNNABLE when the thread is added to the run queue, and
THREAD_RUNNING when an engine begins executing that thread.
runtime/mercury_par_builtin.h:
Use the new threadscope events for instrumenting the use of futures.
References:
1. There are commented out event ids for creating sparks that are marked as
deprecated in the ghc-events tool.
2. Online conversation in #ghc on irc.freenode.net, Simon said that Sparks
will be deprecated in favor of: https://github.com/simonmar/monad-par.
Which, I believe, is covered in a paper submitted a paper to ICFP.
3. http://tinyurl.com/67gf2om
Index: runtime/mercury_par_builtin.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_par_builtin.h,v
retrieving revision 1.2
diff -u -p -b -r1.2 mercury_par_builtin.h
--- runtime/mercury_par_builtin.h 9 Oct 2010 23:43:18 -0000 1.2
+++ runtime/mercury_par_builtin.h 2 Apr 2011 05:34:25 -0000
@@ -85,6 +85,7 @@ vim: ft=c ts=4 sw=4 et
\
Future->MR_fut_signalled = MR_FALSE; \
Future->MR_fut_suspended = NULL; \
+ MR_maybe_post_new_future(Future); \
} while (0)
/*
@@ -107,6 +108,7 @@ vim: ft=c ts=4 sw=4 et
if (Future->MR_fut_signalled) { \
Value = Future->MR_fut_value; \
MR_UNLOCK(&(Future->MR_fut_lock), "future.wait"); \
+ MR_maybe_post_wait_future_nosuspend(Future); \
} else { \
MR_Context *ctxt; \
\
@@ -131,6 +133,7 @@ vim: ft=c ts=4 sw=4 et
Future->MR_fut_suspended = ctxt; \
\
MR_UNLOCK(&(Future->MR_fut_lock), "future.wait"); \
+ MR_maybe_post_wait_future_suspended(Future); \
\
MR_maybe_post_stop_context; \
MR_ENGINE(MR_eng_this_context) = NULL; \
@@ -138,18 +141,6 @@ vim: ft=c ts=4 sw=4 et
} \
} while (0)
-#ifdef MR_THREADSCOPE
- #define MR_maybe_post_stop_context \
- do { \
- MR_threadscope_post_stop_context(MR_TS_STOP_REASON_BLOCKED); \
- } while (0)
-
-#else
- #define MR_maybe_post_stop_context \
- do { \
- } while (0)
-#endif
-
#define MR_par_builtin_get_future(Future, Value) \
do { \
assert(Future->MR_fut_signalled); \
@@ -161,6 +152,11 @@ vim: ft=c ts=4 sw=4 et
MR_Context *ctxt; \
MR_Context *next; \
\
+ /* \
+ ** Post the threadscope signal future message before waking any \
+ ** threads (and posting those messages. \
+ */ \
+ MR_maybe_post_signal_future(Future); \
MR_LOCK(&(Future->MR_fut_lock), "future.signal"); \
\
/* \
@@ -186,6 +182,43 @@ vim: ft=c ts=4 sw=4 et
MR_UNLOCK(&(Future->MR_fut_lock), "future.signal"); \
} while (0)
+#ifdef MR_THREADSCOPE
+ #define MR_maybe_post_stop_context \
+ do { \
+ MR_threadscope_post_stop_context(MR_TS_STOP_REASON_BLOCKED); \
+ } while (0)
+
+ #define MR_maybe_post_new_future(future) \
+ do { \
+ MR_threadscope_post_new_future(future); \
+ } while (0)
+
+ #define MR_maybe_post_wait_future_nosuspend(future) \
+ do { \
+ MR_threadscope_post_wait_future_nosuspend(future); \
+ } while (0)
+
+ #define MR_maybe_post_wait_future_suspended(future) \
+ do { \
+ MR_threadscope_post_wait_future_suspended(future); \
+ } while (0)
+
+ #define MR_maybe_post_signal_future(future) \
+ do { \
+ MR_threadscope_post_signal_future(future); \
+ } while (0)
+
+#else
+ #define MR_noop \
+ do { \
+ } while (0)
+ #define MR_maybe_post_stop_context MR_noop
+ #define MR_maybe_post_new_future(future) MR_noop
+ #define MR_maybe_post_wait_future_nosuspend(future) MR_noop
+ #define MR_maybe_post_wait_future_suspended(future) MR_noop
+ #define MR_maybe_post_signal_future(future) MR_noop
+#endif
+
#else
#define MR_par_builtin_new_future(Future) \
Index: runtime/mercury_threadscope.c
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_threadscope.c,v
retrieving revision 1.9
diff -u -p -b -r1.9 mercury_threadscope.c
--- runtime/mercury_threadscope.c 25 Mar 2011 03:13:42 -0000 1.9
+++ runtime/mercury_threadscope.c 2 Apr 2011 05:34:25 -0000
@@ -137,33 +137,52 @@ ENDINIT
#define MR_TS_EVENT_GC_WORK 21 /* () */
#define MR_TS_EVENT_GC_DONE 22 /* () */
+/* 23, 24 used by eden */
+
/*
-** Duncan Coutts has reserved IDs 23-37 in a discussion via IRC.
+** Capsets or capability sets are groups of engines with some association, for
+** instance a group of threads in a process.
*/
+#define MR_TS_EVENT_CAPSET_CREATE 25 /* (capset, capset_type) */
+#define MR_TS_EVENT_CAPSET_DELETE 26 /* (capset) */
+#define MR_TS_EVENT_CAPSET_ASSIGN_CAP 27 /* (capset, cap) */
+#define MR_TS_EVENT_CAPSET_REMOVE_CAP 28 /* (capset, cap) */
+/* the RTS identifier is in the form of "GHC-version rts_way" */
+#define MR_TS_EVENT_RTS_IDENTIFIER 29 /* (capset, name_version_string) */
+/* the vectors in two these events are null separated strings */
+#define MR_TS_EVENT_PROGRAM_ARGS 30 /* (capset, commandline_vector) */
+#define MR_TS_EVENT_PROGRAM_ENV 31 /* (capset, environment_vector) */
-#define MR_TS_EVENT_RUNTIME_TYPE 38 /* (rt_type) */
+#define MR_TS_EVENT_OSPROCESS_PID 32 /* (capset, pid, parent_pid) */
+/*
+** Duncan Coutts has reserved IDs 33-37 in a discussion via IRC.
+*/
+#define MR_TS_EVENT_LOOKING_FOR_GLOBAL_WORK \
+ 38 /* () */
#define MR_TS_EVENT_STRING 39 /* (string, id) */
#define MR_TS_EVENT_CALL_MAIN 40 /* () */
-#define MR_TS_EVENT_LOOKING_FOR_GLOBAL_WORK \
- 41 /* () */
- /* XXX: Is it possible to infer the
- * dynamic conj id here? */
-#define MR_TS_EVENT_SPARKING 42 /* (int id, spark id) */
-#define MR_TS_NUM_EVENT_TAGS 43
+#define MR_TS_NUM_EVENT_TAGS 41
#define MR_TS_MER_EVENT_START 100
#define MR_TS_MER_EVENT_START_PAR_CONJ 100 /* (int id, memo'd string id) */
#define MR_TS_MER_EVENT_STOP_PAR_CONJ 101 /* (int id) */
-#define MR_TS_MER_EVENT_STOP_PAR_CONJUNCT 102 /* (itn id) */
+#define MR_TS_MER_EVENT_STOP_PAR_CONJUNCT 102 /* (int id) */
+/*
+** Creating sparks is not specifically mercury, but conjunct IDs are,
+** If other systems wish to use this event they can move it to the main events
+** section.
+*/
+#define MR_TS_MER_EVENT_SPARKING 103 /* (int id, spark id) */
-#define MR_TS_NUM_MER_EVENTS 3
+#define MR_TS_MER_EVENT_FUT_CREATE 104 /* (fut id) */
+#define MR_TS_MER_EVENT_FUT_WAIT_NOSUSPEND 105 /* (fut id) */
+#define MR_TS_MER_EVENT_FUT_WAIT_SUSPENDED 106 /* (fut id) */
+#define MR_TS_MER_EVENT_FUT_SIGNAL 107 /* (fut id) */
-#define MR_TS_RUNTIME_HASKELL 0
-#define MR_TS_RUNTIME_EDEN 1
-#define MR_TS_RUNTIME_MERCURY 2
+#define MR_TS_NUM_MER_EVENTS 8
#if 0 /* DEPRECATED EVENTS: */
#define EVENT_CREATE_SPARK 13 /* (cap, thread) */
@@ -171,6 +190,13 @@ ENDINIT
#endif
/*
+ * Engine set type values for EVENT_CAPSET_CREATE
+ */
+#define MR_TS_ENGSET_TYPE_CUSTOM 1 /* reserved for end-user applications */
+#define MR_TS_ENGSET_TYPE_OSPROCESS 2 /* engines belong to the same OS process */
+#define MR_TS_ENGSET_TYPE_CLOCKDOMAIN 3 /* engines share a local clock/time */
+
+/*
** GHC uses 2MB per buffer. Note that the minimum buffer size is the size of
** the largest message plus the size of the block marker message, however it is
** _sensible_ for the buffer to be much larger so that we make system calls
@@ -232,6 +258,19 @@ typedef struct {
/***************************************************************************/
+#define SZ_CAPSET_ID 4
+#define SZ_CAPSET_TYPE 2
+#define SZ_CONTEXT_ID 4
+#define SZ_CONTEXT_STOP_REASON 2
+#define SZ_DYN_CONJ_ID 8
+#define SZ_ENGINELOG_OFFSET 4
+#define SZ_ENGINE_ID 2
+#define SZ_PID 4
+#define SZ_SPARK_ID 4
+#define SZ_STATIC_CONJ_ID 4
+#define SZ_TIME 8
+#define SZ_FUTURE_ID 8
+
static EventTypeDesc event_type_descs[] = {
{
/*
@@ -240,7 +279,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_STARTUP,
"Startup (num_engines)",
- 2 /* MR_EngineId */
+ SZ_ENGINE_ID
},
{
/*
@@ -259,7 +298,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_BLOCK_MARKER,
"A block of events generated by a specific engine follows",
- 4 + 8 + 2 /* EnginelogOffset, Time, MR_EngineId */
+ SZ_ENGINELOG_OFFSET + SZ_TIME + SZ_ENGINE_ID
},
{
/*
@@ -267,7 +306,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_CREATE_THREAD,
"A context is created or re-used",
- 4 /* MR_ContextId */
+ SZ_CONTEXT_ID
},
{
/*
@@ -275,7 +314,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_THREAD_RUNNABLE,
"The context is being placed on the run queue",
- 4 /* MR_ContextId */
+ SZ_CONTEXT_ID
},
{
/*
@@ -283,7 +322,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_RUN_SPARK,
"Run a spark from the local stack",
- 4 + 4 /* MR_ContextId + MR_SparkId */
+ SZ_CONTEXT_ID + SZ_SPARK_ID
},
{
/*
@@ -292,7 +331,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_STEAL_SPARK,
"Run a spark stolen from another engine",
- 4 + 2 + 4 /* MR_ContextId + MR_EngineId + SparkId */
+ SZ_CONTEXT_ID + SZ_ENGINE_ID + SZ_SPARK_ID
},
{
/*
@@ -301,7 +340,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_RUN_THREAD,
"Run context",
- 4 /* MR_ContextId */
+ SZ_CONTEXT_ID
},
{
/*
@@ -310,7 +349,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_STOP_THREAD,
"Context stopped",
- 4 + 2 /* MR_ContextId, MR_ContextStopReason */
+ SZ_CONTEXT_ID + SZ_CONTEXT_STOP_REASON
},
{
/*
@@ -318,7 +357,7 @@ static EventTypeDesc event_type_descs[]
*/
MR_TS_EVENT_CREATE_SPARK_THREAD,
"Create a context for executing a spark",
- 4 /* MR_ContextId */
+ SZ_CONTEXT_ID
},
{
MR_TS_EVENT_LOG_MSG,
@@ -343,15 +382,6 @@ static EventTypeDesc event_type_descs[]
},
{
/*
- ** The runtime system writes down which type of runtime system it is.
- ** ie, Haskell, Eden or Mercury.
- */
- MR_TS_EVENT_RUNTIME_TYPE,
- "The type of the runtime",
- 2
- },
- {
- /*
** The runtime system registers a string and an ID for it so that the
** ID represents the string in future messages.
*/
@@ -374,9 +404,49 @@ static EventTypeDesc event_type_descs[]
0
},
{
- MR_TS_EVENT_SPARKING,
+ MR_TS_EVENT_CAPSET_CREATE,
+ "Create an engine set",
+ SZ_CAPSET_ID + SZ_CAPSET_TYPE
+ },
+ {
+ MR_TS_EVENT_CAPSET_DELETE,
+ "Detete an engine set",
+ SZ_CAPSET_ID
+ },
+ {
+ MR_TS_EVENT_CAPSET_ASSIGN_CAP,
+ "Add an engine to an engine set",
+ SZ_CAPSET_ID + SZ_ENGINE_ID
+ },
+ {
+ MR_TS_EVENT_CAPSET_REMOVE_CAP,
+ "Add an engine to an engine set",
+ SZ_CAPSET_ID + SZ_ENGINE_ID
+ },
+ {
+ MR_TS_EVENT_RTS_IDENTIFIER,
+ "The type of the runtime system for this capset",
+ -1
+ },
+ {
+ MR_TS_EVENT_PROGRAM_ARGS,
+ "The command line arguments of this process",
+ -1
+ },
+ {
+ MR_TS_EVENT_PROGRAM_ENV,
+ "The environment variables this process inherited",
+ -1
+ },
+ {
+ MR_TS_EVENT_OSPROCESS_PID,
+ "The pid and parent pid of this process",
+ 2*SZ_PID
+ },
+ {
+ MR_TS_MER_EVENT_SPARKING,
"A spark is being created",
- 8 + 4 /* Dynamic Conj ID + Spark ID */
+ SZ_DYN_CONJ_ID + SZ_SPARK_ID
/*
* Note that the dynamic conj ID is only useful for Mercury. other
* implementors may want different attributes here.
@@ -385,17 +455,41 @@ static EventTypeDesc event_type_descs[]
{
MR_TS_MER_EVENT_START_PAR_CONJ,
"Start a parallel conjunction (dyn id, static id)",
- 8 + 4 /* Dynamic Conj ID + Static Conj ID */
+ SZ_DYN_CONJ_ID + SZ_STATIC_CONJ_ID
},
{
MR_TS_MER_EVENT_STOP_PAR_CONJ,
"Stop a parallel conjunction (dyn id)",
- 8 /* Dynamic Conj ID */
+ SZ_DYN_CONJ_ID
},
{
MR_TS_MER_EVENT_STOP_PAR_CONJUNCT,
"Stop a parallel conjunct (dyn id)",
- 8 /* Dynamic Conj ID */
+ SZ_DYN_CONJ_ID
+ },
+ {
+ /*
+ * The dynamic conjunction id can be inferred from contact, it is the
+ * next conjunction started after this event.
+ */
+ MR_TS_MER_EVENT_FUT_CREATE,
+ "Create a future (future id)",
+ SZ_FUTURE_ID
+ },
+ {
+ MR_TS_MER_EVENT_FUT_WAIT_NOSUSPEND,
+ "Wait on a future without suspending (no waiting) (future id)",
+ SZ_FUTURE_ID
+ },
+ {
+ MR_TS_MER_EVENT_FUT_WAIT_SUSPENDED,
+ "Wait on a future by suspending this thread (future id)",
+ SZ_FUTURE_ID
+ },
+ {
+ MR_TS_MER_EVENT_FUT_SIGNAL,
+ "Signal a future (future id)",
+ SZ_FUTURE_ID
},
{
/* Mark the end of this array. */
@@ -433,6 +527,21 @@ static struct MR_threadscope_event_buffe
** An ID that may be allocated to the next string to be registered.
*/
static MR_TS_StringId MR_next_string_id = 0;
+static MR_EngSetId next_engset_id = 0;
+
+static MR_EngSetId process_engset_id;
+
+/***************************************************************************/
+
+static MR_EngSetId
+get_next_engset_id(void)
+{
+ /*
+ * This is a seperate function as I may have to add locking or atomic ops
+ * later.
+ */
+ return next_engset_id++;
+}
/***************************************************************************/
@@ -635,6 +744,27 @@ MR_STATIC_INLINE void put_spark_id(
put_be_uint32(buffer, spark_id);
}
+MR_STATIC_INLINE void put_engset_id(
+ struct MR_threadscope_event_buffer *buffer,
+ MR_EngSetId engset_id)
+{
+ put_be_uint32(buffer, engset_id);
+}
+
+MR_STATIC_INLINE void put_engset_type(
+ struct MR_threadscope_event_buffer *buffer,
+ MR_EngSetType type)
+{
+ put_be_uint16(buffer, type);
+}
+
+MR_STATIC_INLINE void put_future_id(
+ struct MR_threadscope_event_buffer *buffer,
+ MR_Future* id)
+{
+ put_be_uint64(buffer, (MR_Word)id);
+}
+
/***************************************************************************/
static struct MR_threadscope_event_buffer*
@@ -653,9 +783,6 @@ static void
put_event_type(struct MR_threadscope_event_buffer *buffer,
EventTypeDesc *event_type);
-static MR_TS_StringId
-MR_threadscope_register_string(const char *string);
-
static MR_bool
flush_event_buffer(struct MR_threadscope_event_buffer *buffer);
@@ -665,6 +792,43 @@ maybe_close_block(struct MR_threadscope_
static void
open_block(struct MR_threadscope_event_buffer *buffer, MR_Unsigned eng_id);
+/***************************************************************************/
+
+static MR_TS_StringId
+MR_threadscope_register_string(const char *string);
+
+/*
+** These four events are used to create and manage engine sets. Haskell calls
+** these cap sets.
+**
+** The first two work on the global event buffer and are not thread safe.
+*/
+static void
+MR_threadscope_post_create_engset(MR_EngSetId id, MR_EngSetType type);
+
+static void
+MR_threadscope_post_destroy_engset(MR_EngSetId id);
+
+static void
+MR_threadscope_post_engset_add(struct MR_threadscope_event_buffer *buffer,
+ MR_EngSetId id, MR_EngineId eng);
+
+static void
+MR_threadscope_post_engset_remove(MR_EngSetId id, MR_EngineId eng);
+
+/*
+** Post the name and version of the runtime system to the log file.
+**
+** Note that this is the name of the implementation (mmc), not the name of the
+** language (mercury).
+**
+** The name and version are separated by a '-'.
+*/
+static void
+MR_threadscope_post_runtime_identifier(MR_EngSetId id, const char *ident);
+
+/***************************************************************************/
+
static void
start_gc_callback(void);
static void
@@ -719,10 +883,13 @@ MR_setup_threadscope(void)
MR_open_output_file_and_write_prelude();
/*
- ** Put the runtime type event in the buffer.
+ ** Post the initial events to the buffer.
*/
- put_event_header(&global_buffer, MR_TS_EVENT_RUNTIME_TYPE, 0);
- put_be_uint16(&global_buffer, MR_TS_RUNTIME_MERCURY);
+ process_engset_id = get_next_engset_id();
+ MR_threadscope_post_create_engset(process_engset_id,
+ MR_TS_ENGSET_TYPE_OSPROCESS);
+ MR_threadscope_post_runtime_identifier(process_engset_id,
+ "mmc-" MR_VERSION);
/*
** Put the startup event in the buffer.
@@ -739,6 +906,9 @@ MR_finalize_threadscope(void)
MR_DO_THREADSCOPE_DEBUG(
fprintf(stderr, "In finalize threadscope thread: 0x%lx\n", pthread_self())
);
+
+ MR_threadscope_post_destroy_engset(process_engset_id);
+
flush_event_buffer(&global_buffer);
MR_close_output_file();
}
@@ -760,6 +930,14 @@ MR_threadscope_setup_engine(MercuryEngin
eng->MR_eng_cpu_clock_ticks_offset = MR_global_offset;
eng->MR_eng_ts_buffer = MR_create_event_buffer();
+
+ MR_threadscope_post_engset_add(eng->MR_eng_ts_buffer, process_engset_id,
+ eng->MR_eng_id);
+ /*
+ ** Flush the buffer to ensure the message above (which lacks a timestamp)
+ ** appears in a sensible place in the buffer.
+ */
+ flush_event_buffer(eng->MR_eng_ts_buffer);
}
void
@@ -771,6 +949,8 @@ MR_threadscope_finalize_engine(MercuryEn
fprintf(stderr, "In threadscope finalize engine thread: 0x%lx\n", pthread_self())
);
+ MR_threadscope_post_engset_remove(process_engset_id, eng->MR_eng_id);
+
MR_US_SPIN_LOCK(&(buffer->MR_tsbuffer_lock));
if (!enough_room_for_event(buffer, MR_TS_EVENT_SHUTDOWN)) {
@@ -1141,14 +1321,14 @@ MR_threadscope_post_sparking(MR_Word* dy
struct MR_threadscope_event_buffer *buffer = MR_ENGINE(MR_eng_ts_buffer);
MR_US_SPIN_LOCK(&(buffer->MR_tsbuffer_lock));
- if (!enough_room_for_event(buffer, MR_TS_EVENT_SPARKING)) {
+ if (!enough_room_for_event(buffer, MR_TS_MER_EVENT_SPARKING)) {
flush_event_buffer(buffer);
open_block(buffer, MR_ENGINE(MR_eng_id));
} else if (!block_is_open(buffer)) {
open_block(buffer, MR_ENGINE(MR_eng_id));
}
- put_event_header(buffer, MR_TS_EVENT_SPARKING,
+ put_event_header(buffer, MR_TS_MER_EVENT_SPARKING,
get_current_time_nanosecs());
put_par_conj_dynamic_id(buffer, dynamic_conj_id);
put_spark_id(buffer, spark_id);
@@ -1310,6 +1490,173 @@ MR_threadscope_post_log_msg(const char *
MR_US_UNLOCK(&(buffer->MR_tsbuffer_lock));
}
+void
+MR_threadscope_post_create_engset(MR_EngSetId id, MR_EngSetType type)
+{
+ struct MR_threadscope_event_buffer *buffer = &global_buffer;
+
+ if (!enough_room_for_event(buffer, MR_TS_EVENT_CAPSET_CREATE)) {
+ flush_event_buffer(buffer);
+ }
+
+ put_event_header(buffer, MR_TS_EVENT_CAPSET_CREATE, 0);
+ put_engset_id(buffer, id);
+ put_engset_type(buffer, type);
+}
+
+void
+MR_threadscope_post_destroy_engset(MR_EngSetId id)
+{
+ struct MR_threadscope_event_buffer *buffer = &global_buffer;
+
+ if (!enough_room_for_event(buffer, MR_TS_EVENT_CAPSET_DELETE)) {
+ flush_event_buffer(buffer);
+ }
+
+ put_event_header(buffer, MR_TS_EVENT_CAPSET_DELETE,
+ get_current_time_nanosecs());
+ put_engset_id(buffer, id);
+}
+
+void
+MR_threadscope_post_engset_add(struct MR_threadscope_event_buffer *buffer,
+ MR_EngSetId id, MR_EngineId eng)
+{
+ MR_US_SPIN_LOCK(&(buffer->MR_tsbuffer_lock));
+ maybe_close_block(buffer);
+ if (!enough_room_for_event(buffer, MR_TS_EVENT_CAPSET_ASSIGN_CAP)) {
+ flush_event_buffer(buffer);
+ }
+
+ /*
+ ** When this event occurs the engine hasn't been setup yet. Even though we
+ ** use the engine's buffer we cannot use get_current_time_nanosecs()
+ */
+ put_event_header(buffer, MR_TS_EVENT_CAPSET_ASSIGN_CAP, 0);
+ put_engset_id(buffer, id);
+ put_engine_id(buffer, eng);
+
+ MR_US_UNLOCK(&(buffer->MR_tsbuffer_lock));
+}
+
+void
+MR_threadscope_post_engset_remove(MR_EngSetId id, MR_EngineId eng)
+{
+ struct MR_threadscope_event_buffer *buffer = MR_ENGINE(MR_eng_ts_buffer);
+
+ MR_US_SPIN_LOCK(&(buffer->MR_tsbuffer_lock));
+ maybe_close_block(buffer);
+ if (!enough_room_for_event(buffer, MR_TS_EVENT_CAPSET_REMOVE_CAP)) {
+ flush_event_buffer(buffer);
+ }
+
+ put_event_header(buffer, MR_TS_EVENT_CAPSET_REMOVE_CAP,
+ get_current_time_nanosecs());
+ put_engset_id(buffer, id);
+ put_engine_id(buffer, eng);
+
+ MR_US_UNLOCK(&(buffer->MR_tsbuffer_lock));
+}
+
+void
+MR_threadscope_post_runtime_identifier(MR_EngSetId engset_id,
+ const char *identifier)
+{
+ struct MR_threadscope_event_buffer *buffer = &global_buffer;
+ unsigned len;
+
+ len = strlen(identifier);
+
+ if (!enough_room_for_variable_size_event(buffer, len + SZ_CAPSET_ID)) {
+ flush_event_buffer(buffer);
+ }
+
+ put_event_header(buffer, MR_TS_EVENT_RTS_IDENTIFIER, 0);
+ put_be_int16(buffer, len + SZ_CAPSET_ID);
+ put_engset_id(buffer, engset_id);
+ put_raw_string(buffer, identifier, len);
+}
+
+void
+MR_threadscope_post_new_future(MR_Future *future_id)
+{
+ struct MR_threadscope_event_buffer *buffer = MR_ENGINE(MR_eng_ts_buffer);
+
+ MR_US_SPIN_LOCK(&(buffer->MR_tsbuffer_lock));
+ if (!enough_room_for_event(buffer, MR_TS_MER_EVENT_FUT_CREATE)) {
+ flush_event_buffer(buffer);
+ open_block(buffer, MR_ENGINE(MR_eng_id));
+ } else if (!block_is_open(buffer)) {
+ open_block(buffer, MR_ENGINE(MR_eng_id));
+ }
+
+ put_event_header(buffer, MR_TS_MER_EVENT_FUT_CREATE,
+ get_current_time_nanosecs());
+ put_future_id(buffer, future_id);
+
+ MR_US_UNLOCK(&(buffer->MR_tsbuffer_lock));
+}
+
+void
+MR_threadscope_post_wait_future_nosuspend(MR_Future* future_id)
+{
+ struct MR_threadscope_event_buffer *buffer = MR_ENGINE(MR_eng_ts_buffer);
+
+ MR_US_SPIN_LOCK(&(buffer->MR_tsbuffer_lock));
+ if (!enough_room_for_event(buffer, MR_TS_MER_EVENT_FUT_WAIT_NOSUSPEND)) {
+ flush_event_buffer(buffer);
+ open_block(buffer, MR_ENGINE(MR_eng_id));
+ } else if (!block_is_open(buffer)) {
+ open_block(buffer, MR_ENGINE(MR_eng_id));
+ }
+
+ put_event_header(buffer, MR_TS_MER_EVENT_FUT_WAIT_NOSUSPEND,
+ get_current_time_nanosecs());
+ put_future_id(buffer, future_id);
+
+ MR_US_UNLOCK(&(buffer->MR_tsbuffer_lock));
+}
+
+void
+MR_threadscope_post_wait_future_suspended(MR_Future* future_id)
+{
+ struct MR_threadscope_event_buffer *buffer = MR_ENGINE(MR_eng_ts_buffer);
+
+ MR_US_SPIN_LOCK(&(buffer->MR_tsbuffer_lock));
+ if (!enough_room_for_event(buffer, MR_TS_MER_EVENT_FUT_WAIT_SUSPENDED)) {
+ flush_event_buffer(buffer);
+ open_block(buffer, MR_ENGINE(MR_eng_id));
+ } else if (!block_is_open(buffer)) {
+ open_block(buffer, MR_ENGINE(MR_eng_id));
+ }
+
+ put_event_header(buffer, MR_TS_MER_EVENT_FUT_WAIT_SUSPENDED,
+ get_current_time_nanosecs());
+ put_future_id(buffer, future_id);
+
+ MR_US_UNLOCK(&(buffer->MR_tsbuffer_lock));
+}
+
+void
+MR_threadscope_post_signal_future(MR_Future* future_id)
+{
+ struct MR_threadscope_event_buffer *buffer = MR_ENGINE(MR_eng_ts_buffer);
+
+ MR_US_SPIN_LOCK(&(buffer->MR_tsbuffer_lock));
+ if (!enough_room_for_event(buffer, MR_TS_MER_EVENT_FUT_SIGNAL)) {
+ flush_event_buffer(buffer);
+ open_block(buffer, MR_ENGINE(MR_eng_id));
+ } else if (!block_is_open(buffer)) {
+ open_block(buffer, MR_ENGINE(MR_eng_id));
+ }
+
+ put_event_header(buffer, MR_TS_MER_EVENT_FUT_SIGNAL,
+ get_current_time_nanosecs());
+ put_future_id(buffer, future_id);
+
+ MR_US_UNLOCK(&(buffer->MR_tsbuffer_lock));
+}
+
/***************************************************************************/
static struct MR_threadscope_event_buffer*
Index: runtime/mercury_threadscope.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_threadscope.h,v
retrieving revision 1.6
diff -u -p -b -r1.6 mercury_threadscope.h
--- runtime/mercury_threadscope.h 25 Mar 2011 03:13:42 -0000 1.6
+++ runtime/mercury_threadscope.h 2 Apr 2011 05:34:25 -0000
@@ -41,6 +41,9 @@ typedef MR_uint_least16_t MR_ContextSt
typedef MR_Integer MR_ContextId;
typedef MR_uint_least32_t MR_TS_StringId;
typedef MR_uint_least32_t MR_SparkId;
+typedef MR_uint_least32_t MR_EngSetId;
+typedef MR_uint_least16_t MR_EngSetType;
+typedef MR_uint_least32_t MR_TS_Pid;
typedef struct MR_Threadscope_String {
const char* MR_tsstring_string;
@@ -179,6 +182,30 @@ extern void
MR_threadscope_post_stop_par_conjunct(MR_Word* dynamic_id);
/*
+** Post this message when a future is created, this establishes the conjuction
+** id to future id mapping. The conjunction id is inferred by context.
+*/
+extern void
+MR_threadscope_post_new_future(MR_Future* future_id);
+
+/*
+** Post either of these messages when waiting on a future. THe first if the
+** context had to be suspended because the future was not available, and the
+** second when the context did not need to be suspended.
+*/
+extern void
+MR_threadscope_post_wait_future_nosuspend(MR_Future* future_id);
+
+extern void
+MR_threadscope_post_wait_future_suspended(MR_Future* future_id);
+
+/*
+** Post this event when signaling the production of a future.
+*/
+extern void
+MR_threadscope_post_signal_future(MR_Future* future_id);
+
+/*
** Register all the strings in an array and save their IDs in the array.
*/
extern void
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 489 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20110402/6d600b9c/attachment.sig>
More information about the reviews
mailing list