[SDL] semaphores made from mutexes?

Carsten Griwodz Carsten.Griwodz at KOM.tu-darmstadt.de
Wed Apr 19 13:15:25 PDT 2000


Hi,

I can only provide a version for the pthread interface (attached). I have
never used the semctl interface.

Wouldn't it be appropriate to provide system-specific semaphores? Win32
has a native(?) implementation anyway.

Tschuess,
   Carsten

-------------- next part --------------

/*
 * glibc-check copied from SDL_mutex.c - cg
 */
#ifdef linux
/* Look to see if glibc is available, and if so, what version */
#include <features.h>

#if (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)
#warning Working around a bug in glibc 2.0 pthreads
#undef SDL_USE_PTHREADS
/* The bug is actually a problem where threads are suspended, but don't
   wake up when the thread manager sends them a signal.  This is a problem
   with thread creation too, but it happens less often. :-/
   We avoid this by using System V IPC for mutexes.
*/
#endif /* glibc 2.0 */
#endif /* linux */

#ifdef SDL_USE_PTHREADS

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

#include "SDL_semaphore.h"
#include "SDL_error.h"
#include "SDL_mutex.h"

struct SDL_semaphore
{
    pthread_mutex_t   count_lock;
    pthread_cond_t    wait_cond;
    Uint32            count;
    Uint32            max;
};

SDL_sem *SDL_CreateSemaphore(Uint32 initial_value)
{
    SDL_sem* sem;

    if ( initial_value < 0 ) {
        SDL_SetError("Cannot create semaphore with negative value");
        return(0);
    }

    sem = (SDL_sem *)malloc(sizeof(*sem));
    if ( ! sem ) {
        SDL_OutOfMemory();
        return(0);
    }
    sem->count = initial_value;
    sem->max   = initial_value;
    pthread_mutex_init( &sem->count_lock, NULL );
    pthread_cond_init( &sem->wait_cond, NULL );

    return sem;
}

void SDL_DestroySemaphore(SDL_sem *sem)
{
    Uint32 holding;
    if ( sem )
    {
        holding = 0;
	pthread_mutex_lock( &sem->count_lock );
        while ( holding < sem->max )
	{
	    pthread_cond_wait( &sem->wait_cond, &sem->count_lock );
	    sem->count--;
	    holding++;
	}
	pthread_cond_destroy ( &sem->wait_cond );
	pthread_mutex_unlock( &sem->count_lock );
	pthread_mutex_destroy( &sem->count_lock );
    }
}

void SDL_SemWait(SDL_sem *sem)
{
    SDL_bool must_wait;

    pthread_mutex_lock( &sem->count_lock );
    while ( sem->count <= 0 ) {
        pthread_cond_wait( &sem->wait_cond, &sem->count_lock );
    }
    --sem->count;
    pthread_mutex_unlock( &sem->count_lock );
}

SDL_bool SDL_SemTryWait(SDL_sem *sem)
{
    SDL_bool must_wait;

    pthread_mutex_lock( &sem->count_lock );
    if ( sem->count > 0 ) {
        must_wait = SDL_FALSE;
        --sem->count;
    } else {
        must_wait = SDL_TRUE;
    }
    pthread_mutex_unlock( &sem->count_lock );

    return !must_wait;
}

Uint32 SDL_SemValue(SDL_sem *sem)
{
    Uint32 value;

    pthread_mutex_lock( &sem->count_lock );
    if ( sem->count < 0 ) {
        value = 0;
    } else {
        value = sem->count;
    }
    pthread_mutex_unlock( &sem->count_lock );
    return value;
}

void SDL_SemPost(SDL_sem *sem)
{
    pthread_mutex_lock( &sem->count_lock );
    ++sem->count;
    pthread_cond_signal ( &sem->wait_cond );
    pthread_mutex_unlock( &sem->count_lock );
}

#else

#error sorry I dont know the semctl interface

#endif



More information about the SDL mailing list