testlock.c (3433B)
1 /* 2 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> 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 <stdio.h> 19 #include <stdlib.h> /* for atexit() */ 20 21 #include "SDL.h" 22 23 static SDL_mutex *mutex = NULL; 24 static SDL_threadID mainthread; 25 static SDL_Thread *threads[6]; 26 static SDL_atomic_t doterminate; 27 28 /* 29 * SDL_Quit() shouldn't be used with atexit() directly because 30 * calling conventions may differ... 31 */ 32 static void 33 SDL_Quit_Wrapper(void) 34 { 35 SDL_Quit(); 36 } 37 38 void 39 printid(void) 40 { 41 SDL_Log("Process %lu: exiting\n", SDL_ThreadID()); 42 } 43 44 void 45 terminate(int sig) 46 { 47 signal(SIGINT, terminate); 48 SDL_AtomicSet(&doterminate, 1); 49 } 50 51 void 52 closemutex(int sig) 53 { 54 SDL_threadID id = SDL_ThreadID(); 55 int i; 56 SDL_Log("Process %lu: Cleaning up...\n", id == mainthread ? 0 : id); 57 SDL_AtomicSet(&doterminate, 1); 58 for (i = 0; i < 6; ++i) 59 SDL_WaitThread(threads[i], NULL); 60 SDL_DestroyMutex(mutex); 61 exit(sig); 62 } 63 64 int SDLCALL 65 Run(void *data) 66 { 67 if (SDL_ThreadID() == mainthread) 68 signal(SIGTERM, closemutex); 69 while (!SDL_AtomicGet(&doterminate)) { 70 SDL_Log("Process %lu ready to work\n", SDL_ThreadID()); 71 if (SDL_LockMutex(mutex) < 0) { 72 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError()); 73 exit(1); 74 } 75 SDL_Log("Process %lu, working!\n", SDL_ThreadID()); 76 SDL_Delay(1 * 1000); 77 SDL_Log("Process %lu, done!\n", SDL_ThreadID()); 78 if (SDL_UnlockMutex(mutex) < 0) { 79 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't unlock mutex: %s", SDL_GetError()); 80 exit(1); 81 } 82 /* If this sleep isn't done, then threads may starve */ 83 SDL_Delay(10); 84 } 85 if (SDL_ThreadID() == mainthread && SDL_AtomicGet(&doterminate)) { 86 SDL_Log("Process %lu: raising SIGTERM\n", SDL_ThreadID()); 87 raise(SIGTERM); 88 } 89 return (0); 90 } 91 92 int 93 main(int argc, char *argv[]) 94 { 95 int i; 96 int maxproc = 6; 97 98 /* Enable standard application logging */ 99 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); 100 101 /* Load the SDL library */ 102 if (SDL_Init(0) < 0) { 103 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError()); 104 exit(1); 105 } 106 atexit(SDL_Quit_Wrapper); 107 108 SDL_AtomicSet(&doterminate, 0); 109 110 if ((mutex = SDL_CreateMutex()) == NULL) { 111 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s\n", SDL_GetError()); 112 exit(1); 113 } 114 115 mainthread = SDL_ThreadID(); 116 SDL_Log("Main thread: %lu\n", mainthread); 117 atexit(printid); 118 for (i = 0; i < maxproc; ++i) { 119 char name[64]; 120 SDL_snprintf(name, sizeof (name), "Worker%d", i); 121 if ((threads[i] = SDL_CreateThread(Run, name, NULL)) == NULL) 122 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread!\n"); 123 } 124 signal(SIGINT, terminate); 125 Run(NULL); 126 127 return (0); /* Never reached */ 128 }