From d90fce3c9eee0b80189f5e3a5f18c2f7a1ab8a37 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 10 Oct 2017 11:10:15 -0700 Subject: [PATCH] Exposed the joystick locking functions for multi-threaded access to the joystick API --- include/SDL_joystick.h | 14 ++++++++++ src/dynapi/SDL_dynapi_overrides.h | 2 ++ src/dynapi/SDL_dynapi_procs.h | 2 ++ src/joystick/SDL_gamecontroller.c | 38 +++++++++++++------------- src/joystick/SDL_joystick.c | 44 +++++++++++++++---------------- src/joystick/SDL_joystick_c.h | 4 --- 6 files changed, 59 insertions(+), 45 deletions(-) diff --git a/include/SDL_joystick.h b/include/SDL_joystick.h index 698b09c1429c5..f598dc828dafa 100644 --- a/include/SDL_joystick.h +++ b/include/SDL_joystick.h @@ -106,6 +106,20 @@ typedef enum } SDL_JoystickPowerLevel; /* Function prototypes */ + +/** + * Locking for multi-threaded access to the joystick API + * + * If you are using the joystick API or handling events from multiple threads + * you should use these locking functions to protect access to the joysticks. + * + * In particular, you are guaranteed that the joystick list won't change, so + * the API functions that take a joystick index will be valid, and joystick + * and game controller events will not be delivered. + */ +extern DECLSPEC void SDLCALL SDL_LockJoysticks(void); +extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void); + /** * Count the number of joysticks attached to the system right now */ diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 95943bc1f6a30..3ef56d23af2db 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -635,3 +635,5 @@ #define SDL_Vulkan_GetInstanceExtensions SDL_Vulkan_GetInstanceExtensions_REAL #define SDL_Vulkan_CreateSurface SDL_Vulkan_CreateSurface_REAL #define SDL_Vulkan_GetDrawableSize SDL_Vulkan_GetDrawableSize_REAL +#define SDL_LockJoysticks SDL_LockJoysticks_REAL +#define SDL_UnlockJoysticks SDL_UnlockJoysticks_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index b7466fdb64c4e..730fbcc327e97 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -669,3 +669,5 @@ SDL_DYNAPI_PROC(void,SDL_Vulkan_UnloadLibrary,(void),(),) SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_GetInstanceExtensions,(SDL_Window *a, unsigned int *b, const char **c),(a,b,c),return) SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b, VkSurfaceKHR *c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_Vulkan_GetDrawableSize,(SDL_Window *a, int *b, int *c),(a,b,c),) +SDL_DYNAPI_PROC(void,SDL_LockJoysticks,(void),(),) +SDL_DYNAPI_PROC(void,SDL_UnlockJoysticks,(void),(),) diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 0802c88c763af..13953de51c250 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -24,9 +24,9 @@ #include "SDL_events.h" #include "SDL_assert.h" +#include "SDL_hints.h" #include "SDL_sysjoystick.h" #include "SDL_joystick_c.h" -#include "SDL_hints.h" #include "SDL_gamecontrollerdb.h" #if !SDL_EVENTS_DISABLED @@ -910,7 +910,7 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index) SDL_JoystickGUID guid; ControllerMapping_t *mapping; - SDL_LockJoystickList(); + SDL_LockJoysticks(); name = SDL_JoystickNameForIndex(device_index); guid = SDL_JoystickGetDeviceGUID(device_index); mapping = SDL_PrivateGetControllerMappingForNameAndGUID(name, guid); @@ -919,7 +919,7 @@ static ControllerMapping_t *SDL_PrivateGetControllerMapping(int device_index) mapping = s_pXInputMapping; } #endif - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return mapping; } @@ -1349,7 +1349,7 @@ SDL_GameControllerOpen(int device_index) return (NULL); } - SDL_LockJoystickList(); + SDL_LockJoysticks(); gamecontrollerlist = SDL_gamecontrollers; /* If the controller is already open, return it */ @@ -1357,7 +1357,7 @@ SDL_GameControllerOpen(int device_index) if (SDL_SYS_GetInstanceIdOfDeviceIndex(device_index) == gamecontrollerlist->joystick->instance_id) { gamecontroller = gamecontrollerlist; ++gamecontroller->ref_count; - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return (gamecontroller); } gamecontrollerlist = gamecontrollerlist->next; @@ -1367,7 +1367,7 @@ SDL_GameControllerOpen(int device_index) pSupportedController = SDL_PrivateGetControllerMapping(device_index); if (!pSupportedController) { SDL_SetError("Couldn't find mapping for device (%d)", device_index); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } @@ -1375,14 +1375,14 @@ SDL_GameControllerOpen(int device_index) gamecontroller = (SDL_GameController *) SDL_calloc(1, sizeof(*gamecontroller)); if (gamecontroller == NULL) { SDL_OutOfMemory(); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } gamecontroller->joystick = SDL_JoystickOpen(device_index); if (!gamecontroller->joystick) { SDL_free(gamecontroller); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } @@ -1392,7 +1392,7 @@ SDL_GameControllerOpen(int device_index) SDL_OutOfMemory(); SDL_JoystickClose(gamecontroller->joystick); SDL_free(gamecontroller); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } } @@ -1403,7 +1403,7 @@ SDL_GameControllerOpen(int device_index) SDL_JoystickClose(gamecontroller->joystick); SDL_free(gamecontroller->last_match_axis); SDL_free(gamecontroller); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } } @@ -1416,7 +1416,7 @@ SDL_GameControllerOpen(int device_index) gamecontroller->next = SDL_gamecontrollers; SDL_gamecontrollers = gamecontroller; - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return (gamecontroller); } @@ -1589,16 +1589,16 @@ SDL_GameControllerFromInstanceID(SDL_JoystickID joyid) { SDL_GameController *gamecontroller; - SDL_LockJoystickList(); + SDL_LockJoysticks(); gamecontroller = SDL_gamecontrollers; while (gamecontroller) { if (gamecontroller->joystick->instance_id == joyid) { - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return gamecontroller; } gamecontroller = gamecontroller->next; } - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } @@ -1674,11 +1674,11 @@ SDL_GameControllerClose(SDL_GameController * gamecontroller) if (!gamecontroller) return; - SDL_LockJoystickList(); + SDL_LockJoysticks(); /* First decrement ref count */ if (--gamecontroller->ref_count > 0) { - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return; } @@ -1705,7 +1705,7 @@ SDL_GameControllerClose(SDL_GameController * gamecontroller) SDL_free(gamecontroller->last_hat_mask); SDL_free(gamecontroller); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); } @@ -1715,12 +1715,12 @@ SDL_GameControllerClose(SDL_GameController * gamecontroller) void SDL_GameControllerQuit(void) { - SDL_LockJoystickList(); + SDL_LockJoysticks(); while (SDL_gamecontrollers) { SDL_gamecontrollers->ref_count = 1; SDL_GameControllerClose(SDL_gamecontrollers); } - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); } void diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index 0724db258adb0..4c4cae7578191 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -40,7 +40,7 @@ static SDL_bool SDL_updating_joystick = SDL_FALSE; static SDL_mutex *SDL_joystick_lock = NULL; /* This needs to support recursive locks */ void -SDL_LockJoystickList(void) +SDL_LockJoysticks(void) { if (SDL_joystick_lock) { SDL_LockMutex(SDL_joystick_lock); @@ -48,7 +48,7 @@ SDL_LockJoystickList(void) } void -SDL_UnlockJoystickList(void) +SDL_UnlockJoysticks(void) { if (SDL_joystick_lock) { SDL_UnlockMutex(SDL_joystick_lock); @@ -168,7 +168,7 @@ SDL_JoystickOpen(int device_index) return (NULL); } - SDL_LockJoystickList(); + SDL_LockJoysticks(); joysticklist = SDL_joysticks; /* If the joystick is already open, return it @@ -178,7 +178,7 @@ SDL_JoystickOpen(int device_index) if (SDL_JoystickGetDeviceInstanceID(device_index) == joysticklist->instance_id) { joystick = joysticklist; ++joystick->ref_count; - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return (joystick); } joysticklist = joysticklist->next; @@ -188,13 +188,13 @@ SDL_JoystickOpen(int device_index) joystick = (SDL_Joystick *) SDL_calloc(sizeof(*joystick), 1); if (joystick == NULL) { SDL_OutOfMemory(); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } if (SDL_SYS_JoystickOpen(joystick, device_index) < 0) { SDL_free(joystick); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } @@ -222,7 +222,7 @@ SDL_JoystickOpen(int device_index) || ((joystick->nbuttons > 0) && !joystick->buttons)) { SDL_OutOfMemory(); SDL_JoystickClose(joystick); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } joystick->epowerlevel = SDL_JOYSTICK_POWER_UNKNOWN; @@ -244,7 +244,7 @@ SDL_JoystickOpen(int device_index) joystick->next = SDL_joysticks; SDL_joysticks = joystick; - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); SDL_SYS_JoystickUpdate(joystick); @@ -460,14 +460,14 @@ SDL_JoystickFromInstanceID(SDL_JoystickID joyid) { SDL_Joystick *joystick; - SDL_LockJoystickList(); + SDL_LockJoysticks(); for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { if (joystick->instance_id == joyid) { - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return joystick; } } - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return NULL; } @@ -497,16 +497,16 @@ SDL_JoystickClose(SDL_Joystick * joystick) return; } - SDL_LockJoystickList(); + SDL_LockJoysticks(); /* First decrement ref count */ if (--joystick->ref_count > 0) { - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return; } if (SDL_updating_joystick) { - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return; } @@ -538,7 +538,7 @@ SDL_JoystickClose(SDL_Joystick * joystick) SDL_free(joystick->buttons); SDL_free(joystick); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); } void @@ -547,7 +547,7 @@ SDL_JoystickQuit(void) /* Make sure we're not getting called in the middle of updating joysticks */ SDL_assert(!SDL_updating_joystick); - SDL_LockJoystickList(); + SDL_LockJoysticks(); /* Stop the event polling */ while (SDL_joysticks) { @@ -558,7 +558,7 @@ SDL_JoystickQuit(void) /* Quit the joystick setup */ SDL_SYS_JoystickQuit(); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); #if !SDL_EVENTS_DISABLED SDL_QuitSubSystem(SDL_INIT_EVENTS); @@ -847,18 +847,18 @@ SDL_JoystickUpdate(void) { SDL_Joystick *joystick; - SDL_LockJoystickList(); + SDL_LockJoysticks(); if (SDL_updating_joystick) { /* The joysticks are already being updated */ - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); return; } SDL_updating_joystick = SDL_TRUE; /* Make sure the list is unlocked while dispatching events to prevent application deadlocks */ - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); for (joystick = SDL_joysticks; joystick; joystick = joystick->next) { SDL_SYS_JoystickUpdate(joystick); @@ -885,7 +885,7 @@ SDL_JoystickUpdate(void) } } - SDL_LockJoystickList(); + SDL_LockJoysticks(); SDL_updating_joystick = SDL_FALSE; @@ -901,7 +901,7 @@ SDL_JoystickUpdate(void) */ SDL_SYS_JoystickDetect(); - SDL_UnlockJoystickList(); + SDL_UnlockJoysticks(); } int diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 5339b83780941..85d3920042706 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -33,10 +33,6 @@ extern void SDL_GameControllerQuitMappings(void); extern int SDL_GameControllerInit(void); extern void SDL_GameControllerQuit(void); -/* Locking for multi-threaded access to the joystick API */ -extern void SDL_LockJoystickList(void); -extern void SDL_UnlockJoystickList(void); - /* Function to extract information from an SDL joystick GUID */ extern void SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version);