Atlas - testlock.c
Home / ext / SDL / test Lines: 1 | Size: 5913 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)][FILE BEGIN]1/* 2 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 3 4 This software is provided 'as-is', without any express or implied 5 warranty. In no event will the authors be held liable for any damages 6 arising from the use of this software. 7 8 Permission is granted to anyone to use this software for any purpose, 9 including commercial applications, and to alter it and redistribute it 10 freely. 11*/ 12 13/* Test the thread and mutex locking functions 14 Also exercises the system's signal/thread interaction 15*/ 16 17#include <signal.h> 18#include <stdlib.h> /* for atexit() */ 19 20#include <SDL3/SDL.h> 21#include <SDL3/SDL_main.h> 22#include <SDL3/SDL_test.h> 23 24static SDL_Mutex *mutex = NULL; 25static SDL_ThreadID mainthread; 26static SDL_AtomicInt doterminate; 27static int nb_threads = 6; 28static SDL_Thread **threads; 29static int worktime = 1000; 30static SDLTest_CommonState *state; 31 32/** 33 * SDL_Quit() shouldn't be used with atexit() directly because 34 * calling conventions may differ... 35 */ 36static void 37SDL_Quit_Wrapper(void) 38{ 39 SDL_Quit(); 40 SDLTest_CommonDestroyState(state); 41} 42 43static void printid(void) 44{ 45 SDL_Log("Thread %" SDL_PRIu64 ": exiting", SDL_GetCurrentThreadID()); 46} 47 48static void terminate(int sig) 49{ 50 (void)signal(SIGINT, terminate); 51 SDL_SetAtomicInt(&doterminate, 1); 52} 53 54static void closemutex(int sig) 55{ 56 SDL_ThreadID id = SDL_GetCurrentThreadID(); 57 int i; 58 SDL_Log("Thread %" SDL_PRIu64 ": Cleaning up...", id == mainthread ? 0 : id); 59 SDL_SetAtomicInt(&doterminate, 1); 60 if (threads) { 61 for (i = 0; i < nb_threads; ++i) { 62 SDL_WaitThread(threads[i], NULL); 63 } 64 SDL_free(threads); 65 threads = NULL; 66 } 67 SDL_DestroyMutex(mutex); 68 /* Let 'main()' return normally */ 69 if (sig != 0) { 70 exit(sig); 71 } 72} 73 74static int SDLCALL 75Run(void *data) 76{ 77 SDL_ThreadID current_thread = SDL_GetCurrentThreadID(); 78 79 if (current_thread == mainthread) { 80 (void)signal(SIGTERM, closemutex); 81 } 82 SDL_Log("Thread %" SDL_PRIu64 ": starting up", current_thread); 83 while (!SDL_GetAtomicInt(&doterminate)) { 84 SDL_Log("Thread %" SDL_PRIu64 ": ready to work", current_thread); 85 SDL_LockMutex(mutex); 86 SDL_Log("Thread %" SDL_PRIu64 ": start work!", current_thread); 87 SDL_Delay(1 * worktime); 88 SDL_Log("Thread %" SDL_PRIu64 ": work done!", current_thread); 89 SDL_UnlockMutex(mutex); 90 91 /* If this sleep isn't done, then threads may starve */ 92 SDL_Delay(10); 93 } 94 if (current_thread == mainthread && SDL_GetAtomicInt(&doterminate)) { 95 SDL_Log("Thread %" SDL_PRIu64 ": raising SIGTERM", current_thread); 96 (void)raise(SIGTERM); 97 } 98 SDL_Log("Thread %" SDL_PRIu64 ": exiting!", current_thread); 99 return 0; 100} 101 102#ifndef _WIN32 103static Uint32 hit_timeout(void *param, SDL_TimerID timerID, Uint32 interval) { 104 SDL_Log("Hit timeout! Sending SIGINT!"); 105 (void)raise(SIGINT); 106 return 0; 107} 108#endif 109 110int main(int argc, char *argv[]) 111{ 112 int i; 113#ifndef _WIN32 114 int timeout = 0; 115#endif 116 117 /* Initialize test framework */ 118 state = SDLTest_CommonCreateState(argv, 0); 119 if (!state) { 120 return 1; 121 } 122 123 /* Parse commandline */ 124 for (i = 1; i < argc;) { 125 int consumed; 126 127 consumed = SDLTest_CommonArg(state, i); 128 if (!consumed) { 129 if (SDL_strcmp(argv[i], "--nbthreads") == 0) { 130 if (argv[i + 1]) { 131 char *endptr; 132 nb_threads = SDL_strtol(argv[i + 1], &endptr, 0); 133 if (endptr != argv[i + 1] && *endptr == '\0' && nb_threads > 0) { 134 consumed = 2; 135 } 136 } 137 } else if (SDL_strcmp(argv[i], "--worktime") == 0) { 138 if (argv[i + 1]) { 139 char *endptr; 140 nb_threads = SDL_strtol(argv[i + 1], &endptr, 0); 141 if (endptr != argv[i + 1] && *endptr == '\0' && nb_threads > 0) { 142 consumed = 2; 143 } 144 } 145#ifndef _WIN32 146 } else if (SDL_strcmp(argv[i], "--timeout") == 0) { 147 if (argv[i + 1]) { 148 char *endptr; 149 timeout = SDL_strtol(argv[i + 1], &endptr, 0); 150 if (endptr != argv[i + 1] && *endptr == '\0' && timeout > 0) { 151 consumed = 2; 152 } 153 } 154#endif 155 } 156 } 157 if (consumed <= 0) { 158 static const char *options[] = { 159 "[--nbthreads NB]", 160 "[--worktime ms]", 161#ifndef _WIN32 162 "[--timeout ms]", 163#endif 164 NULL, 165 }; 166 SDLTest_CommonLogUsage(state, argv[0], options); 167 exit(1); 168 } 169 170 i += consumed; 171 } 172 173 threads = SDL_malloc(nb_threads * sizeof(SDL_Thread*)); 174 175 /* Load the SDL library */ 176 if (!SDL_Init(0)) { 177 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s", SDL_GetError()); 178 exit(1); 179 } 180 (void)atexit(SDL_Quit_Wrapper); 181 182 SDL_SetAtomicInt(&doterminate, 0); 183 184 mutex = SDL_CreateMutex(); 185 if (!mutex) { 186 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s", SDL_GetError()); 187 exit(1); 188 } 189 190 mainthread = SDL_GetCurrentThreadID(); 191 SDL_Log("Main thread: %" SDL_PRIu64, mainthread); 192 (void)atexit(printid); 193 for (i = 0; i < nb_threads; ++i) { 194 char name[64]; 195 (void)SDL_snprintf(name, sizeof(name), "Worker%d", i); 196 threads[i] = SDL_CreateThread(Run, name, NULL); 197 if (threads[i] == NULL) { 198 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread!"); 199 } 200 } 201 202#ifndef _WIN32 203 if (timeout) { 204 SDL_AddTimer(timeout, hit_timeout, NULL); 205 } 206#endif 207 208 (void)signal(SIGINT, terminate); 209 Run(NULL); 210 211 return 0; /* Never reached */ 212} 213[FILE END](C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.