Commit c2ed6935 authored by Eric Engestrom's avatar Eric Engestrom Committed by Andres Gomez

egl/display: make platform detection thread-safe

Imagine there are 2 threads that both call _eglGetNativePlatform()
simultaneously:
- thread 1 completes the first "if (native_platform ==
  _EGL_INVALID_PLATFORM)" check and is preempted to do something else
- thread 2 executes the whole function, does "native_platform =
  _EGL_NATIVE_PLATFORM" and just before returning it's preempted
- thread 1 wakes up and calls _eglGetNativePlatformFromEnv() which
  returns _EGL_INVALID_PLATFORM because no env vars are set, updates
  native_platform and then gets preempted again
- thread 2 wakes up and returns wrong _EGL_INVALID_PLATFORM

Solve this by doing the detection in a local var and only overwriting
the global one at the end, if no other thread has updated it since.

This means the platform detected in the thread might not be the platform
returned by the function, but this is a different issue that will need
to be discussed when this becomes possible.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101252Signed-off-by: Eric Engestrom's avatarEric Engestrom <eric@engestrom.ch>
Reviewed-by: Grazvydas Ignotas's avatarGrazvydas Ignotas <notasas@gmail.com>
Acked-by: Emil Velikov's avatarEmil Velikov <emil.l.velikov@gmail.com>
(cherry picked from commit 311c0916)
parent f9c7c9f4
......@@ -36,6 +36,7 @@
#include <stdlib.h>
#include <string.h>
#include "c11/threads.h"
#include "util/u_atomic.h"
#include "eglcontext.h"
#include "eglcurrent.h"
......@@ -181,25 +182,29 @@ _EGLPlatformType
_eglGetNativePlatform(void *nativeDisplay)
{
static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
_EGLPlatformType detected_platform = native_platform;
if (native_platform == _EGL_INVALID_PLATFORM) {
if (detected_platform == _EGL_INVALID_PLATFORM) {
const char *detection_method;
native_platform = _eglGetNativePlatformFromEnv();
detected_platform = _eglGetNativePlatformFromEnv();
detection_method = "environment overwrite";
if (native_platform == _EGL_INVALID_PLATFORM) {
native_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
if (detected_platform == _EGL_INVALID_PLATFORM) {
detected_platform = _eglNativePlatformDetectNativeDisplay(nativeDisplay);
detection_method = "autodetected";
}
if (native_platform == _EGL_INVALID_PLATFORM) {
native_platform = _EGL_NATIVE_PLATFORM;
if (detected_platform == _EGL_INVALID_PLATFORM) {
detected_platform = _EGL_NATIVE_PLATFORM;
detection_method = "build-time configuration";
}
_eglLog(_EGL_DEBUG, "Native platform type: %s (%s)",
egl_platforms[native_platform].name, detection_method);
egl_platforms[detected_platform].name, detection_method);
p_atomic_cmpxchg(&native_platform, _EGL_INVALID_PLATFORM,
detected_platform);
}
return native_platform;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment