SDL_systhread.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:6k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_systhread.c,v 1.4 2002/04/22 21:38:03 wmay Exp $";
  21. #endif
  22. /* Linux thread management routines for SDL */
  23. #include "SDL_error.h"
  24. #include "SDL_thread.h"
  25. #include "SDL_systhread.h"
  26. #ifdef FORK_HACK
  27. #include <unistd.h>
  28. int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
  29. {
  30. SDL_SetError("Threads are not supported on this platform");
  31. return(-1);
  32. }
  33. void SDL_SYS_SetupThread(void)
  34. {
  35. return;
  36. }
  37. Uint32 SDL_ThreadID(void)
  38. {
  39. return((Uint32)getpid());
  40. }
  41. void SDL_SYS_WaitThread(SDL_Thread *thread)
  42. {
  43. return;
  44. }
  45. void SDL_SYS_KillThread(SDL_Thread *thread)
  46. {
  47. return;
  48. }
  49. #else
  50. #include <signal.h>
  51. #if !defined(MACOSX) /* pthread_sigmask seems to be missing on MacOS X? */
  52. /* List of signals to mask in the subthreads */
  53. static int sig_list[] = {
  54. SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH,
  55. SIGVTALRM, SIGPROF, 0
  56. };
  57. #endif /* !MACOSX */
  58. #ifdef SDL_USE_PTHREADS
  59. #include <pthread.h>
  60. static void *RunThread(void *data)
  61. {
  62. SDL_RunThread(data);
  63. pthread_exit((void*)0);
  64. return((void *)0); /* Prevent compiler warning */
  65. }
  66. int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
  67. {
  68. pthread_attr_t type;
  69. /* Set the thread attributes */
  70. if ( pthread_attr_init(&type) != 0 ) {
  71. SDL_SetError("Couldn't initialize pthread attributes");
  72. return(-1);
  73. }
  74. pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
  75. /* Create the thread and go! */
  76. if ( pthread_create(&thread->handle, &type, RunThread, args) != 0 ) {
  77. SDL_SetError("Not enough resources to create thread");
  78. return(-1);
  79. }
  80. return(0);
  81. }
  82. void SDL_SYS_SetupThread(void)
  83. {
  84. #if !defined(MACOSX) /* pthread_sigmask seems to be missing on MacOS X? */
  85. int i;
  86. sigset_t mask;
  87. /* Mask asynchronous signals for this thread */
  88. sigemptyset(&mask);
  89. for ( i=0; sig_list[i]; ++i ) {
  90. sigaddset(&mask, sig_list[i]);
  91. }
  92. pthread_sigmask(SIG_BLOCK, &mask, 0);
  93. #endif /* !MACOSX */
  94. #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
  95. /* Allow ourselves to be asynchronously cancelled */
  96. { int oldstate;
  97. pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldstate);
  98. }
  99. #endif
  100. }
  101. /* WARNING:  This may not work for systems with 64-bit pid_t */
  102. Uint32 SDL_ThreadID(void)
  103. {
  104. return((Uint32)pthread_self());
  105. }
  106. void SDL_SYS_WaitThread(SDL_Thread *thread)
  107. {
  108. pthread_join(thread->handle, 0);
  109. }
  110. void SDL_SYS_KillThread(SDL_Thread *thread)
  111. {
  112. #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
  113. pthread_cancel(thread->handle);
  114. #else
  115. #ifdef __FreeBSD__
  116. #warning For some reason, this doesnt actually kill a thread - FreeBSD 3.2
  117. #endif
  118. pthread_kill(thread->handle, SIGKILL);
  119. #endif
  120. }
  121. #else /* Linux-specific clone() based implementation */
  122. #include <stdlib.h>
  123. #include <errno.h>
  124. #include <unistd.h>
  125. #include <sys/wait.h>
  126. /* Stack size for child thread */
  127. #define STACKSIZE 16384*4 /* 16384 is too small */
  128. #ifdef __GLIBC__
  129. #include <sched.h>
  130. #else
  131. /* From <linux/sched.h> */
  132. #define CLONE_VM      0x00000100   /* set if VM shared */
  133. #define CLONE_FS      0x00000200   /* set if fs info shared */
  134. #define CLONE_FILES   0x00000400   /* set if open files shared */
  135. #define CLONE_SIGHAND 0x00000800   /* set if signal handlers shared */
  136. #define CLONE_PID     0x00001000   /* set if pid shared */
  137. /* The infamous "start_thread" function, courtesy Linus Torvalds */
  138. extern int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg);
  139. #endif
  140. static int RunThread(void *data)
  141. {
  142. SDL_RunThread(data);
  143. return(0);
  144. }
  145. int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
  146. {
  147. void *stack;
  148. /* Allocate memory for thread stack */
  149. stack = malloc(STACKSIZE);
  150. if ( stack == (void *)0 ) {
  151. SDL_OutOfMemory();
  152. return(-1);
  153. }
  154. thread->data = stack;
  155. /* Adjust the stack since it actually grows down */
  156.         stack = (void *) ((char *)stack + STACKSIZE);
  157. /* Create the thread and go! */
  158. thread->handle = clone(RunThread, stack,
  159. (CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND), args);
  160. if ( thread->handle < 0 ) {
  161. free(thread->data);
  162. SDL_SetError("Not enough resources to create thread");
  163. return(-1);
  164. }
  165. return(0);
  166. }
  167. void SDL_SYS_SetupThread(void)
  168. {
  169. int i;
  170. sigset_t mask;
  171. /* Mask asynchronous signals for this thread */
  172. sigemptyset(&mask);
  173. for ( i=0; sig_list[i]; ++i ) {
  174. sigaddset(&mask, sig_list[i]);
  175. }
  176. sigprocmask(SIG_BLOCK, &mask, 0);
  177. }
  178. /* WARNING:  This may not work for systems with 64-bit pid_t */
  179. Uint32 SDL_ThreadID(void)
  180. {
  181. return((Uint32)getpid());
  182. }
  183. void SDL_SYS_WaitThread(SDL_Thread *thread)
  184. {
  185. #ifdef __WCLONE
  186. errno = 0;
  187. while ( errno != ECHILD ) {
  188. waitpid(thread->handle, 0, __WCLONE);
  189. }
  190. #else
  191. /* Ack, ugly ugly hack --
  192.    wait() doesn't work, waitpid() doesn't work, and ignoring SIG_CHLD
  193.    doesn't work .. and the child thread is still a zombie, so kill()
  194.    doesn't work.
  195. */
  196. char command[1024];
  197. sprintf(command,
  198. "ps ax|fgrep -v fgrep|fgrep -v '<zombie>'|fgrep %d >/dev/null",
  199. thread->handle);
  200. while ( system(command) == 0 )
  201. sleep(1);
  202. #endif
  203. free(thread->data);
  204. }
  205. void SDL_SYS_KillThread(SDL_Thread *thread)
  206. {
  207. kill(thread->handle, SIGKILL);
  208. }
  209. #endif /* SDL_USE_PTHREADS */
  210. #endif /* FORK_HACK */