testlock.c
Go to the documentation of this file.
/*
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely.
*/
/* Test the thread and mutex locking functions
Also exercises the system's signal/thread interaction
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h> /* for atexit() */
#include "SDL.h"
static SDL_mutex *mutex = NULL;
static SDL_threadID mainthread;
static SDL_Thread *threads[6];
static SDL_atomic_t doterminate;
/*
* SDL_Quit() shouldn't be used with atexit() directly because
* calling conventions may differ...
*/
static void
SDL_Quit_Wrapper(void)
{
SDL_Quit();
}
void
printid(void)
{
SDL_Log("Process %lu: exiting\n", SDL_ThreadID());
}
void
terminate(int sig)
{
signal(SIGINT, terminate);
SDL_AtomicSet(&doterminate, 1);
}
void
closemutex(int sig)
{
SDL_threadID id = SDL_ThreadID();
int i;
SDL_Log("Process %lu: Cleaning up...\n", id == mainthread ? 0 : id);
SDL_AtomicSet(&doterminate, 1);
for (i = 0; i < 6; ++i)
SDL_WaitThread(threads[i], NULL);
SDL_DestroyMutex(mutex);
exit(sig);
}
int SDLCALL
Run(void *data)
{
if (SDL_ThreadID() == mainthread)
signal(SIGTERM, closemutex);
while (!SDL_AtomicGet(&doterminate)) {
SDL_Log("Process %lu ready to work\n", SDL_ThreadID());
if (SDL_LockMutex(mutex) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError());
exit(1);
}
SDL_Log("Process %lu, working!\n", SDL_ThreadID());
SDL_Delay(1 * 1000);
SDL_Log("Process %lu, done!\n", SDL_ThreadID());
if (SDL_UnlockMutex(mutex) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't unlock mutex: %s", SDL_GetError());
exit(1);
}
/* If this sleep isn't done, then threads may starve */
SDL_Delay(10);
}
if (SDL_ThreadID() == mainthread && SDL_AtomicGet(&doterminate)) {
SDL_Log("Process %lu: raising SIGTERM\n", SDL_ThreadID());
raise(SIGTERM);
}
return (0);
}
int
main(int argc, char *argv[])
{
int i;
int maxproc = 6;
/* Enable standard application logging */
SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
/* Load the SDL library */
if (SDL_Init(0) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "%s\n", SDL_GetError());
exit(1);
}
atexit(SDL_Quit_Wrapper);
SDL_AtomicSet(&doterminate, 0);
if ((mutex = SDL_CreateMutex()) == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s\n", SDL_GetError());
exit(1);
}
mainthread = SDL_ThreadID();
SDL_Log("Main thread: %lu\n", mainthread);
atexit(printid);
for (i = 0; i < maxproc; ++i) {
char name[64];
SDL_snprintf(name, sizeof (name), "Worker%d", i);
if ((threads[i] = SDL_CreateThread(Run, name, NULL)) == NULL)
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create thread!\n");
}
signal(SIGINT, terminate);
Run(NULL);
return (0); /* Never reached */
}
SDL_ThreadID
#define SDL_ThreadID
Definition: SDL_dynapi_overrides.h:475
SDL_LockMutex
#define SDL_LockMutex
Definition: SDL_dynapi_overrides.h:260
SDL_GetError
#define SDL_GetError
Definition: SDL_dynapi_overrides.h:113
SDL_atomic_t
A type representing an atomic integer value. It is a struct so people don&#39;t accidentally use numeric ...
Definition: SDL_atomic.h:198
SDL_CreateMutex
#define SDL_CreateMutex
Definition: SDL_dynapi_overrides.h:259
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
printid
void printid(void)
Definition: testlock.c:39
mutex
static SDL_mutex * mutex
Definition: testlock.c:23
main
int main(int argc, char *argv[])
Definition: testlock.c:93
name
GLuint const GLchar * name
Definition: SDL_opengl_glext.h:660
SDL_mutex
Definition: SDL_sysmutex.c:29
SDL_LogError
#define SDL_LogError
Definition: SDL_dynapi_overrides.h:36
SDL_Log
#define SDL_Log
Definition: SDL_dynapi_overrides.h:31
Run
int Run(void *data)
Definition: testlock.c:65
closemutex
void closemutex(int sig)
Definition: testlock.c:52
SDL_Quit
#define SDL_Quit
Definition: SDL_dynapi_overrides.h:58
SDL_LOG_PRIORITY_INFO
Definition: SDL_log.h:106
SDL_CreateThread
#define SDL_CreateThread
Definition: SDL_dynapi_overrides.h:41
SDL_Delay
#define SDL_Delay
Definition: SDL_dynapi_overrides.h:486
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
SDL_LogSetPriority
#define SDL_LogSetPriority
Definition: SDL_dynapi_overrides.h:236
NULL
#define NULL
Definition: begin_code.h:164
threads
static SDL_Thread * threads[6]
Definition: testlock.c:25
SDL_DestroyMutex
#define SDL_DestroyMutex
Definition: SDL_dynapi_overrides.h:263
SDL_AtomicSet
#define SDL_AtomicSet
Definition: SDL_dynapi_overrides.h:67
terminate
void terminate(int sig)
Definition: testlock.c:45
SDL_AtomicGet
#define SDL_AtomicGet
Definition: SDL_dynapi_overrides.h:68
SDL_snprintf
#define SDL_snprintf
Definition: SDL_dynapi_overrides.h:40
SDL_Thread
Definition: SDL_thread_c.h:54
SDL_UnlockMutex
#define SDL_UnlockMutex
Definition: SDL_dynapi_overrides.h:262
SDL_Init
#define SDL_Init
Definition: SDL_dynapi_overrides.h:54
SDL_Quit_Wrapper
static void SDL_Quit_Wrapper(void)
Definition: testlock.c:33
SDL.h
doterminate
static SDL_atomic_t doterminate
Definition: testlock.c:26
SDLCALL
#define SDLCALL
Definition: SDL_internal.h:45
SDL_LOG_CATEGORY_APPLICATION
Definition: SDL_log.h:66
SDL_threadID
unsigned long SDL_threadID
Definition: SDL_thread.h:49
SDL_WaitThread
#define SDL_WaitThread
Definition: SDL_dynapi_overrides.h:478
mainthread
static SDL_threadID mainthread
Definition: testlock.c:24