Fix #33125: cycles OSL crash with multiple render sessions running at the same time.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 9 Nov 2012 03:10:22 +0000 (03:10 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Fri, 9 Nov 2012 03:10:22 +0000 (03:10 +0000)
intern/cycles/kernel/osl/osl_globals.h
intern/cycles/kernel/osl/osl_shader.cpp
intern/cycles/render/osl.cpp
intern/cycles/render/osl.h

index 5d557ff..80ced9d 100644 (file)
@@ -68,6 +68,11 @@ struct OSLGlobals {
        };
 
        static tls_ptr(ThreadData, thread_data);
+       static thread_mutex thread_data_mutex;
+       static volatile int thread_data_users;
+
+       void thread_data_init();
+       void thread_data_free();
 };
 
 CCL_NAMESPACE_END
index 0c8de05..abf7c04 100644 (file)
 CCL_NAMESPACE_BEGIN
 
 tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data);
+volatile int OSLGlobals::thread_data_users = 0;
+thread_mutex OSLGlobals::thread_data_mutex;
 
 /* Threads */
 
+void OSLGlobals::thread_data_init()
+{
+       thread_scoped_lock thread_data_lock(thread_data_mutex);
+
+       if(thread_data_users == 0)
+               tls_create(OSLGlobals::ThreadData, thread_data);
+
+       thread_data_users++;
+}
+
+void OSLGlobals::thread_data_free()
+{
+       /* thread local storage delete */
+       thread_scoped_lock thread_data_lock(thread_data_mutex);
+
+       thread_data_users--;
+
+       if(thread_data_users == 0)
+               tls_delete(OSLGlobals::ThreadData, thread_data);
+}
+
 void OSLShader::thread_init(KernelGlobals *kg)
 {
        OSL::ShadingSystem *ss = kg->osl.ss;
index 8bdb09e..5fbc793 100644 (file)
@@ -45,6 +45,8 @@ CCL_NAMESPACE_BEGIN
 
 OSLShaderManager::OSLShaderManager()
 {
+       thread_data_initialized = false;
+
        services = new OSLRenderServices();
 
        shading_system_init();
@@ -91,8 +93,6 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
        og->background_state = og->surface_state[background_id & SHADER_MASK];
        og->use = true;
 
-       tls_create(OSLGlobals::ThreadData, og->thread_data);
-
        foreach(Shader *shader, scene->shaders)
                shader->need_update = false;
 
@@ -102,6 +102,11 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene
        scene->image_manager->set_osl_texture_system((void*)ts);
 
        device_update_common(device, dscene, scene, progress);
+
+       if(!thread_data_initialized) {
+               og->thread_data_init();
+               thread_data_initialized = true;
+       }
 }
 
 void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
@@ -114,12 +119,15 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene)
        og->use = false;
        og->ss = NULL;
 
-       tls_delete(OSLGlobals::ThreadData, og->thread_data);
-
        og->surface_state.clear();
        og->volume_state.clear();
        og->displacement_state.clear();
        og->background_state.reset();
+
+       if(thread_data_initialized) {
+               og->thread_data_free();
+               thread_data_initialized = false;
+       }
 }
 
 void OSLShaderManager::texture_system_init()
index cee37c5..b4b3f59 100644 (file)
@@ -73,6 +73,8 @@ protected:
        OSLRenderServices *services;
        OSL::ErrorHandler errhandler;
        set<string> loaded_shaders;
+
+       bool thread_data_initialized;
 };
 
 #endif