[Mesa-dev] Threading issues with LLVM pipeline

Jose Fonseca jfonseca at vmware.com
Fri Mar 30 03:42:11 PDT 2012


gallivm/llvmpipe is not thread safe.

To fix it, we need to have separate LLVMContext / JIT engines for each pipe_context (i.e., each thread).

I'm working on a branch that does most of this, and I plan to commit over the next month or so. That branch also has changes for the compilation to happen per function, and not per module, so that we can use MC-JIT (which will eventually supersed the current JIT engine), and that part is a bit experimental and needs more work, which is why I can't commit immediately.

Jose

----- Original Message -----
> Hi,
> 
> last time I was wondering about thread safety in Mesa 8.0 build with
> llvm=no - this configuration seems to be working with the lock patch.
> 
> Now I am testing 8.0 branch with LLVM 3.0 (with scons script fix
> a1482b21cb438c271cf20e7d52cb9e4e0537344c - stop me if it is not
> supposed to work)
> 
> I have very simple GL code:
> 
>   HGLRC glContext = wglCreateContext(hDC);
>   wglMakeCurrent(hDC, glContext);
> 
>   glViewport(0, 0, 1024, 600);
> 
>   void *buffer = malloc(1024*600*3);
>   for (int i=0; i < 100; i++) {
>     glClearColor(0.0, 0.0, 1.0, 0);
>     glClear(GL_COLOR_BUFFER_BIT);
>     glReadPixels(0, 0, 1024, 600, GL_RGB, GL_UNSIGNED_BYTE, buffer);
>     SwapBuffers(hDC);
>     Sleep(20);
>   }
>   free (buffer);
> 
> 
> which I run in 2 or more threads. The first problem occurs during
> wglMakeCurrent:
> 
> thread 1:
> 
> opengl32.dll!pipe_semaphore_wait(pipe_semaphore * sema)  Line 432 +
> 0x17 bytes
> opengl32.dll!lp_rast_finish(lp_rasterizer * rast)  Line 782 + 0x16
> bytes
> opengl32.dll!lp_setup_rasterize_scene(lp_setup_context * setup)  Line
> 160 + 0xc bytes
> opengl32.dll!set_scene_state(lp_setup_context * setup, setup_state
> new_state, const char * reason)  Line 313 + 0x9 bytes
> opengl32.dll!lp_setup_flush(lp_setup_context * setup,
> pipe_fence_handle * * fence, const char * reason)  Line 342 + 0xf
> bytes
> opengl32.dll!llvmpipe_flush(pipe_context * pipe, pipe_fence_handle *
> *
> fence, const char * reason)  Line 55 + 0x17 bytes
> opengl32.dll!llvmpipe_finish(pipe_context * pipe, const char *
> reason)
>  Line 89 + 0x11 bytes
> opengl32.dll!llvmpipe_flush_resource(pipe_context * pipe,
> pipe_resource * resource, unsigned int level, int layer, unsigned
> char
> read_only, unsigned char cpu_access, unsigned char do_not_block,
> const
> char * reason)  Line 128 + 0xd bytes
> opengl32.dll!llvmpipe_get_transfer(pipe_context * pipe, pipe_resource
> * resource, unsigned int level, unsigned int usage, const pipe_box *
> box)  Line 607 + 0x41 bytes
> opengl32.dll!pipe_get_transfer(pipe_context * context, pipe_resource
> *
> resource, unsigned int level, unsigned int layer, pipe_transfer_usage
> usage, unsigned int x, unsigned int y, unsigned int w, unsigned int
> h)
>  Line 393 + 0x1f bytes
> opengl32.dll!st_MapRenderbuffer(gl_context * ctx, gl_renderbuffer *
> rb, unsigned int x, unsigned int y, unsigned int w, unsigned int h,
> unsigned int mode, unsigned char * * mapOut, int * rowStrideOut)
>  Line
> 683 + 0x38 bytes
> opengl32.dll!slow_read_rgba_pixels(gl_context * ctx, int x, int y,
> int
> width, int height, unsigned int format, unsigned int type, void *
> pixels, const gl_pixelstore_attrib * packing, unsigned int
> transferOps)  Line 274 + 0x2d bytes
> opengl32.dll!read_rgba_pixels(gl_context * ctx, int x, int y, int
> width, int height, unsigned int format, unsigned int type, void *
> pixels, const gl_pixelstore_attrib * packing)  Line 338 + 0x2d bytes
> opengl32.dll!_mesa_readpixels(gl_context * ctx, int x, int y, int
> width, int height, unsigned int format, unsigned int type, const
> gl_pixelstore_attrib * packing, void * pixels)  Line 586 + 0x29 bytes
> opengl32.dll!st_readpixels(gl_context * ctx, int x, int y, int width,
> int height, unsigned int format, unsigned int type, const
> gl_pixelstore_attrib * pack, void * dest)  Line 54 + 0x29 bytes
> opengl32.dll!_mesa_ReadnPixelsARB(int x, int y, int width, int
> height,
> unsigned int format, unsigned int type, int bufSize, void * pixels)
> Line 831 + 0x35 bytes
> opengl32.dll!_mesa_ReadPixels(int x, int y, int width, int height,
> unsigned int format, unsigned int type, void * pixels)  Line 839
> opengl32.dll!glReadPixels(int x, int y, int width, int height,
> unsigned int format, unsigned int type, void * pixels)  Line 1618
> multithreads.exe!display_gl_window(int id)  Line 103 + 0x24 bytes
> multithreads.exe!thread_1_main(void * lpParameter)  Line 126 + 0x9
> bytes
> 
> thread 2:
> 
> opengl32.dll!_debug_assert_fail(const char * expr, const char * file,
> unsigned int line, const char * function)  Line 278
> opengl32.dll!begin_binning(lp_setup_context * setup)  Line 180 + 0x24
> bytes
> opengl32.dll!execute_clears(lp_setup_context * setup)  Line 262 + 0x9
> bytes
> opengl32.dll!set_scene_state(lp_setup_context * setup, setup_state
> new_state, const char * reason)  Line 310 + 0x9 bytes
> opengl32.dll!lp_setup_flush(lp_setup_context * setup,
> pipe_fence_handle * * fence, const char * reason)  Line 342 + 0xf
> bytes
> opengl32.dll!llvmpipe_flush(pipe_context * pipe, pipe_fence_handle *
> *
> fence, const char * reason)  Line 55 + 0x17 bytes
> opengl32.dll!do_flush(pipe_context * pipe, pipe_fence_handle * *
> fence)  Line 141 + 0x12 bytes
> opengl32.dll!st_flush(st_context * st, pipe_fence_handle * * fence)
> Line 92 + 0x19 bytes
> opengl32.dll!st_context_flush(st_context_iface * stctxi, unsigned int
> flags, pipe_fence_handle * * fence)  Line 462 + 0xd bytes
> opengl32.dll!stw_make_current(HDC__ * hdc, unsigned long dhglrc)
>  Line
> 327 + 0x14 bytes
> opengl32.dll!DrvSetContext(HDC__ * hdc, unsigned long dhglrc, void
> (_GLCLTPROCTABLE *)* pfnSetProcTable)  Line 768 + 0xd bytes
> opengl32.dll!wglMakeCurrent(HDC__ * hdc, HGLRC__ * hglrc)  Line 88 +
> 0xf bytes
> multithreads.exe!display_gl_window(int id)  Line 94 + 0x10 bytes
> multithreads.exe!thread_1_main(void * lpParameter)  Line 126 + 0x9
> bytes
> 
> I tested that this is probably because of late init of ThreadSafe
> flag
> in u_current.c - if I set it to 1 the call does not fail. Basically
> the call to stw_current_context in stw_make_current returns the other
> thread context and not null.
> After hard coding ThreadSafe to 1 I am getting crashes in LLVM code.
> The suspicious code is gallivm_create() which returns singleton but
> the creation is not guarded by any lock.
> The code is randomly failing somewhere within LLVMCreateJITCompiler.
> 
> Thanks,
> Juraj
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
> 


More information about the mesa-dev mailing list