Commit d30f0bfb authored by Brice Videau's avatar Brice Videau
Browse files

Merge branch 'profiling' into 'master'

Profiling

See merge request !1
parents dddcf447 aa69d6f2
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
MEMBER_SEPARATOR = "__"
module LTTng
class TracepointField
FIELDS = {
:ctf_array => [ :type, :name, :expression, :length ],
:ctf_array_hex => [ :type, :name, :expression, :length ],
:ctf_array_network => [:type, :name, :expression, :length ],
:ctf_array_network_hex => [:type, :name, :expression, :length ],
:ctf_array_text => [:type, :name, :expression, :length ],
:ctf_enum => [:provider_name, :enum_name, :type, :name, :expression ],
:ctf_float => [:type, :name, :expression ],
:ctf_integer => [:type, :name, :expression ],
:ctf_integer_hex => [:type, :name, :expression ],
:ctf_integer_network => [:type, :name, :expression ],
:ctf_integer_network_hex => [:type, :name, :expression ],
:ctf_sequence => [:type, :name, :expression, :length_type, :length ],
:ctf_sequence_hex => [:type, :name, :expression, :length_type, :length ],
:ctf_sequence_network => [:type, :name, :expression, :length_type, :length ],
:ctf_sequence_network_hex => [:type, :name, :expression, :length_type, :length ],
:ctf_sequence_text => [:type, :name, :expression, :length_type, :length ],
:ctf_string => [:name, :expression ]
}
attr_accessor :macro
attr_accessor :name
attr_accessor :expression
attr_accessor :type
attr_accessor :provider_name
attr_accessor :enum_name
attr_accessor :length
attr_accessor :length_type
attr_accessor :cast
def initialize(*args)
if args.length > 0
desc = FIELDS[args[0].to_sym]
raise "Invalid field #{args[0]}!" unless desc
@macro = args[0].to_sym
raise "Invalid field parameters #{args[1..-1]}!" unless args[1..-1].length == desc.length
desc.zip(args[1..-1]).each { |sym, v|
self.instance_variable_set(:"@#{sym}", v)
}
m = @expression.match(/\((.*?)\)(.*)/)
if m
@cast = m[1]
@expression = m[2]
end
end
end
def call_string
str = "#{@macro}("
str << [ @provider_name, @enum_name, @type, @name, @cast ? "(#{@cast})(#{@expression})" : @expression, @length_type, @length ].compact.join(", ")
str << ")"
end
def name=(n)
@name = n.gsub("->", MEMBER_SEPARATOR)
end
end
def self.print_enum(namespace, en)
puts <<EOF
TRACEPOINT_ENUM(
#{namespace},
#{en["name"]},
TP_ENUM_VALUES(
EOF
print " "
puts en["values"].collect { |(f, sy, *args)|
"#{f}(#{sy.to_s.inspect}, #{args.join(", ")})"
}.join("\n ")
puts <<EOF
)
)
EOF
end
def self.print_tracepoint(namespace, tp, dir = nil)
puts <<EOF
TRACEPOINT_EVENT(
#{namespace},
#{tp["name"]}#{dir ? "_#{dir}" : ""},
TP_ARGS(
EOF
print " "
args = tp["args"]
if args.empty?
puts "void"
else
puts args.collect { |a| a.join(", ") }.join(",\n ")
end
puts <<EOF
),
TP_FIELDS(
EOF
dir = "fields" unless dir
if tp[dir]
print " "
puts tp[dir].collect { |(f, *args)| "#{f}(#{args.join(", ")})" }.join("\n ")
end
puts <<EOF
)
)
EOF
end
end
......@@ -4,6 +4,6 @@
*.c
*.h
*.yaml
ze_tracepoints.tp
zex_tracepoints.tp
zet_tracepoints.tp
*.tp
babeltrace_ze_lib.rb
ze_library.rb
......@@ -7,6 +7,16 @@ ZE_OBJS = $(ZE_PROBES:=.o)
ZE_INCL = $(ZE_PROBES:=.h)
ZE_SRC = $(ZE_PROBES:=.c)
ZE_STATIC_PROBES = ze_profiling
ZE_STATIC_TP = $(ZE_STATIC_PROBES:=.tp)
ZE_STATIC_OBJS = $(ZE_STATIC_PROBES:=.o)
ZE_STATIC_INCL = $(ZE_STATIC_PROBES:=.h)
ZE_STATIC_SRC = $(ZE_STATIC_PROBES:=.c)
ZE_EXTRACT = extract_base.rb modified_include
ZE_EXTRACTED = ze_api.yaml zet_api.yaml
ZE_MODEL = ze_model.rb yaml_ast.rb ze_meta_parameters.yaml zet_meta_parameters.yaml $(ZE_EXTRACTED)
.SECONDARY: $(ZE_TP)
all: tracer_ze.so ze_library.rb babeltrace_ze_lib.rb
......@@ -20,33 +30,40 @@ modified_include: include headers.patch
../utils/lttng/tracepoint_gen.h: ../utils/tracepoint_gen.rb
ruby ../utils/tracepoint_gen.rb 25 > ../utils/lttng/tracepoint_gen.h
ze_api.yaml: $(shell find include/core -type f) extract_base.rb extract_ze.rb modified_include
ze_api.yaml: $(shell find include/core -type f) $(ZE_EXTRACT) extract_ze.rb
ruby extract_ze.rb
zet_api.yaml: $(shell find include/core include/tools -type f) extract_base.rb extract_zet.rb modified_include
zet_api.yaml: $(shell find include/core include/tools -type f) $(ZE_EXTRACT) extract_zet.rb
ruby extract_zet.rb
%.tp: %.rb ze_api.yaml zet_api.yaml yaml_ast.rb ze_model.rb gen_probe_base.rb ze_meta_parameters.yaml zet_meta_parameters.yaml
ze_profiling.tp: gen_ze_custom_probes.rb ../utils/LTTng.rb $(ZE_MODEL)
ruby gen_ze_custom_probes.rb lttng_ust_ze_profiling > $@
%.tp: %.rb $(ZE_MODEL) gen_probe_base.rb
ruby $*.rb > $@
%.c %.h %.o: %.tp ../utils/lttng/tracepoint_gen.h
CFLAGS="$(LTTNG_FLAGS)" lttng-gen-tp $<
tracer_ze.c: gen_ze.rb tracer_ze_helpers.include.c ze_api.yaml zet_api.yaml yaml_ast.rb ze_model.rb ze_meta_parameters.yaml zet_meta_parameters.yaml
tracer_ze.c: gen_ze.rb tracer_ze_helpers.include.c $(ZE_MODEL)
ruby $< > $@
tracer_ze.so: ../utils/lttng/tracepoint_gen.h tracer_ze.c $(ZE_OBJS) $(ZE_INCL)
gcc -g -O3 -Wall -Wextra -Werror -I./include/core -I./include/tools -I./ -I../utils/ -o tracer_ze.so -shared -fPIC tracer_ze.c $(ZE_OBJS) -llttng-ust -ldl -lffi
tracer_ze.so: ../utils/lttng/tracepoint_gen.h tracer_ze.c $(ZE_OBJS) $(ZE_INCL) $(ZE_STATIC_OBJS) $(ZE_STATIC_INCL)
gcc -g -O3 -Wall -Wextra -Werror -I./include/core -I./include/tools -I./ -I../utils/ -o tracer_ze.so -shared -fPIC tracer_ze.c $(ZE_OBJS) $(ZE_STATIC_OBJS) -llttng-ust -ldl -lffi
ze_library.rb: gen_ze_library.rb gen_ze_library_base.rb gen_probe_base.rb ze_model.rb ze_api.yaml zet_api.yaml
ze_library.rb: gen_ze_library.rb gen_ze_library_base.rb gen_probe_base.rb $(ZE_MODEL)
ruby $< > $@
babeltrace_ze_lib.rb: gen_babeltrace_ze_lib.rb gen_ze_library_base.rb gen_probe_base.rb ze_model.rb ze_api.yaml zet_api.yaml ze_meta_parameters.yaml zet_meta_parameters.yaml
babeltrace_ze_lib.rb: gen_babeltrace_ze_lib.rb gen_ze_library_base.rb gen_probe_base.rb $(ZE_MODEL)
ruby $< > $@
# objcopy --prefix-symbols= on ze_api.a content should allow a wrapper creation
clean:
rm -f ze_api.yaml zet_api.yaml $(ZE_TP) $(ZE_OBJS) $(ZE_INCL) $(ZE_SRC) tracer_ze.c tracer_ze.so ze_library.rb babeltrace_ze_lib.rb
rm -f \
ze_api.yaml zet_api.yaml\
$(ZE_TP) $(ZE_OBJS) $(ZE_INCL) $(ZE_SRC)\
$(ZE_STATIC_TP) $(ZE_STATIC_OBJS) $(ZE_STATIC_INCL) $(ZE_STATIC_SRC)\
tracer_ze.c tracer_ze.so ze_library.rb babeltrace_ze_lib.rb
rm -fr modified_include
$(MAKE) -C ../utils clean
......@@ -79,7 +79,7 @@ EOF
}
end
else
fields.push 's << "ze_result: #{ZE::ZEResult.from_native(defi["ze_result"], nil)}"'
fields.push "s << \"#{RESULT_NAME}: \#{ZE::ZEResult.from_native(defi[\"#{RESULT_NAME}\"], nil)}\""
fields += c.meta_parameters.select { |m| m.kind_of?(Out) }.collect { |m|
meta_parameter_lambda.call(m, :stop)
}
......@@ -111,3 +111,45 @@ $zet_commands.each { |c|
gen_event_lambda.call(provider, c, :start)
gen_event_lambda.call(provider, c, :stop)
}
extra_events = YAML::load_file("ze_events.yaml")
extra_events.each { |provider, h|
h["events"].each { |e|
puts <<EOF
$event_lambdas["#{provider}:#{e["name"]}"] = lambda { |defi|
s = "{ "
EOF
fields = e["fields"].collect { |f|
field = LTTng::TracepointField::new(*f)
case field.macro
when :ctf_integer_hex
"s << \"#{field.name}: \#{\"0x%016x\" % defi[\"#{field.name}\"]}\""
when :ctf_integer
arg = e["args"].find { |type, name|
name == field.expression
}
if arg
if $all_enum_names.include?(arg[0])
"s << \"#{field.name}: \#{ZE::#{to_class_name(arg[0])}.from_native(defi[\"#{field.name}\"], nil)}\""
elsif $all_bitfield_names.include?(arg[0])
"s << \"#{field.name}: [ \#{ZE::#{to_class_name(arg[0])}.from_native(defi[\"#{field.name}\"], nil)} ]\""
else
"s << \"#{field.name}: \#{defi[\"#{field.name}\"]}\""
end
else
"s << \"#{field.name}: \#{defi[\"#{field.name}\"]}\""
end
else
raise "Unsupported LTTng macro #{field.macro}!"
end
}
puts <<EOF
#{fields.join("\n s << ', '\n ")}
EOF
puts <<EOF
s << " }"
}
EOF
}
}
RESULT_NAME = "zeResult"
$tracepoint_lambda = lambda { |provider, c, dir|
puts <<EOF
TRACEPOINT_EVENT(
......@@ -14,7 +16,7 @@ EOF
"#{p.type}, #{p.name}"
} unless c.parameters.nil?
if c.has_return_type? && dir == :stop
params.push("#{c.type}, ze_result")
params.push("#{c.type}, #{RESULT_NAME}")
end
params += c.tracepoint_parameters.collect { |p|
"#{p.type}, #{p.name}"
......@@ -36,8 +38,8 @@ EOF
elsif dir == :stop
r = c.type.lttng_type
if r
r.name = "ze_result"
r.expression = "ze_result"
r.name = RESULT_NAME
r.expression = RESULT_NAME
fields.push(r.call_string)
end
c.meta_parameters.collect(&:lttng_out_type).flatten.compact.each { |r|
......
......@@ -19,9 +19,11 @@ puts <<EOF
#include <pthread.h>
#include <sys/mman.h>
#include <ffi.h>
#include "uthash.h"
#include "ze_tracepoints.h"
#include "zet_tracepoints.h"
#include "ze_profiling.h"
EOF
......
require_relative 'ze_model'
namespace = ARGV[0]
raise "No namespace provided!" unless namespace
h = YAML::load_file("ze_events.yaml")[namespace]
raise "Invalid namespace!" unless h
puts <<EOF
#define CL_TARGET_OPENCL_VERSION 220
#define ZE_ENABLE_OCL_INTEROP 1
#include <ze_api.h>
#include <ze_ddi.h>
EOF
enums = h["enums"]
if enums
enums.each { |e|
LTTng.print_enum(namespace, e)
}
end
h["events"].each { |e|
LTTng.print_tracepoint(namespace, e)
}
enum _ze_obj_type {
UNKNOWN = 0,
DRIVER,
DEVICE,
COMMAND_LIST
};
struct _ze_device_obj_data {
ze_driver_handle_t driver;
ze_device_properties_t properties;
};
struct _ze_command_list_obj_data {
ze_device_handle_t device;
ze_driver_handle_t driver;
};
struct _ze_obj_h {
void *ptr;
UT_hash_handle hh;
enum _ze_obj_type type;
void *obj_data;
void (*obj_data_free)(void *obj_data);
};
struct _ze_obj_h *_ze_objs = NULL;
pthread_mutex_t _ze_objs_mutex = PTHREAD_MUTEX_INITIALIZER;
static inline void _delete_ze_obj(struct _ze_obj_h *o_h) {
HASH_DEL(_ze_objs, o_h);
if (o_h->obj_data && o_h->obj_data_free) {
o_h->obj_data_free(o_h->obj_data);
}
free(o_h);
}
#define FIND_ZE_OBJ(key, val) { \
pthread_mutex_lock(&_ze_objs_mutex); \
HASH_FIND_PTR(_ze_objs, key, val); \
pthread_mutex_unlock(&_ze_objs_mutex); \
}
#define ADD_ZE_OBJ(val) { \
pthread_mutex_lock(&_ze_objs_mutex); \
HASH_ADD_PTR(_ze_objs, ptr, val); \
pthread_mutex_unlock(&_ze_objs_mutex); \
}
#define FIND_AND_DEL_ZE_OBJ(key, val) { \
pthread_mutex_lock(&_ze_objs_mutex); \
HASH_FIND_PTR(_ze_objs, key, val); \
if (val) { \
HASH_DEL(_ze_objs, val); \
} \
pthread_mutex_unlock(&_ze_objs_mutex); \
}
static inline void _register_ze_device(
ze_device_handle_t device,
ze_driver_handle_t driver) {
struct _ze_obj_h *o_h = NULL;
struct _ze_device_obj_data *d_data = NULL;
FIND_ZE_OBJ(&device, o_h);
if (o_h)
return;
intptr_t mem = (intptr_t)calloc(1, sizeof(struct _ze_obj_h) +
sizeof(struct _ze_device_obj_data) );
if (mem == 0)
return;
o_h = (struct _ze_obj_h *)mem;
d_data = (struct _ze_device_obj_data *)(mem + sizeof(struct _ze_obj_h));
o_h->ptr = (void *)device;
o_h->type = DEVICE;
d_data->driver = driver;
o_h->obj_data = (void *)d_data;
d_data->properties.version = ZE_DEVICE_PROPERTIES_VERSION_CURRENT;
ze_result_t res = zeDeviceGetProperties(device, &(d_data->properties));
if (res != ZE_RESULT_SUCCESS) {
free((void *)mem);
return;
}
ADD_ZE_OBJ(o_h);
}
static inline void _register_ze_command_list(
ze_command_list_handle_t command_list,
ze_device_handle_t device) {
struct _ze_obj_h *o_h = NULL;
struct _ze_command_list_obj_data *cl_data = NULL;
ze_driver_handle_t driver;
FIND_ZE_OBJ(&device, o_h);
if (!o_h)
return;
driver = ((struct _ze_device_obj_data *)(o_h->obj_data))->driver;
FIND_ZE_OBJ(&command_list, o_h);
if (o_h)
return;
intptr_t mem = (intptr_t)calloc(1, sizeof(struct _ze_obj_h) +
sizeof(struct _ze_command_list_obj_data) );
if (mem == 0)
return;
o_h = (struct _ze_obj_h *)mem;
cl_data = (struct _ze_command_list_obj_data *)(mem + sizeof(struct _ze_obj_h));
o_h->ptr = (void *)command_list;
o_h->type = COMMAND_LIST;
cl_data->device = device;
cl_data->driver = driver;
o_h->obj_data = (void *)cl_data;
ADD_ZE_OBJ(o_h);
}
static inline void _unregister_ze_command_list(
ze_command_list_handle_t command_list ) {
struct _ze_obj_h *o_h = NULL;
FIND_AND_DEL_ZE_OBJ(&command_list, o_h);
if (!o_h)
return;
free(o_h);
}
struct _ze_event_h {
ze_event_handle_t event;
UT_hash_handle hh;
ze_command_list_handle_t command_list;
ze_event_pool_handle_t event_pool;
};
#define FIND_ZE_EVENT(key, val) { \
pthread_mutex_lock(&_ze_events_mutex); \
HASH_FIND_PTR(_ze_events, key, val); \
pthread_mutex_unlock(&_ze_events_mutex); \
}
#define ADD_ZE_EVENT(val) { \
pthread_mutex_lock(&_ze_events_mutex); \
HASH_ADD_PTR(_ze_events, event, val); \
pthread_mutex_unlock(&_ze_events_mutex); \
}
#define FIND_AND_DEL_ZE_EVENT(key, val) { \
pthread_mutex_lock(&_ze_events_mutex); \
HASH_FIND_PTR(_ze_events, key, val); \
if (val) { \
HASH_DEL(_ze_events, val); \
} \
pthread_mutex_unlock(&_ze_events_mutex); \
}
struct _ze_event_h *_ze_events = NULL;
pthread_mutex_t _ze_events_mutex = PTHREAD_MUTEX_INITIALIZER;
static inline void _register_ze_event(
ze_event_handle_t event,
ze_command_list_handle_t command_list,
ze_event_pool_handle_t event_pool) {
struct _ze_event_h *_ze_event = NULL;
FIND_ZE_EVENT(&event, _ze_event);
if (_ze_event)
return;
_ze_event = (struct _ze_event_h *)calloc(1, sizeof(struct _ze_event_h));
if (!_ze_event)
return;
_ze_event->event = event;
_ze_event->command_list = command_list;
_ze_event->event_pool = event_pool;
ADD_ZE_EVENT(_ze_event);
}
ze_event_handle_t _get_profiling_event(
ze_command_list_handle_t command_list,
ze_event_pool_handle_t *pool_ret) {
struct _ze_obj_h *o_h = NULL;
FIND_ZE_OBJ(&command_list, o_h);
if (!o_h)
return NULL;
ze_driver_handle_t driver =
((struct _ze_command_list_obj_data *)(o_h->obj_data))->driver;
ze_device_handle_t device =
((struct _ze_command_list_obj_data *)(o_h->obj_data))->device;
ze_event_pool_handle_t event_pool = NULL;
ze_event_pool_desc_t desc = {ZE_EVENT_POOL_DESC_VERSION_CURRENT, ZE_EVENT_POOL_FLAG_TIMESTAMP, 1};
ze_result_t res = ZE_EVENT_POOL_CREATE_PTR(driver, &desc, 1, &device, &event_pool);
if (res != ZE_RESULT_SUCCESS)
return NULL;
ze_event_handle_t event;
ze_event_desc_t e_desc = {ZE_EVENT_DESC_VERSION_CURRENT, 0, ZE_EVENT_SCOPE_FLAG_HOST, ZE_EVENT_SCOPE_FLAG_HOST};
res = ZE_EVENT_CREATE_PTR(event_pool, &e_desc, &event);
if (res != ZE_RESULT_SUCCESS) {
ZE_EVENT_POOL_DESTROY_PTR(event_pool);
return NULL;
}
*pool_ret = event_pool;
return event;
}
static void _profile_event_results(ze_event_handle_t event);
static inline void _unregister_ze_event(ze_event_handle_t event) {
struct _ze_event_h *ze_event = NULL;
FIND_AND_DEL_ZE_EVENT(&event, ze_event);
if (!ze_event)
return;
_profile_event_results(event);
free(ze_event);
}
static void _profile_event_results(ze_event_handle_t event) {
ze_result_t status;
ze_result_t global_start_status;
uint64_t global_start;
ze_result_t global_end_status;
uint64_t global_end;
ze_result_t context_start_status;
uint64_t context_start;
ze_result_t context_end_status;
uint64_t context_end;
if (tracepoint_enabled(lttng_ust_ze_profiling, event_profiling_results)) {
status = ZE_EVENT_QUERY_STATUS_PTR(event);
global_start_status = ZE_EVENT_GET_TIMESTAMP_PTR(
event,
ZE_EVENT_TIMESTAMP_GLOBAL_START,
&global_start);
global_end_status = ZE_EVENT_GET_TIMESTAMP_PTR(
event,
ZE_EVENT_TIMESTAMP_GLOBAL_END,
&global_end);
context_start_status = ZE_EVENT_GET_TIMESTAMP_PTR(
event,
ZE_EVENT_TIMESTAMP_CONTEXT_START,
&context_start);
context_end_status = ZE_EVENT_GET_TIMESTAMP_PTR(
event,
ZE_EVENT_TIMESTAMP_CONTEXT_END,
&context_end);
do_tracepoint(lttng_ust_ze_profiling, event_profiling_results,
event, status,
global_start_status, global_start,
global_end_status, global_end,
context_start_status, context_start,
context_end_status, context_end);
}
}
void _event_cleanup() {
struct _ze_event_h *ze_event = NULL;
struct _ze_event_h *tmp = NULL;
HASH_ITER(hh, _ze_events, ze_event, tmp) {
HASH_DEL(_ze_events, ze_event);
if (ze_event->event) {
_profile_event_results(ze_event->event);
ZE_EVENT_DESTROY_PTR(ze_event->event);
}
if (ze_event->event_pool) {
ZE_EVENT_POOL_DESTROY_PTR(ze_event->event_pool);
}
free(ze_event);
}
}
static pthread_once_t _init = PTHREAD_ONCE_INIT;