From f01d19431d0e2a14a007d5480e805b99dc933169 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sat, 1 Mar 2014 20:46:58 +0100 Subject: Fix T38873: Crashing on undo of ocean modifier. Issue of this bug is that most part of fftw is not thread safe, only compute-intensive fftw_execute & co are. Since smoke was affected by this issue as well, a global fftw mutex was added to BLI_threads. Audaspace also uses fftw in one of its readers (AUD_BandPassReader.cpp), but this is not an issue currently since this code is disabled in CMake/scons files. There was another threading issue with smoke, we need to copy dm used by emit_from_derivedmesh(), as it is modified by this func. Reviewers: sergey, brecht Reviewed By: brecht CC: brecht Differential Revision: https://developer.blender.org/D374 --- source/blender/blenkernel/intern/ocean.c | 8 ++++++++ source/blender/blenkernel/intern/smoke.c | 14 +++++++++++++- source/blender/blenlib/BLI_threads.h | 1 + source/blender/blenlib/intern/threads.c | 5 +++++ 4 files changed, 27 insertions(+), 1 deletion(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index c1e43365a84..3458f149aa2 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -846,6 +846,8 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in"); o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda"); + BLI_lock_thread(LOCK_FFTW); + if (o->_do_disp_y) { o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y"); o->_disp_y_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in, o->_disp_y, FFTW_ESTIMATE); @@ -890,6 +892,8 @@ void BKE_init_ocean(struct Ocean *o, int M, int N, float Lx, float Lz, float V, o->_Jxz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxz, o->_Jxz, FFTW_ESTIMATE); } + BLI_unlock_thread(LOCK_FFTW); + BLI_rw_mutex_unlock(&o->oceanmutex); set_height_normalize_factor(o); @@ -903,6 +907,8 @@ void BKE_free_ocean_data(struct Ocean *oc) BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE); + BLI_lock_thread(LOCK_FFTW); + if (oc->_do_disp_y) { fftw_destroy_plan(oc->_disp_y_plan); MEM_freeN(oc->_disp_y); @@ -939,6 +945,8 @@ void BKE_free_ocean_data(struct Ocean *oc) MEM_freeN(oc->_Jxz); } + BLI_unlock_thread(LOCK_FFTW); + if (oc->_fft_in) MEM_freeN(oc->_fft_in); diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 61d9ea99c2f..0ec277aeed6 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -207,7 +207,14 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[ sds->wt = NULL; return; } + + /* smoke_turbulence_init uses non-threadsafe functions from fftw3 lib (like fftw_plan & co). */ + BLI_lock_thread(LOCK_FFTW); + sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BLI_temporary_dir(), use_fire, use_colors); + + BLI_unlock_thread(LOCK_FFTW); + sds->res_wt[0] = res[0] * (sds->amplify + 1); sds->res_wt[1] = res[1] * (sds->amplify + 1); sds->res_wt[2] = res[2] * (sds->amplify + 1); @@ -1550,7 +1557,7 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo { if (!sfs->dm) return; { - DerivedMesh *dm = sfs->dm; + DerivedMesh *dm; int defgrp_index = sfs->vgroup_density - 1; MDeformVert *dvert = NULL; MVert *mvert = NULL; @@ -1566,6 +1573,11 @@ static void emit_from_derivedmesh(Object *flow_ob, SmokeDomainSettings *sds, Smo int min[3], max[3], res[3]; int hires_multiplier = 1; + /* copy derivedmesh for thread safety because we modify it, + * main issue is its VertArray being modified, then replaced and freed + */ + dm = CDDM_copy(sfs->dm); + CDDM_calc_normals(dm); mvert = dm->getVertArray(dm); mvert_orig = dm->dupVertArray(dm); /* copy original mvert and restore when done */ diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 3ccfcc023da..62eadb8a8b5 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -88,6 +88,7 @@ int BLI_system_num_threads_override_get(void); #define LOCK_NODES 6 #define LOCK_MOVIECLIP 7 #define LOCK_COLORMANAGE 8 +#define LOCK_FFTW 9 void BLI_lock_thread(int type); void BLI_unlock_thread(int type); diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index c9f4e9ddc15..ded2fd7e06d 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -121,6 +121,7 @@ static pthread_mutex_t _opengl_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _nodes_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _movieclip_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _colormanage_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t _fftw_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_t mainid; static int thread_levels = 0; /* threads can be invoked inside threads */ static int num_threads_override = 0; @@ -399,6 +400,8 @@ void BLI_lock_thread(int type) pthread_mutex_lock(&_movieclip_lock); else if (type == LOCK_COLORMANAGE) pthread_mutex_lock(&_colormanage_lock); + else if (type == LOCK_FFTW) + pthread_mutex_lock(&_fftw_lock); } void BLI_unlock_thread(int type) @@ -421,6 +424,8 @@ void BLI_unlock_thread(int type) pthread_mutex_unlock(&_movieclip_lock); else if (type == LOCK_COLORMANAGE) pthread_mutex_unlock(&_colormanage_lock); + else if (type == LOCK_FFTW) + pthread_mutex_unlock(&_fftw_lock); } /* Mutex Locks */ -- cgit v1.2.3