babl: make space remodelling array dynamic
authorØyvind Kolås <pippin@gimp.org>
Thu, 20 Apr 2023 21:04:09 +0000 (23:04 +0200)
committerØyvind Kolås <pippin@gimp.org>
Thu, 20 Apr 2023 21:19:08 +0000 (23:19 +0200)
Thus fixing issue #89

We protect this behind a mutex, initialization of color managed code from
multiple threads have been known to trigger babl races in GEGL/GIMP code.

babl/babl-internal.c
babl/babl-internal.h
babl/babl-model.c

index 94043d3c4f62e8388b01addb43526a8e0071168b..072127aefb29fd1ebdc70ccff753452f0ccfe66a 100644 (file)
@@ -85,6 +85,7 @@ BablMutex *babl_debug_mutex;
 #endif
 BablMutex *babl_reference_mutex;
 BablMutex *babl_space_mutex;
+BablMutex *babl_remodel_mutex;
 
 void
 babl_internal_init (void)
@@ -95,6 +96,7 @@ babl_internal_init (void)
   babl_format_mutex = babl_mutex_new ();
   babl_reference_mutex = babl_mutex_new ();
   babl_space_mutex = babl_mutex_new ();
+  babl_remodel_mutex = babl_mutex_new ();
 #if BABL_DEBUG_MEM
   babl_debug_mutex = babl_mutex_new ();
 #endif
index 4bdc487cc9b75b33c732e1a2bc8f0709295c54e1..38c4db5282fa320337ea3dbf65c0627c3e3ee3c6 100644 (file)
@@ -250,6 +250,7 @@ extern BablMutex *babl_format_mutex;
 extern BablMutex *babl_fish_mutex;
 extern BablMutex *babl_reference_mutex;
 extern BablMutex *babl_space_mutex;
+extern BablMutex *babl_remodel_mutex;
 
 #define BABL_DEBUG_MEM 0
 #if BABL_DEBUG_MEM
index 7780c73781bdb2d0e4e29077561eaa7f948614b4..a2ec53aa2ccab95e8f5b8b01295786b8221cdab3 100644 (file)
@@ -421,11 +421,9 @@ babl_model_is_symmetric (const Babl *cbabl)
 
 BABL_CLASS_IMPLEMENT (model)
 
-/* XXX: probably better to do like with babl_format, add a -suffix and
- *      insert in normal database than to have this static cache list
- */
-static const Babl *babl_remodels[512]={NULL,};
-int          babl_n_remodels = 0;
+static Babl **babl_remodels = NULL;
+static int    babl_remodel_size = 0;
+static int    babl_n_remodels = 0;
 
 const Babl *
 babl_remodel_with_space (const Babl *model, 
@@ -454,24 +452,37 @@ babl_remodel_with_space (const Babl *model,
 
   assert (BABL_IS_BABL (model));
 
+  babl_mutex_lock (babl_remodel_mutex);
   /* get back to the sRGB model if we are in a COW clone of it  */
   if (model->model.model)
     model = (void*)model->model.model;
 
   assert (BABL_IS_BABL (model));
+  if (babl_remodel_size < babl_n_remodels + 2)
+  {
+    int new_size = (babl_n_remodels + 2) * 2;
+    if (new_size < 256) new_size = 256;
+    babl_remodels = babl_realloc (babl_remodels, new_size * sizeof (Babl*));
+    babl_remodel_size = new_size;
+  }
 
   for (i = 0; i < babl_n_remodels; i++)
   {
     if (babl_remodels[i]->model.model == model &&
         babl_remodels[i]->model.space == space)
-          return babl_remodels[i];
+        {
+          ret = (Babl*)babl_remodels[i];
+          babl_mutex_unlock (babl_remodel_mutex);
+          return ret;
+       }
   }
 
   ret = babl_calloc (sizeof (BablModel), 1);
   memcpy (ret, model, sizeof (BablModel));
   ret->model.space = space;
   ret->model.model = (void*)model; /* use the data as a backpointer to original model */
-  return babl_remodels[babl_n_remodels++] = ret;
+  babl_remodels[babl_n_remodels++] = ret;
+  babl_mutex_unlock (babl_remodel_mutex);
   return (Babl*)ret;
 }