src/thread/pthread/SDL_syssem.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 16 Feb 2006 10:11:48 +0000
changeset 1361 19418e4422cb
child 1402 d910939febfa
permissions -rw-r--r--
New configure-based build system. Still work in progress, but much improved
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #include <pthread.h>
    24 #include <semaphore.h>
    25 
    26 #include "SDL_thread.h"
    27 #include "SDL_timer.h"
    28 
    29 /* Wrapper around POSIX 1003.1b semaphores */
    30 
    31 #if MACOSX
    32 #define USE_NAMED_SEMAPHORES 1
    33 #endif /* MACOSX */
    34 
    35 struct SDL_semaphore {
    36 	sem_t *sem;
    37 #if !USE_NAMED_SEMAPHORES
    38 	sem_t sem_data;
    39 #endif
    40 };
    41 
    42 /* Create a semaphore, initialized with value */
    43 SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
    44 {
    45 	SDL_sem *sem = (SDL_sem *) SDL_malloc(sizeof(SDL_sem));
    46 	if ( sem ) {
    47 #if USE_NAMED_SEMAPHORES
    48 		static int semnum = 0;
    49 		char name[32];
    50 
    51 		SDL_snprintf(name, SDL_arraysize(name), "/SDL_sem-%d-%4.4d", getpid(), semnum++);
    52 		sem->sem = sem_open(name, O_CREAT, 0600, initial_value);
    53 		if ( sem->sem == (sem_t *)SEM_FAILED ) {
    54 			SDL_SetError("sem_open(%s) failed", name);
    55 			SDL_free(sem);
    56 			sem = NULL;
    57 		} else {
    58 			sem_unlink(name);
    59 		}
    60 #else
    61 		if ( sem_init(&sem->sem_data, 0, initial_value) < 0 ) {
    62 			SDL_SetError("sem_init() failed");
    63 			SDL_free(sem);
    64 			sem = NULL;
    65 		} else {
    66 			sem->sem = &sem->sem_data;
    67 		}
    68 #endif /* USE_NAMED_SEMAPHORES */
    69 	} else {
    70 		SDL_OutOfMemory();
    71 	}
    72 	return sem;
    73 }
    74 
    75 void SDL_DestroySemaphore(SDL_sem *sem)
    76 {
    77 	if ( sem ) {
    78 #if USE_NAMED_SEMAPHORES
    79 		sem_close(sem->sem);
    80 #else
    81 		sem_destroy(sem->sem);
    82 #endif
    83 		SDL_free(sem);
    84 	}
    85 }
    86 
    87 int SDL_SemTryWait(SDL_sem *sem)
    88 {
    89 	int retval;
    90 
    91 	if ( ! sem ) {
    92 		SDL_SetError("Passed a NULL semaphore");
    93 		return -1;
    94 	}
    95 	retval = SDL_MUTEX_TIMEDOUT;
    96 	if ( sem_trywait(sem->sem) == 0 ) {
    97 		retval = 0;
    98 	}
    99 	return retval;
   100 }
   101 
   102 int SDL_SemWait(SDL_sem *sem)
   103 {
   104 	int retval;
   105 
   106 	if ( ! sem ) {
   107 		SDL_SetError("Passed a NULL semaphore");
   108 		return -1;
   109 	}
   110 
   111 	retval = sem_wait(sem->sem);
   112 	if ( retval < 0 ) {
   113 		SDL_SetError("sem_wait() failed");
   114 	}
   115 	return retval;
   116 }
   117 
   118 int SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
   119 {
   120 	int retval;
   121 
   122 	if ( ! sem ) {
   123 		SDL_SetError("Passed a NULL semaphore");
   124 		return -1;
   125 	}
   126 
   127 	/* Try the easy cases first */
   128 	if ( timeout == 0 ) {
   129 		return SDL_SemTryWait(sem);
   130 	}
   131 	if ( timeout == SDL_MUTEX_MAXWAIT ) {
   132 		return SDL_SemWait(sem);
   133 	}
   134 
   135 	/* Ack!  We have to busy wait... */
   136 	timeout += SDL_GetTicks();
   137 	do {
   138 		retval = SDL_SemTryWait(sem);
   139 		if ( retval == 0 ) {
   140 			break;
   141 		}
   142 		SDL_Delay(1);
   143 	} while ( SDL_GetTicks() < timeout );
   144 
   145 	return retval;
   146 }
   147 
   148 Uint32 SDL_SemValue(SDL_sem *sem)
   149 {
   150 	int ret = 0;
   151 	if ( sem ) {
   152 		sem_getvalue(sem->sem, &ret);
   153 		if ( ret < 0 ) {
   154 			ret = 0;
   155 		}
   156 	}
   157 	return (Uint32)ret;
   158 }
   159 
   160 int SDL_SemPost(SDL_sem *sem)
   161 {
   162 	int retval;
   163 
   164 	if ( ! sem ) {
   165 		SDL_SetError("Passed a NULL semaphore");
   166 		return -1;
   167 	}
   168 
   169 	retval = sem_post(sem->sem);
   170 	if ( retval < 0 ) {
   171 		SDL_SetError("sem_post() failed");
   172 	}
   173 	return retval;
   174 }