[PATCH v2 08/18] mt trace: track GL context create/destroy calls

José Fonseca jose.r.fonseca at gmail.com
Mon May 21 01:44:51 PDT 2012


On Tue, May 15, 2012 at 3:11 PM, Imre Deak <imre.deak at intel.com> wrote:
> This is needed for muti-threaded tracing to work properly.
>
> Tracing multi-threaded GL apps requires that we track the lifetime of
> the GL context objects and store thread specific state like the currently
> active GL context on thread-local memory area.
>
> Signed-off-by: Imre Deak <imre.deak at intel.com>
> ---
>  wrappers/egltrace.py       |    5 +++
>  wrappers/gltrace.hpp       |   17 +++++++++-
>  wrappers/gltrace_state.cpp |   71 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 91 insertions(+), 2 deletions(-)
>  create mode 100644 wrappers/gltrace_state.cpp
>
> diff --git a/wrappers/egltrace.py b/wrappers/egltrace.py
> index 4858e2f..b958a0c 100644
> --- a/wrappers/egltrace.py
> +++ b/wrappers/egltrace.py
> @@ -52,6 +52,9 @@ class EglTracer(GlTracer):
>     def traceFunctionImplBody(self, function):
>         GlTracer.traceFunctionImplBody(self, function)
>
> +        if function.name == 'eglCreateContext':
> +            print '    gltrace::createContext((unsigned long)_result);'
> +
>         if function.name == 'eglMakeCurrent':
>             print '    // update the profile'
>             print '    if (ctx != EGL_NO_CONTEXT) {'
> @@ -67,6 +70,8 @@ class EglTracer(GlTracer):
>             print '            tr->profile = gltrace::PROFILE_ES2;'
>             print '    }'
>
> +        if function.name == 'eglDestroyContext':
> +            print '    gltrace::destroyContext((unsigned long)_result);'
>
>  if __name__ == '__main__':
>     print '#include <stdlib.h>'
> diff --git a/wrappers/gltrace.hpp b/wrappers/gltrace.hpp
> index cd602cb..627b2f7 100644
> --- a/wrappers/gltrace.hpp
> +++ b/wrappers/gltrace.hpp
> @@ -39,13 +39,26 @@ enum Profile {
>     PROFILE_ES2,
>  };
>
> -struct Context {
> +class Context {
> +public:
>     enum Profile profile;
>     bool user_arrays;
>     bool user_arrays_arb;
>     bool user_arrays_nv;
> +
> +    Context(void) : profile(PROFILE_COMPAT), user_arrays(false),
> +                    user_arrays_arb(false), user_arrays_nv(false) { }
>  };
> -
> +
> +void
> +createContext(unsigned long context_id);
> +
> +void
> +destroyContext(unsigned long context_id);
> +
> +void
> +setContext(unsigned long context_id);
> +
>  Context *
>  getContext(void);
>
> diff --git a/wrappers/gltrace_state.cpp b/wrappers/gltrace_state.cpp
> new file mode 100644
> index 0000000..cce4e14
> --- /dev/null
> +++ b/wrappers/gltrace_state.cpp
> @@ -0,0 +1,71 @@
> +#include <gltrace.hpp>
> +#include <os_thread.hpp>
> +#include <assert.h>
> +
> +namespace gltrace {
> +
> +static std::map<unsigned long, Context *> context_map;

Imre,

Thanks for these changes. I've already applied some of them.

Please protect access to context_map with a mutex, to prevent race
conditions which could  cause segfaults if one thread is writing while
another is reading.

Jose

> +
> +class ThreadState {
> +public:
> +       Context *current_context;
> +       Context dummy_context;
> +
> +       ThreadState(void) : current_context(NULL) { }
> +};
> +
> +static os::thread_specific_ptr<struct ThreadState> thread_state;
> +
> +static ThreadState *get_ts(void)
> +{
> +       struct ThreadState *ts = thread_state.get();
> +
> +       if (!ts) {
> +               ts = new ThreadState;
> +               thread_state.reset(ts);
> +       }
> +
> +       return ts;
> +}
> +
> +void createContext(unsigned long context_id)
> +{
> +       assert(context_map.find(context_id) == context_map.end());
> +       context_map[context_id] = new Context();
> +}
> +
> +void destroyContext(unsigned long context_id)
> +{
> +       struct ThreadState *ts = get_ts();
> +       Context *ctx;
> +
> +       ctx = context_map[context_id];
> +       if (ctx == ts->current_context)
> +               ts->current_context = NULL;
> +
> +       context_map.erase(context_id);
> +       delete ctx;
> +}
> +
> +void setContext(unsigned long context_id)
> +{
> +       struct ThreadState *ts = get_ts();
> +
> +       ts->current_context = context_map[context_id];
> +}
> +
> +Context *getContext(void)
> +{
> +       struct ThreadState *ts = get_ts();
> +       Context *ctx = ts->current_context;
> +
> +       /*
> +        * We are called from some gl* function at which point the behaviour
> +        * is undefined if there is no active context. So in this case return
> +        * a dummy context so that at least the apitrace internal book-keeping
> +        * - which is context dependent - won't crash.
> +        */
> +       return ctx ? ctx : &ts->dummy_context;
> +}
> +
> +}
> --
> 1.7.5.4
>


More information about the apitrace mailing list