src/thread/nds/SDL_syscond.c
author Darren Alton <dalton@stevens.edu>
Thu, 12 Jun 2008 02:38:49 +0000
branchgsoc2008_nds
changeset 2671 c3e7c0698cbb
parent 2670 6e4669f4db49
permissions -rw-r--r--
some changes to the dummy driver for debug purposes that should be reverted.
most importantly, commenting out a check for an env. var.
dalton@2670
     1
/*
dalton@2670
     2
    SDL - Simple DirectMedia Layer
dalton@2670
     3
    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
dalton@2670
     4
dalton@2670
     5
    This library is free software; you can redistribute it and/or
dalton@2670
     6
    modify it under the terms of the GNU Library General Public
dalton@2670
     7
    License as published by the Free Software Foundation; either
dalton@2670
     8
    version 2 of the License, or (at your option) any later version.
dalton@2670
     9
dalton@2670
    10
    This library is distributed in the hope that it will be useful,
dalton@2670
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
dalton@2670
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
dalton@2670
    13
    Library General Public License for more details.
dalton@2670
    14
dalton@2670
    15
    You should have received a copy of the GNU Library General Public
dalton@2670
    16
    License along with this library; if not, write to the Free
dalton@2670
    17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
dalton@2670
    18
dalton@2670
    19
    Sam Lantinga
dalton@2670
    20
    slouken@devolution.com
dalton@2670
    21
*/
dalton@2670
    22
dalton@2670
    23
#ifdef SAVE_RCSID
dalton@2670
    24
static char rcsid =
dalton@2671
    25
    "@(#) $Id: SDL_syscond.c,v 1.2 2001/04/26 16:50:18 hercules Exp $";
dalton@2670
    26
#endif
dalton@2670
    27
dalton@2670
    28
/* An implementation of condition variables using semaphores and mutexes */
dalton@2670
    29
/*
dalton@2670
    30
   This implementation borrows heavily from the BeOS condition variable
dalton@2670
    31
   implementation, written by Christopher Tate and Owen Smith.  Thanks!
dalton@2670
    32
 */
dalton@2670
    33
dalton@2670
    34
#include <stdio.h>
dalton@2670
    35
#include <stdlib.h>
dalton@2670
    36
dalton@2670
    37
#include "SDL_error.h"
dalton@2670
    38
#include "SDL_thread.h"
dalton@2670
    39
dalton@2670
    40
struct SDL_cond
dalton@2670
    41
{
dalton@2671
    42
    SDL_mutex *lock;
dalton@2671
    43
    int waiting;
dalton@2671
    44
    int signals;
dalton@2671
    45
    SDL_sem *wait_sem;
dalton@2671
    46
    SDL_sem *wait_done;
dalton@2670
    47
};
dalton@2670
    48
dalton@2670
    49
/* Create a condition variable */
dalton@2671
    50
SDL_cond *
dalton@2671
    51
SDL_CreateCond(void)
dalton@2670
    52
{
dalton@2671
    53
    SDL_cond *cond;
dalton@2670
    54
dalton@2671
    55
    cond = (SDL_cond *) malloc(sizeof(SDL_cond));
dalton@2671
    56
    if (cond) {
dalton@2671
    57
        cond->lock = SDL_CreateMutex();
dalton@2671
    58
        cond->wait_sem = SDL_CreateSemaphore(0);
dalton@2671
    59
        cond->wait_done = SDL_CreateSemaphore(0);
dalton@2671
    60
        cond->waiting = cond->signals = 0;
dalton@2671
    61
        if (!cond->lock || !cond->wait_sem || !cond->wait_done) {
dalton@2671
    62
            SDL_DestroyCond(cond);
dalton@2671
    63
            cond = NULL;
dalton@2671
    64
        }
dalton@2671
    65
    } else {
dalton@2671
    66
        SDL_OutOfMemory();
dalton@2671
    67
    }
dalton@2671
    68
    return (cond);
dalton@2670
    69
}
dalton@2670
    70
dalton@2670
    71
/* Destroy a condition variable */
dalton@2671
    72
void
dalton@2671
    73
SDL_DestroyCond(SDL_cond * cond)
dalton@2670
    74
{
dalton@2671
    75
    if (cond) {
dalton@2671
    76
        if (cond->wait_sem) {
dalton@2671
    77
            SDL_DestroySemaphore(cond->wait_sem);
dalton@2671
    78
        }
dalton@2671
    79
        if (cond->wait_done) {
dalton@2671
    80
            SDL_DestroySemaphore(cond->wait_done);
dalton@2671
    81
        }
dalton@2671
    82
        if (cond->lock) {
dalton@2671
    83
            SDL_DestroyMutex(cond->lock);
dalton@2671
    84
        }
dalton@2671
    85
        free(cond);
dalton@2671
    86
    }
dalton@2670
    87
}
dalton@2670
    88
dalton@2670
    89
/* Restart one of the threads that are waiting on the condition variable */
dalton@2671
    90
int
dalton@2671
    91
SDL_CondSignal(SDL_cond * cond)
dalton@2670
    92
{
dalton@2671
    93
    if (!cond) {
dalton@2671
    94
        SDL_SetError("Passed a NULL condition variable");
dalton@2671
    95
        return -1;
dalton@2671
    96
    }
dalton@2670
    97
dalton@2671
    98
    /* If there are waiting threads not already signalled, then
dalton@2671
    99
       signal the condition and wait for the thread to respond.
dalton@2671
   100
     */
dalton@2671
   101
    SDL_LockMutex(cond->lock);
dalton@2671
   102
    if (cond->waiting > cond->signals) {
dalton@2671
   103
        ++cond->signals;
dalton@2671
   104
        SDL_SemPost(cond->wait_sem);
dalton@2671
   105
        SDL_UnlockMutex(cond->lock);
dalton@2671
   106
        SDL_SemWait(cond->wait_done);
dalton@2671
   107
    } else {
dalton@2671
   108
        SDL_UnlockMutex(cond->lock);
dalton@2671
   109
    }
dalton@2670
   110
dalton@2671
   111
    return 0;
dalton@2670
   112
}
dalton@2670
   113
dalton@2670
   114
/* Restart all threads that are waiting on the condition variable */
dalton@2671
   115
int
dalton@2671
   116
SDL_CondBroadcast(SDL_cond * cond)
dalton@2670
   117
{
dalton@2671
   118
    if (!cond) {
dalton@2671
   119
        SDL_SetError("Passed a NULL condition variable");
dalton@2671
   120
        return -1;
dalton@2671
   121
    }
dalton@2670
   122
dalton@2671
   123
    /* If there are waiting threads not already signalled, then
dalton@2671
   124
       signal the condition and wait for the thread to respond.
dalton@2671
   125
     */
dalton@2671
   126
    SDL_LockMutex(cond->lock);
dalton@2671
   127
    if (cond->waiting > cond->signals) {
dalton@2671
   128
        int i, num_waiting;
dalton@2670
   129
dalton@2671
   130
        num_waiting = (cond->waiting - cond->signals);
dalton@2671
   131
        cond->signals = cond->waiting;
dalton@2671
   132
        for (i = 0; i < num_waiting; ++i) {
dalton@2671
   133
            SDL_SemPost(cond->wait_sem);
dalton@2671
   134
        }
dalton@2671
   135
        /* Now all released threads are blocked here, waiting for us.
dalton@2671
   136
           Collect them all (and win fabulous prizes!) :-)
dalton@2671
   137
         */
dalton@2671
   138
        SDL_UnlockMutex(cond->lock);
dalton@2671
   139
        for (i = 0; i < num_waiting; ++i) {
dalton@2671
   140
            SDL_SemWait(cond->wait_done);
dalton@2671
   141
        }
dalton@2671
   142
    } else {
dalton@2671
   143
        SDL_UnlockMutex(cond->lock);
dalton@2671
   144
    }
dalton@2670
   145
dalton@2671
   146
    return 0;
dalton@2670
   147
}
dalton@2670
   148
dalton@2670
   149
/* Wait on the condition variable for at most 'ms' milliseconds.
dalton@2670
   150
   The mutex must be locked before entering this function!
dalton@2670
   151
   The mutex is unlocked during the wait, and locked again after the wait.
dalton@2670
   152
dalton@2670
   153
Typical use:
dalton@2670
   154
dalton@2670
   155
Thread A:
dalton@2670
   156
	SDL_LockMutex(lock);
dalton@2670
   157
	while ( ! condition ) {
dalton@2670
   158
		SDL_CondWait(cond);
dalton@2670
   159
	}
dalton@2670
   160
	SDL_UnlockMutex(lock);
dalton@2670
   161
dalton@2670
   162
Thread B:
dalton@2670
   163
	SDL_LockMutex(lock);
dalton@2670
   164
	...
dalton@2670
   165
	condition = true;
dalton@2670
   166
	...
dalton@2670
   167
	SDL_UnlockMutex(lock);
dalton@2670
   168
 */
dalton@2671
   169
int
dalton@2671
   170
SDL_CondWaitTimeout(SDL_cond * cond, SDL_mutex * mutex, Uint32 ms)
dalton@2670
   171
{
dalton@2671
   172
    int retval;
dalton@2670
   173
dalton@2671
   174
    if (!cond) {
dalton@2671
   175
        SDL_SetError("Passed a NULL condition variable");
dalton@2671
   176
        return -1;
dalton@2671
   177
    }
dalton@2670
   178
dalton@2671
   179
    /* Obtain the protection mutex, and increment the number of waiters.
dalton@2671
   180
       This allows the signal mechanism to only perform a signal if there
dalton@2671
   181
       are waiting threads.
dalton@2671
   182
     */
dalton@2671
   183
    SDL_LockMutex(cond->lock);
dalton@2671
   184
    ++cond->waiting;
dalton@2671
   185
    SDL_UnlockMutex(cond->lock);
dalton@2670
   186
dalton@2671
   187
    /* Unlock the mutex, as is required by condition variable semantics */
dalton@2671
   188
    SDL_UnlockMutex(mutex);
dalton@2670
   189
dalton@2671
   190
    /* Wait for a signal */
dalton@2671
   191
    if (ms == SDL_MUTEX_MAXWAIT) {
dalton@2671
   192
        retval = SDL_SemWait(cond->wait_sem);
dalton@2671
   193
    } else {
dalton@2671
   194
        retval = SDL_SemWaitTimeout(cond->wait_sem, ms);
dalton@2671
   195
    }
dalton@2670
   196
dalton@2671
   197
    /* Let the signaler know we have completed the wait, otherwise
dalton@2671
   198
       the signaler can race ahead and get the condition semaphore
dalton@2671
   199
       if we are stopped between the mutex unlock and semaphore wait,
dalton@2671
   200
       giving a deadlock.  See the following URL for details:
dalton@2671
   201
       http://www-classic.be.com/aboutbe/benewsletter/volume_III/Issue40.html
dalton@2671
   202
     */
dalton@2671
   203
    SDL_LockMutex(cond->lock);
dalton@2671
   204
    if (cond->signals > 0) {
dalton@2671
   205
        /* If we timed out, we need to eat a condition signal */
dalton@2671
   206
        if (retval > 0) {
dalton@2671
   207
            SDL_SemWait(cond->wait_sem);
dalton@2671
   208
        }
dalton@2671
   209
        /* We always notify the signal thread that we are done */
dalton@2671
   210
        SDL_SemPost(cond->wait_done);
dalton@2670
   211
dalton@2671
   212
        /* Signal handshake complete */
dalton@2671
   213
        --cond->signals;
dalton@2671
   214
    }
dalton@2671
   215
    --cond->waiting;
dalton@2671
   216
    SDL_UnlockMutex(cond->lock);
dalton@2670
   217
dalton@2671
   218
    /* Lock the mutex, as is required by condition variable semantics */
dalton@2671
   219
    SDL_LockMutex(mutex);
dalton@2670
   220
dalton@2671
   221
    return retval;
dalton@2670
   222
}
dalton@2670
   223
dalton@2670
   224
/* Wait on the condition variable forever */
dalton@2671
   225
int
dalton@2671
   226
SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex)
dalton@2670
   227
{
dalton@2671
   228
    return SDL_CondWaitTimeout(cond, mutex, SDL_MUTEX_MAXWAIT);
dalton@2670
   229
}