[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