146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2006 Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Lesser General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2.1 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Lesser General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Lesser General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free Software
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <pthread.h>
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <signal.h>
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_thread.h"
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_thread_c.h"
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_systhread.h"
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* List of signals to mask in the subthreads */
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int sig_list[] = {
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SIGVTALRM, SIGPROF, 0
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner};
3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef __RISCOS__
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* RISC OS needs to know the main thread for
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * it's timer and event processing. */
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint riscos_using_threads = 0;
4146be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint32 riscos_main_thread = 0; /* Thread running events */
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void *RunThread(void *data)
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_RunThread(data);
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pthread_exit((void*)0);
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return((void *)0);		/* Prevent compiler warning */
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pthread_attr_t type;
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Set the thread attributes */
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( pthread_attr_init(&type) != 0 ) {
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("Couldn't initialize pthread attributes");
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Create the thread and go! */
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( pthread_create(&thread->handle, &type, RunThread, args) != 0 ) {
6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("Not enough resources to create thread");
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef __RISCOS__
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if (riscos_using_threads == 0) {
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		riscos_using_threads = 1;
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		riscos_main_thread = SDL_ThreadID();
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(0);
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_SYS_SetupThread(void)
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	sigset_t mask;
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Mask asynchronous signals for this thread */
8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	sigemptyset(&mask);
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for ( i=0; sig_list[i]; ++i ) {
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		sigaddset(&mask, sig_list[i]);
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pthread_sigmask(SIG_BLOCK, &mask, 0);
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Allow ourselves to be asynchronously cancelled */
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{ int oldstate;
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* WARNING:  This may not work for systems with 64-bit pid_t */
10046be48730333120a7b939116cef075e61c12c703David 'Digit' TurnerUint32 SDL_ThreadID(void)
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return((Uint32)pthread_self());
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_SYS_WaitThread(SDL_Thread *thread)
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pthread_join(thread->handle, 0);
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_SYS_KillThread(SDL_Thread *thread)
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pthread_cancel(thread->handle);
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef __FREEBSD__
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#warning For some reason, this doesnt actually kill a thread - FreeBSD 3.2
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	pthread_kill(thread->handle, SIGKILL);
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
121