From 6867f6189fa31bd22d623d87367975f830f14a46 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Fri, 16 Feb 2018 14:56:28 -0500 Subject: [PATCH] video: put a spinlock around a global linked list. This should only contend if you're allocating or freeing surfaces from multiple threads at once, and then just for a short time. Fixes Bugzilla #4084. --- src/video/SDL_pixels.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index 5dacf5303d9fa..2e263955c062e 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -490,16 +490,20 @@ SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, } static SDL_PixelFormat *formats; +static SDL_SpinLock formats_lock = 0; SDL_PixelFormat * SDL_AllocFormat(Uint32 pixel_format) { SDL_PixelFormat *format; + SDL_AtomicLock(&formats_lock); + /* Look it up in our list of previously allocated formats */ for (format = formats; format; format = format->next) { if (pixel_format == format->format) { ++format->refcount; + SDL_AtomicUnlock(&formats_lock); return format; } } @@ -507,10 +511,12 @@ SDL_AllocFormat(Uint32 pixel_format) /* Allocate an empty pixel format structure, and initialize it */ format = SDL_malloc(sizeof(*format)); if (format == NULL) { + SDL_AtomicUnlock(&formats_lock); SDL_OutOfMemory(); return NULL; } if (SDL_InitFormat(format, pixel_format) < 0) { + SDL_AtomicUnlock(&formats_lock); SDL_free(format); SDL_InvalidParamError("format"); return NULL; @@ -521,6 +527,9 @@ SDL_AllocFormat(Uint32 pixel_format) format->next = formats; formats = format; } + + SDL_AtomicUnlock(&formats_lock); + return format; } @@ -598,7 +607,11 @@ SDL_FreeFormat(SDL_PixelFormat *format) SDL_InvalidParamError("format"); return; } + + SDL_AtomicLock(&formats_lock); + if (--format->refcount > 0) { + SDL_AtomicUnlock(&formats_lock); return; } @@ -614,6 +627,8 @@ SDL_FreeFormat(SDL_PixelFormat *format) } } + SDL_AtomicUnlock(&formats_lock); + if (format->palette) { SDL_FreePalette(format->palette); }