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

流媒体/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@devolution.com
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_syssem.c,v 1.3 2002/04/22 21:38:02 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 SDL_USE_PTHREADS
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <unistd.h> /* For getpid() */
  30. #include <pthread.h>
  31. /*
  32.  * This is semaphore.h inlined here so that BSD/OS POSIX semaphore are
  33.  * completely selfcontained without requiring any additional include files
  34.  * or libraries not present in the stock system
  35. */
  36. /* semaphore.h: POSIX 1003.1b semaphores */
  37. /*-
  38.  * Copyright (c) 1996, 1997
  39.  * HD Associates, Inc.  All rights reserved.
  40.  *
  41.  * Redistribution and use in source and binary forms, with or without
  42.  * modification, are permitted provided that the following conditions
  43.  * are met:
  44.  * 1. Redistributions of source code must retain the above copyright
  45.  *    notice, this list of conditions and the following disclaimer.
  46.  * 2. Redistributions in binary form must reproduce the above copyright
  47.  *    notice, this list of conditions and the following disclaimer in the
  48.  *    documentation and/or other materials provided with the distribution.
  49.  * 3. All advertising materials mentioning features or use of this software
  50.  *    must display the following acknowledgement:
  51.  * This product includes software developed by HD Associates, Inc
  52.  * 4. Neither the name of the author nor the names of any co-contributors
  53.  *    may be used to endorse or promote products derived from this software
  54.  *    without specific prior written permission.
  55.  *
  56.  * THIS SOFTWARE IS PROVIDED BY HD ASSOCIATES AND CONTRIBUTORS ``AS IS'' AND
  57.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  58.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  59.  * ARE DISCLAIMED.  IN NO EVENT SHALL HD ASSOCIATES OR CONTRIBUTORS BE LIABLE
  60.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  61.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  62.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  63.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  64.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  65.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  66.  * SUCH DAMAGE.
  67.  *
  68.  * $FreeBSD: src/sys/posix4/semaphore.h,v 1.6 2000/01/20 07:55:42 jasone Exp $
  69.  */
  70. #include <machine/limits.h>
  71. #include <sys/types.h>
  72. #include <fcntl.h>
  73. /* Opaque type definition. */
  74. struct sem;
  75. typedef struct sem *sem_t;
  76. #define SEM_FAILED ((sem_t *)0)
  77. #define SEM_VALUE_MAX UINT_MAX
  78. #include <sys/cdefs.h>
  79. __BEGIN_DECLS
  80. int  sem_init __P((sem_t *, int, unsigned int));
  81. int  sem_destroy __P((sem_t *));
  82. sem_t *sem_open __P((const char *, int, ...));
  83. int  sem_close __P((sem_t *));
  84. int  sem_unlink __P((const char *));
  85. int  sem_wait __P((sem_t *));
  86. int  sem_trywait __P((sem_t *));
  87. int  sem_post __P((sem_t *));
  88. int  sem_getvalue __P((sem_t *, int *));
  89. __END_DECLS
  90. /* END of inlined semaphore.h */
  91. /* Wrapper around POSIX 1003.1b semaphores */
  92. struct SDL_semaphore {
  93. sem_t *sem;
  94. sem_t sem_data;
  95. };
  96. /* Create a semaphore, initialized with value */
  97. SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
  98. {
  99. SDL_sem *sem = (SDL_sem *) malloc(sizeof(SDL_sem));
  100. if ( sem ) {
  101. if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) {
  102. SDL_SetError("sem_init() failed");
  103. free(sem);
  104. sem = NULL;
  105. } else {
  106. sem->sem = &sem->sem_data;
  107. }
  108. } else {
  109. SDL_OutOfMemory();
  110. }
  111. return sem;
  112. }
  113. void SDL_DestroySemaphore(SDL_sem *sem)
  114. {
  115. if ( sem ) {
  116. sem_destroy(sem->sem);
  117. free(sem);
  118. }
  119. }
  120. int SDL_SemTryWait(SDL_sem *sem)
  121. {
  122. int retval;
  123. if ( ! sem ) {
  124. SDL_SetError("Passed a NULL semaphore");
  125. return -1;
  126. }
  127. retval = SDL_MUTEX_TIMEDOUT;
  128. if ( sem_trywait(sem->sem) == 0 )
  129. retval = 0;
  130. return retval;
  131. }
  132. int SDL_SemWait(SDL_sem *sem)
  133. {
  134. int retval;
  135. if ( ! sem ) {
  136. SDL_SetError("Passed a NULL semaphore");
  137. return -1;
  138. }
  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. sem_getvalue(sem->sem, &ret);
  175. if ( ret < 0 ) {
  176. ret = 0;
  177. }
  178. }
  179. return (Uint32)ret;
  180. }
  181. int SDL_SemPost(SDL_sem *sem)
  182. {
  183. int retval;
  184. if ( ! sem ) {
  185. SDL_SetError("Passed a NULL semaphore");
  186. return -1;
  187. }
  188. retval = sem_post(sem->sem);
  189. if ( retval < 0 ) {
  190. SDL_SetError("sem_post() failed");
  191. }
  192. return retval;
  193. }
  194. /* 
  195.  * BEGIN inlined uthread_sem.c.  This is done here so that no extra libraries
  196.  * or include files not present in BSD/OS are required
  197. */
  198. /*
  199.  * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
  200.  * All rights reserved.
  201.  * 
  202.  * Redistribution and use in source and binary forms, with or without
  203.  * modification, are permitted provided that the following conditions
  204.  * are met:
  205.  * 1. Redistributions of source code must retain the above copyright
  206.  *    notice(s), this list of conditions and the following disclaimer as
  207.  *    the first lines of this file unmodified other than the possible
  208.  *    addition of one or more copyright notices.
  209.  * 2. Redistributions in binary form must reproduce the above copyright
  210.  *    notice(s), this list of conditions and the following disclaimer in
  211.  *    the documentation and/or other materials provided with the
  212.  *    distribution.
  213.  * 
  214.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
  215.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  216.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  217.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
  218.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  219.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  220.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  221.  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  222.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  223.  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  224.  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  225.  *
  226.  * $FreeBSD: src/lib/libc_r/uthread/uthread_sem.c,v 1.3.2.1 2000/07/18 02:05:57 jasone Exp $
  227.  */
  228. #include <errno.h>
  229. #include <pthread.h>
  230. /* Begin thread_private.h kluge */
  231. /*
  232.  * These come out of (or should go into) thread_private.h - rather than have 
  233.  * to copy (or symlink) the files from the source tree these definitions are 
  234.  * inlined here.  Obviously these go away when this module is part of libc.
  235. */
  236. struct sem {
  237. #define SEM_MAGIC       ((u_int32_t) 0x09fa4012)
  238.         u_int32_t       magic;
  239.         pthread_mutex_t lock;
  240.         pthread_cond_t  gtzero;
  241.         u_int32_t       count;
  242.         u_int32_t       nwaiters;
  243. };
  244. extern pthread_once_t _thread_init_once;
  245. extern int _threads_initialized;
  246. extern void  _thread_init __P((void));
  247. #define THREAD_INIT() 
  248. (void) pthread_once(&_thread_init_once, _thread_init)
  249. #define THREAD_SAFE() 
  250. (_threads_initialized != 0)
  251. #define _SEM_CHECK_VALIDITY(sem)
  252. if ((*(sem))->magic != SEM_MAGIC) {
  253. errno = EINVAL;
  254. retval = -1;
  255. goto RETURN;
  256. }
  257. /* End thread_private.h kluge */
  258. int
  259. sem_init(sem_t *sem, int pshared, unsigned int value)
  260. {
  261. int retval;
  262. if (!THREAD_SAFE())
  263. THREAD_INIT();
  264. /*
  265.  * Range check the arguments.
  266.  */
  267. if (pshared != 0) {
  268. /*
  269.  * The user wants a semaphore that can be shared among
  270.  * processes, which this implementation can't do.  Sounds like a
  271.  * permissions problem to me (yeah right).
  272.  */
  273. errno = EPERM;
  274. retval = -1;
  275. goto RETURN;
  276. }
  277. if (value > SEM_VALUE_MAX) {
  278. errno = EINVAL;
  279. retval = -1;
  280. goto RETURN;
  281. }
  282. *sem = (sem_t)malloc(sizeof(struct sem));
  283. if (*sem == NULL) {
  284. errno = ENOSPC;
  285. retval = -1;
  286. goto RETURN;
  287. }
  288. /*
  289.  * Initialize the semaphore.
  290.  */
  291. if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) {
  292. free(*sem);
  293. errno = ENOSPC;
  294. retval = -1;
  295. goto RETURN;
  296. }
  297. if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) {
  298. pthread_mutex_destroy(&(*sem)->lock);
  299. free(*sem);
  300. errno = ENOSPC;
  301. retval = -1;
  302. goto RETURN;
  303. }
  304. (*sem)->count = (u_int32_t)value;
  305. (*sem)->nwaiters = 0;
  306. (*sem)->magic = SEM_MAGIC;
  307. retval = 0;
  308.   RETURN:
  309. return retval;
  310. }
  311. int
  312. sem_destroy(sem_t *sem)
  313. {
  314. int retval;
  315. _SEM_CHECK_VALIDITY(sem);
  316. /* Make sure there are no waiters. */
  317. pthread_mutex_lock(&(*sem)->lock);
  318. if ((*sem)->nwaiters > 0) {
  319. pthread_mutex_unlock(&(*sem)->lock);
  320. errno = EBUSY;
  321. retval = -1;
  322. goto RETURN;
  323. }
  324. pthread_mutex_unlock(&(*sem)->lock);
  325. pthread_mutex_destroy(&(*sem)->lock);
  326. pthread_cond_destroy(&(*sem)->gtzero);
  327. (*sem)->magic = 0;
  328. free(*sem);
  329. retval = 0;
  330.   RETURN:
  331. return retval;
  332. }
  333. sem_t *
  334. sem_open(const char *name, int oflag, ...)
  335. {
  336. errno = ENOSYS;
  337. return SEM_FAILED;
  338. }
  339. int
  340. sem_close(sem_t *sem)
  341. {
  342. errno = ENOSYS;
  343. return -1;
  344. }
  345. int
  346. sem_unlink(const char *name)
  347. {
  348. errno = ENOSYS;
  349. return -1;
  350. }
  351. int
  352. sem_wait(sem_t *sem)
  353. {
  354. int retval;
  355. pthread_testcancel();
  356. _SEM_CHECK_VALIDITY(sem);
  357. pthread_mutex_lock(&(*sem)->lock);
  358. while ((*sem)->count == 0) {
  359. (*sem)->nwaiters++;
  360. pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock);
  361. (*sem)->nwaiters--;
  362. }
  363. (*sem)->count--;
  364. pthread_mutex_unlock(&(*sem)->lock);
  365. retval = 0;
  366.   RETURN:
  367. pthread_testcancel();
  368. return retval;
  369. }
  370. int
  371. sem_trywait(sem_t *sem)
  372. {
  373. int retval;
  374. _SEM_CHECK_VALIDITY(sem);
  375. pthread_mutex_lock(&(*sem)->lock);
  376. if ((*sem)->count > 0) {
  377. (*sem)->count--;
  378. retval = 0;
  379. } else {
  380. errno = EAGAIN;
  381. retval = -1;
  382. }
  383. pthread_mutex_unlock(&(*sem)->lock);
  384.   RETURN:
  385. return retval;
  386. }
  387. int
  388. sem_post(sem_t *sem)
  389. {
  390. int retval;
  391. _SEM_CHECK_VALIDITY(sem);
  392. pthread_mutex_lock(&(*sem)->lock);
  393. (*sem)->count++;
  394. if ((*sem)->nwaiters > 0) {
  395. /*
  396.  * We must use pthread_cond_broadcast() rather than
  397.  * pthread_cond_signal() in order to assure that the highest
  398.  * priority thread is run by the scheduler, since
  399.  * pthread_cond_signal() signals waiting threads in FIFO order.
  400.  */
  401. pthread_cond_broadcast(&(*sem)->gtzero);
  402. }
  403. pthread_mutex_unlock(&(*sem)->lock);
  404. retval = 0;
  405.   RETURN:
  406. return retval;
  407. }
  408. int
  409. sem_getvalue(sem_t *sem, int *sval)
  410. {
  411. int retval;
  412. _SEM_CHECK_VALIDITY(sem);
  413. pthread_mutex_lock(&(*sem)->lock);
  414. *sval = (int)(*sem)->count;
  415. pthread_mutex_unlock(&(*sem)->lock);
  416. retval = 0;
  417.   RETURN:
  418. return retval;
  419. }
  420. /* END of inlined uthread_sem.c */
  421. #endif /* SDL_USE_PTHREADS */