Testing xbmc pvr; libGL threading issues...
Juergen Lock
nox at jelal.kn-bremen.de
Fri Oct 14 21:56:56 UTC 2011
Hi!
I had been playing with opdenkamp's xbmc pvr branch and pipelka's
xvdr xbmc addon and vdr plugin for a little while now, and finally
have something that more or less runs. One issue that took me a
while to figure out were crashes in libGL when switching live
channels:
(gdb) bt
#0 0x00000008041abca7 in glIsTexture () from /usr/local/lib/libGL.so.1
#1 0x0000000000b2a995 in CLinuxRendererGL::DeleteYV12Texture (
this=0x8340b8800, index=0) at LinuxRendererGL.cpp:1690
#2 0x0000000000b2eae2 in CLinuxRendererGL::UnInit (this=0x8340b8800)
at LinuxRendererGL.cpp:1059
#3 0x0000000000b2ed9e in CLinuxRendererGL::PreInit (this=0x8340b8800)
at LinuxRendererGL.cpp:719
#4 0x0000000000b29049 in CXBMCRenderManager::PreInit (this=0x1546920)
at RenderManager.cpp:324
#5 0x0000000000b8bf4f in CDVDPlayerVideo::OpenStream (this=0x835400590,
hint=@0x7ffffdfcee20) at DVDPlayerVideo.cpp:183
#6 0x0000000000b6d88e in CDVDPlayer::OpenVideoStream (this=0x835400000,
iStream=0, source=256) at DVDPlayer.cpp:2891
#7 0x0000000000b79734 in CDVDPlayer::Process (this=0x835400000)
at DVDPlayer.cpp:1207
#8 0x0000000000f4a74d in CThread::staticThread (data=0x835400010)
at Thread.cpp:177
turns out libGL keeps thread-local pointers and xbmc called into
libGL (glIsTexture()) from (apparently) a new thread where then
_x86_64_get_dispatch in:
work/Mesa-7.6.1/src/mesa/x86-64/glapi_x86-64.S
returned NULL and thus the glIsTexture wrapper in the same .S
got a segfault referencing that NULL pointer here:
[...]
.p2align 4,,15
.globl GL_PREFIX(IsTexture)
.type GL_PREFIX(IsTexture), @function
GL_PREFIX(IsTexture):
#if defined(GLX_USE_TLS)
call _x86_64_get_dispatch at PLT
movq 2640(%rax), %r11
jmp *%r11
#elif defined(PTHREADS)
pushq %rdi
call _x86_64_get_dispatch at PLT
popq %rdi
movq 2640(%rax), %r11
^^^^^^^^^^^^^^^^^^^^^^^^ segfault
jmp *%r11
#else
[...]
_x86_64_get_dispatch uses pthread_getspecific() and looks like this:
[...]
#elif defined(PTHREADS)
.extern _glapi_Dispatch
.extern _gl_DispatchTSD
.extern pthread_getspecific
.p2align 4,,15
_x86_64_get_dispatch:
movq _gl_DispatchTSD at GOTPCREL(%rip), %rax
movl (%rax), %edi
jmp pthread_getspecific at PLT
#elif defined(THREADS)
[...]
and some documentation about these thread-local pointers is here:
work/Mesa-7.6.1/docs/dispatch.html
After some googling I stumbled across this debian ticket that has a patch:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=536106
so I changed the libGL port's files/patch-src__mesa__x86-64__glapi_x86-64.S
into this:
--------snip------
--- ./src/mesa/x86-64/glapi_x86-64.S.orig 2009-03-13 04:28:49.000000000 +0100
+++ ./src/mesa/x86-64/glapi_x86-64.S 2011-01-28 18:12:18.000000000 +0100
@@ -73,7 +73,12 @@ _x86_64_get_dispatch:
.p2align 4,,15
_x86_64_get_dispatch:
- movq _gl_DispatchTSD(%rip), %rdi
+ movq _glapi_Dispatch(%rip), %rax
+ testq %rax,%rax
+ je 1f
+ ret
+1: movq _gl_DispatchTSD at GOTPCREL(%rip), %rax
+ movl (%rax), %edi
jmp pthread_getspecific at PLT
#elif defined(THREADS)
--------snip------
That fixed these crashes but now I got other crashes that seem to be
related to messages like:
Recursive call into r300FlushCmdBufLocked!
(this is using the xorg radeon drivers, the nvidia libGL blob on
the other box crashed in glIsTexture() too but obviously I cannot
easily debug that) - so I looked for another workaround. What I
finally ended up doing was this patch:
(files/patch-xbmc-cores-VideoRenderers-LinuxRendererGL.cpp)
--- xbmc/cores/VideoRenderers/LinuxRendererGL.cpp.orig
+++ xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
@@ -159,6 +159,10 @@ CLinuxRendererGL::CLinuxRendererGL()
m_rgbPbo = 0;
m_dllSwScale = new DllSwScale;
+
+#ifdef __FreeBSD__
+ m_tid = NULL;
+#endif
}
CLinuxRendererGL::~CLinuxRendererGL()
@@ -247,6 +251,9 @@ bool CLinuxRendererGL::ValidateRenderTar
(this->*m_textureCreate)(i);
m_bValidated = true;
+#ifdef __FreeBSD__
+ m_tid = pthread_self();
+#endif
return true;
}
return false;
@@ -716,6 +723,9 @@ unsigned int CLinuxRendererGL::PreInit()
CSingleLock lock(g_graphicsContext);
m_bConfigured = false;
m_bValidated = false;
+#ifdef __FreeBSD__ // XXX Will this leak? It's needed to avoid crashes... :(
+ if (pthread_self() == m_tid)
+#endif
UnInit();
m_resolution = g_guiSettings.m_LookAndFeelResolution;
if ( m_resolution == RES_WINDOW )
i.e. I only called into CLinuxRendererGL::UnInit() (where the original
crashes happened) if this was the same thread that created the textures
that CLinuxRendererGL::UnInit() tried to delete. I don't know if this
will leak memory, textures, or something else so I'd prefer libGL
to be fixed properly... (And as you might have guessed, this code runs
just fine unpatched on Linux...)
Anyway, here are the preliminary ports:
http://people.freebsd.org/~nox/tmp/xbmcpvr-opdenkamp.patch
(to be applied on top of the current xbmc port)
http://people.freebsd.org/~nox/tmp/vdr-plugin-xvdr.shar
vdr plugin to connect to:
http://people.freebsd.org/~nox/tmp/xbmc-addon-xvdr.shar
xbmc pvr addon to connect to vdr
All are git snapshots so likely contain bugs; xbmc pvr has support
for mythtv (and tvheadend) too so you _might_ be able to test that too,
I only tested with vdr. (The xbmc pvr port at _least_ still needs
the commented out REINPLACE_CMD 's|/usr/local|${LOCALBASE}|g' fixed,
and I also would like to know where the remaining
libXBMC_addon-x86_64-linux.so etc references come from; I had to
symlink e.g. libXBMC_addon-x86_64-freebsd.so to the linux name.)
Oh and I just saw the vdr-plugin-xvdr port's COMMENT still mentions
vnsi (the old name of the plugin) - will fix that later.
Thanx,
Juergen
More information about the freebsd-multimedia
mailing list