1# -*- coding: utf-8 -*-
2
3"""
4Simple built-in backend.
5"""
6
7__author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
8__copyright__  = "Copyright 2012-2017, Lluís Vilanova <vilanova@ac.upc.edu>"
9__license__    = "GPL version 2 or (at your option) any later version"
10
11__maintainer__ = "Stefan Hajnoczi"
12__email__      = "stefanha@redhat.com"
13
14
15from tracetool import out
16
17
18PUBLIC = True
19
20
21def is_string(arg):
22    strtype = ('const char*', 'char*', 'const char *', 'char *')
23    arg_strip = arg.lstrip()
24    if arg_strip.startswith(strtype) and arg_strip.count('*') == 1:
25        return True
26    else:
27        return False
28
29
30def generate_h_begin(events, group):
31    for event in events:
32        out('void _simple_%(api)s(%(args)s);',
33            api=event.api(),
34            args=event.args)
35    out('')
36
37
38def generate_h(event, group):
39    out('    _simple_%(api)s(%(args)s);',
40        api=event.api(),
41        args=", ".join(event.args.names()))
42
43
44def generate_h_backend_dstate(event, group):
45    out('    trace_event_get_state_dynamic_by_id(%(event_id)s) || \\',
46        event_id="TRACE_" + event.name.upper())
47
48
49def generate_c_begin(events, group):
50    out('#include "qemu/osdep.h"',
51        '#include "trace/control.h"',
52        '#include "trace/simple.h"',
53        '')
54
55
56def generate_c(event, group):
57    out('void _simple_%(api)s(%(args)s)',
58        '{',
59        '    TraceBufferRecord rec;',
60        api=event.api(),
61        args=event.args)
62    sizes = []
63    for type_, name in event.args:
64        if is_string(type_):
65            out('    size_t arg%(name)s_len = %(name)s ? MIN(strlen(%(name)s), MAX_TRACE_STRLEN) : 0;',
66                name=name)
67            strsizeinfo = "4 + arg%s_len" % name
68            sizes.append(strsizeinfo)
69        else:
70            sizes.append("8")
71    sizestr = " + ".join(sizes)
72    if len(event.args) == 0:
73        sizestr = '0'
74
75    event_id = 'TRACE_' + event.name.upper()
76    if "vcpu" in event.properties:
77        # already checked on the generic format code
78        cond = "true"
79    else:
80        cond = "trace_event_get_state(%s)" % event_id
81
82    out('',
83        '    if (!%(cond)s) {',
84        '        return;',
85        '    }',
86        '',
87        '    if (trace_record_start(&rec, %(event_obj)s.id, %(size_str)s)) {',
88        '        return; /* Trace Buffer Full, Event Dropped ! */',
89        '    }',
90        cond=cond,
91        event_obj=event.api(event.QEMU_EVENT),
92        size_str=sizestr)
93
94    if len(event.args) > 0:
95        for type_, name in event.args:
96            # string
97            if is_string(type_):
98                out('    trace_record_write_str(&rec, %(name)s, arg%(name)s_len);',
99                    name=name)
100            # pointer var (not string)
101            elif type_.endswith('*'):
102                out('    trace_record_write_u64(&rec, (uintptr_t)(uint64_t *)%(name)s);',
103                    name=name)
104            # primitive data type
105            else:
106                out('    trace_record_write_u64(&rec, (uint64_t)%(name)s);',
107                   name=name)
108
109    out('    trace_record_finish(&rec);',
110        '}',
111        '')
112