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

流媒体/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_syssem.c,v 1.4 2002/04/22 21:38:03 wmay Exp $";
  21. #endif
  22. #include <stdlib.h>
  23. #include "SDL_error.h"
  24. #include "SDL_thread.h"
  25. #include "SDL_timer.h"
  26. #ifdef linux
  27. /* Look to see if glibc is available, and if so, what version */
  28. #include <features.h>
  29. #if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)
  30. #warning Working around a bug in glibc 2.0 pthreads
  31. #undef SDL_USE_PTHREADS
  32. /* The bug is actually a problem where threads are suspended, but don't
  33.    wake up when the thread manager sends them a signal.  This is a problem
  34.    with thread creation too, but it happens less often. :-/
  35.    We avoid this by using System V IPC for semaphores.
  36.  */
  37. #endif /* glibc 2.0 */
  38. #endif /* linux */
  39. #ifdef SDL_USE_PTHREADS
  40. #ifdef SDL_NO_PTHREAD_SEMAPHORES
  41. #include "generic/SDL_syssem.c"
  42. #else
  43. #include <stdio.h>
  44. #include <stdlib.h>
  45. #include <unistd.h> /* For getpid() */
  46. #include <pthread.h>
  47. #include <semaphore.h>
  48. /* Wrapper around POSIX 1003.1b semaphores */
  49. #ifdef MACOSX
  50. #define USE_NAMED_SEMAPHORES
  51. /* Broken sem_getvalue() in MacOS X Public Beta */
  52. #define BROKEN_SEMGETVALUE
  53. #endif /* MACOSX */
  54. struct SDL_semaphore {
  55. sem_t *sem;
  56. #ifndef USE_NAMED_SEMAPHORES
  57. sem_t sem_data;
  58. #endif
  59. #ifdef BROKEN_SEMGETVALUE
  60. /* This is a little hack for MacOS X -
  61.    It's not thread-safe, but it's better than nothing
  62.  */
  63. int sem_value;
  64. #endif
  65. };
  66. /* Create a semaphore, initialized with value */
  67. SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
  68. {
  69. SDL_sem *sem = (SDL_sem *) malloc(sizeof(SDL_sem));
  70. if ( sem ) {
  71. #ifdef USE_NAMED_SEMAPHORES
  72. static int semnum = 0;
  73. char name[32];
  74. sprintf(name, "/SDL_sem-%d-%4.4d", getpid(), semnum++);
  75. sem->sem = sem_open(name, O_CREAT, 0600, initial_value);
  76. if ( sem->sem == (sem_t *)SEM_FAILED ) {
  77. SDL_SetError("sem_open(%s) failed", name);
  78. free(sem);
  79. sem = NULL;
  80. } else {
  81. sem_unlink(name);
  82. }
  83. #else
  84. if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) {
  85. SDL_SetError("sem_init() failed");
  86. free(sem);
  87. sem = NULL;
  88. } else {
  89. sem->sem = &sem->sem_data;
  90. }
  91. #endif /* USE_NAMED_SEMAPHORES */
  92. #ifdef BROKEN_SEMGETVALUE
  93. if ( sem ) {
  94. sem->sem_value = initial_value;
  95. }
  96. #endif /* BROKEN_SEMGETVALUE */
  97. } else {
  98. SDL_OutOfMemory();
  99. }
  100. return sem;
  101. }
  102. void SDL_DestroySemaphore(SDL_sem *sem)
  103. {
  104. if ( sem ) {
  105. #ifdef USE_NAMED_SEMAPHORES
  106. sem_close(sem->sem);
  107. #else
  108. sem_destroy(sem->sem);
  109. #endif
  110. free(sem);
  111. }
  112. }
  113. int SDL_SemTryWait(SDL_sem *sem)
  114. {
  115. int retval;
  116. if ( ! sem ) {
  117. SDL_SetError("Passed a NULL semaphore");
  118. return -1;
  119. }
  120. retval = SDL_MUTEX_TIMEDOUT;
  121. if ( sem_trywait(sem->sem) == 0 ) {
  122. #ifdef BROKEN_SEMGETVALUE
  123. --sem->sem_value;
  124. #endif
  125. retval = 0;
  126. }
  127. return retval;
  128. }
  129. int SDL_SemWait(SDL_sem *sem)
  130. {
  131. int retval;
  132. if ( ! sem ) {
  133. SDL_SetError("Passed a NULL semaphore");
  134. return -1;
  135. }
  136. #ifdef BROKEN_SEMGETVALUE
  137. --sem->sem_value;
  138. #endif
  139. retval = sem_wait(sem->sem);
  140. if ( retval < 0 ) {
  141. SDL_SetError("sem_wait() failed");
  142. }
  143. return retval;
  144. }
  145. int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
  146. {
  147. int retval;
  148. if ( ! sem ) {
  149. SDL_SetError("Passed a NULL semaphore");
  150. return -1;
  151. }
  152. /* Try the easy cases first */
  153. if ( timeout == 0 ) {
  154. return SDL_SemTryWait(sem);
  155. }
  156. if ( timeout == SDL_MUTEX_MAXWAIT ) {
  157. return SDL_SemWait(sem);
  158. }
  159. /* Ack!  We have to busy wait... */
  160. timeout += SDL_GetTicks();
  161. do {
  162. retval = SDL_SemTryWait(sem);
  163. if ( retval == 0 ) {
  164. break;
  165. }
  166. SDL_Delay(1);
  167. } while ( SDL_GetTicks() < timeout );
  168. return retval;
  169. }
  170. Uint32 SDL_SemValue(SDL_sem *sem)
  171. {
  172. int ret = 0;
  173. if ( sem ) {
  174. #ifdef BROKEN_SEMGETVALUE
  175. ret = sem->sem_value;
  176. #else
  177. sem_getvalue(sem->sem, &ret);
  178. #endif
  179. if ( ret < 0 ) {
  180. ret = 0;
  181. }
  182. }
  183. return (Uint32)ret;
  184. }
  185. int SDL_SemPost(SDL_sem *sem)
  186. {
  187. int retval;
  188. if ( ! sem ) {
  189. SDL_SetError("Passed a NULL semaphore");
  190. return -1;
  191. }
  192. #ifdef BROKEN_SEMGETVALUE
  193. ++sem->sem_value;
  194. #endif
  195. retval = sem_post(sem->sem);
  196. if ( retval < 0 ) {
  197. SDL_SetError("sem_post() failed");
  198. }
  199. return retval;
  200. }
  201. #endif /* NO_PTHREAD_SEMAPHORES */
  202. #else /* System V IPC implementation */
  203. #include <stdio.h>
  204. #include <stdlib.h>
  205. #include <sys/types.h>
  206. #include <sys/ipc.h>
  207. #include <sys/sem.h>
  208. #include <errno.h>
  209. #include "SDL_error.h"
  210. #include "SDL_thread.h"
  211. struct SDL_semaphore {
  212. int id;
  213. };
  214. /* Not defined by many operating systems, use configure to detect */
  215. #if !defined(HAVE_SEMUN)
  216. union semun {
  217. int val;
  218. struct semid_ds *buf;
  219. ushort *array;
  220. };
  221. #endif
  222. static struct sembuf op_trywait[2] = {
  223. { 0, -1, (IPC_NOWAIT|SEM_UNDO) } /* Decrement semaphore, no block */
  224. };
  225. static struct sembuf op_wait[2] = {
  226. { 0, -1, SEM_UNDO } /* Decrement semaphore */
  227. };
  228. static struct sembuf op_post[1] = {
  229. { 0, 1, (IPC_NOWAIT|SEM_UNDO) } /* Increment semaphore */
  230. };
  231. /* Create a blockable semaphore */
  232. SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
  233. {
  234. extern int _creating_thread_lock; /* SDL_threads.c */
  235. SDL_sem *sem;
  236. union semun init;
  237. key_t key;
  238. sem = (SDL_sem *)malloc(sizeof(*sem));
  239. if ( sem == NULL ) {
  240. SDL_OutOfMemory();
  241. return(NULL);
  242. }
  243. /* This flag is true if we are creating the thread manager sem,
  244.    which is never freed.  This allows us to reuse the same sem.
  245. */
  246. if ( _creating_thread_lock ) {
  247. key = 'S'+'D'+'L';
  248. } else {
  249. key = IPC_PRIVATE;
  250. }
  251. /* Keep trying to create sem while we don't own the requested key */
  252. do {
  253. if ( key != IPC_PRIVATE ) {
  254. ++key;
  255. }
  256. sem->id = semget(key, 1, (0600|IPC_CREAT));
  257. } while ((sem->id < 0) && (key != IPC_PRIVATE) && (errno == EACCES));
  258. /* Report the error if we eventually failed */
  259. if ( sem->id < 0 ) {
  260. SDL_SetError("Couldn't create semaphore");
  261. free(sem);
  262. return(NULL);
  263. }
  264. init.val = initial_value; /* Initialize semaphore */
  265. semctl(sem->id, 0, SETVAL, init);
  266. return(sem);
  267. }
  268. void SDL_DestroySemaphore(SDL_sem *sem)
  269. {
  270. if ( sem ) {
  271. #ifdef _SGI_SOURCE
  272. semctl(sem->id, 0, IPC_RMID);
  273. #else
  274. union semun dummy;
  275. dummy.val = 0;
  276. semctl(sem->id, 0, IPC_RMID, dummy);
  277. #endif
  278. free(sem);
  279. }
  280. }
  281. int SDL_SemTryWait(SDL_sem *sem)
  282. {
  283. int retval;
  284. if ( ! sem ) {
  285. SDL_SetError("Passed a NULL semaphore");
  286. return -1;
  287. }
  288. retval = 0;
  289.   tryagain:
  290. if ( semop(sem->id, op_trywait, 1) < 0 ) {
  291. if ( errno == EINTR ) {
  292. goto tryagain;
  293. }
  294. retval = SDL_MUTEX_TIMEDOUT;
  295. }
  296. return retval;
  297. }
  298. int SDL_SemWait(SDL_sem *sem)
  299. {
  300. int retval;
  301. if ( ! sem ) {
  302. SDL_SetError("Passed a NULL semaphore");
  303. return -1;
  304. }
  305. retval = 0;
  306.   tryagain:
  307. if ( semop(sem->id, op_wait, 1) < 0 ) {
  308. if ( errno == EINTR ) {
  309. goto tryagain;
  310. }
  311. SDL_SetError("Semaphore operation error");
  312. retval = -1;
  313. }
  314. return retval;
  315. }
  316. int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
  317. {
  318. int retval;
  319. if ( ! sem ) {
  320. SDL_SetError("Passed a NULL semaphore");
  321. return -1;
  322. }
  323. /* Try the easy cases first */
  324. if ( timeout == 0 ) {
  325. return SDL_SemTryWait(sem);
  326. }
  327. if ( timeout == SDL_MUTEX_MAXWAIT ) {
  328. return SDL_SemWait(sem);
  329. }
  330. /* Ack!  We have to busy wait... */
  331. timeout += SDL_GetTicks();
  332. do {
  333. retval = SDL_SemTryWait(sem);
  334. if ( retval == 0 ) {
  335. break;
  336. }
  337. SDL_Delay(1);
  338. } while ( SDL_GetTicks() < timeout );
  339. return retval;
  340. }
  341. Uint32 SDL_SemValue(SDL_sem *sem)
  342. {
  343. int semval;
  344. Uint32 value;
  345. value = 0;
  346. if ( sem ) {
  347.   tryagain:
  348. #ifdef _SGI_SOURCE
  349. semval = semctl(sem->id, 0, GETVAL);
  350. #else
  351. {
  352. union semun arg;
  353. arg.val = 0;
  354. semval = semctl(sem->id, 0, GETVAL, arg);
  355. }
  356. #endif
  357. if ( semval < 0 ) {
  358. if ( errno == EINTR ) {
  359. goto tryagain;
  360. }
  361. } else {
  362. value = (Uint32)semval;
  363. }
  364. }
  365. return value;
  366. }
  367. int SDL_SemPost(SDL_sem *sem)
  368. {
  369. int retval;
  370. if ( ! sem ) {
  371. SDL_SetError("Passed a NULL semaphore");
  372. return -1;
  373. }
  374. retval = 0;
  375.   tryagain:
  376. if ( semop(sem->id, op_post, 1) < 0 ) {
  377. if ( errno == EINTR ) {
  378. goto tryagain;
  379. }
  380. SDL_SetError("Semaphore operation error");
  381. retval = -1;
  382. }
  383. return retval;
  384. }
  385. #endif /* SDL_USE_PTHREADS */