src/thread/os2/SDL_syssem.c
author Sam Lantinga <slouken@libsdl.org>
Thu, 16 Feb 2006 10:11:48 +0000
changeset 1361 19418e4422cb
parent 1358 c71e05b4dc2e
child 1402 d910939febfa
permissions -rw-r--r--
New configure-based build system. Still work in progress, but much improved
icculus@1190
     1
/*
icculus@1190
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
icculus@1190
     4
icculus@1190
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
icculus@1190
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
icculus@1190
     9
icculus@1190
    10
    This library is distributed in the hope that it will be useful,
icculus@1190
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
icculus@1190
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
icculus@1190
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
icculus@1190
    18
icculus@1190
    19
    Sam Lantinga
icculus@1190
    20
    slouken@libsdl.org
icculus@1190
    21
*/
icculus@1190
    22
icculus@1190
    23
/* Semaphore functions using the OS/2 API */
icculus@1190
    24
icculus@1190
    25
#define INCL_DOS
icculus@1190
    26
#define INCL_DOSERRORS
icculus@1190
    27
#define INCL_DOSSEMAPHORES
icculus@1190
    28
#include <os2.h>
icculus@1190
    29
icculus@1190
    30
#include "SDL_thread.h"
icculus@1190
    31
#include "SDL_timer.h"
icculus@1190
    32
icculus@1190
    33
icculus@1190
    34
struct SDL_semaphore {
icculus@1190
    35
        HMTX id;
icculus@1190
    36
        HEV  changed;
icculus@1190
    37
        Uint32 value;
icculus@1190
    38
};
icculus@1190
    39
icculus@1190
    40
icculus@1190
    41
/* Create a semaphore */
icculus@1190
    42
DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value)
icculus@1190
    43
{
icculus@1190
    44
        SDL_sem *sem;
icculus@1190
    45
        ULONG ulrc;
icculus@1190
    46
icculus@1190
    47
        /* Allocate sem memory */
slouken@1336
    48
        sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
icculus@1190
    49
        if ( sem ) {
icculus@1190
    50
                /* Create the mutex semaphore */
icculus@1190
    51
                ulrc = DosCreateMutexSem(NULL,&(sem->id),0,TRUE);
icculus@1190
    52
                if ( ulrc ) {
icculus@1190
    53
                        SDL_SetError("Couldn't create semaphore");
slouken@1336
    54
                        SDL_free(sem);
icculus@1190
    55
                        sem = NULL;
icculus@1190
    56
                } else
icculus@1190
    57
                {
icculus@1190
    58
                    DosCreateEventSem(NULL, &(sem->changed), 0, FALSE);
icculus@1190
    59
                    sem->value = initial_value;
icculus@1190
    60
                    DosReleaseMutexSem(sem->id);
icculus@1190
    61
                }
icculus@1190
    62
        } else {
icculus@1190
    63
                SDL_OutOfMemory();
icculus@1190
    64
        }
icculus@1190
    65
        return(sem);
icculus@1190
    66
}
icculus@1190
    67
icculus@1190
    68
/* Free the semaphore */
icculus@1190
    69
DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem)
icculus@1190
    70
{
icculus@1190
    71
        if ( sem ) {
icculus@1190
    72
                if ( sem->id ) {
icculus@1190
    73
                        DosCloseEventSem(sem->changed);
icculus@1190
    74
                        DosCloseMutexSem(sem->id);
icculus@1190
    75
                        sem->id = 0;
icculus@1190
    76
                }
slouken@1336
    77
                SDL_free(sem);
icculus@1190
    78
        }
icculus@1190
    79
}
icculus@1190
    80
icculus@1190
    81
DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
icculus@1190
    82
{
icculus@1190
    83
        ULONG ulrc;
icculus@1190
    84
icculus@1190
    85
        if ( ! sem ) {
icculus@1190
    86
                SDL_SetError("Passed a NULL sem");
icculus@1190
    87
                return -1;
icculus@1190
    88
        }
icculus@1190
    89
icculus@1190
    90
        if ( timeout == SDL_MUTEX_MAXWAIT ) {
icculus@1190
    91
           while (1) {
icculus@1190
    92
              ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
icculus@1190
    93
              if (ulrc) {
icculus@1190
    94
                 /* if error waiting mutex */
icculus@1190
    95
                 SDL_SetError("DosRequestMutexSem() failed");
icculus@1190
    96
                 return -1;
icculus@1190
    97
              } else if (sem->value) {
icculus@1190
    98
                        sem->value--;
icculus@1190
    99
                        DosReleaseMutexSem(sem->id);
icculus@1190
   100
                        return 0;
icculus@1190
   101
                     } else {
icculus@1190
   102
                        ULONG ulPostCount;
icculus@1190
   103
                        DosResetEventSem(sem->changed, &ulPostCount);
icculus@1190
   104
                        DosReleaseMutexSem(sem->id);
icculus@1190
   105
                        /* continue waiting until somebody posts the semaphore */
icculus@1190
   106
                        DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT);
icculus@1190
   107
                     }
icculus@1190
   108
           }
icculus@1190
   109
        } else
icculus@1190
   110
        if ( timeout == 0 )
icculus@1190
   111
        {
icculus@1190
   112
            ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
icculus@1190
   113
            if (ulrc==NO_ERROR)
icculus@1190
   114
            {
icculus@1190
   115
                if (sem->value)
icculus@1190
   116
                {
icculus@1190
   117
                    sem->value--;
icculus@1190
   118
                    DosReleaseMutexSem(sem->id);
icculus@1190
   119
                    return 0;
icculus@1190
   120
                } else
icculus@1190
   121
                {
icculus@1190
   122
                    DosReleaseMutexSem(sem->id);
icculus@1190
   123
                    return SDL_MUTEX_TIMEDOUT;
icculus@1190
   124
                }
icculus@1190
   125
            } else
icculus@1190
   126
            {
icculus@1190
   127
                SDL_SetError("DosRequestMutexSem() failed");
icculus@1190
   128
                return -1;
icculus@1190
   129
            }
icculus@1190
   130
        } else {
icculus@1190
   131
            ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
icculus@1190
   132
            if (ulrc) {
icculus@1190
   133
               /* if error waiting mutex */
icculus@1190
   134
               SDL_SetError("DosRequestMutexSem() failed");
icculus@1190
   135
               return -1;
icculus@1190
   136
            } else
icculus@1190
   137
              if (sem->value) {
icculus@1190
   138
                sem->value--;
icculus@1190
   139
                DosReleaseMutexSem(sem->id);
icculus@1190
   140
                return 0;
icculus@1190
   141
              } else {
icculus@1190
   142
                ULONG ulPostCount;
icculus@1190
   143
                DosResetEventSem(sem->changed, &ulPostCount);
icculus@1190
   144
                DosReleaseMutexSem(sem->id);
icculus@1190
   145
                /* continue waiting until somebody posts the semaphore */
icculus@1190
   146
                ulrc = DosWaitEventSem(sem->changed, timeout);
icculus@1190
   147
                if (ulrc==NO_ERROR)
icculus@1190
   148
                  return 0;
icculus@1190
   149
                else
icculus@1190
   150
                  return SDL_MUTEX_TIMEDOUT;
icculus@1190
   151
              }
icculus@1190
   152
        }
icculus@1190
   153
        /* never reached */
icculus@1190
   154
        return -1;
icculus@1190
   155
}
icculus@1190
   156
icculus@1190
   157
DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem)
icculus@1190
   158
{
icculus@1190
   159
        return SDL_SemWaitTimeout(sem, 0);
icculus@1190
   160
}
icculus@1190
   161
icculus@1190
   162
DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem)
icculus@1190
   163
{
icculus@1190
   164
        return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
icculus@1190
   165
}
icculus@1190
   166
icculus@1190
   167
/* Returns the current count of the semaphore */
icculus@1190
   168
DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem)
icculus@1190
   169
{
icculus@1190
   170
        if ( ! sem ) {
icculus@1190
   171
                SDL_SetError("Passed a NULL sem");
icculus@1190
   172
                return 0;
icculus@1190
   173
        }
icculus@1190
   174
        return sem->value;
icculus@1190
   175
}
icculus@1190
   176
icculus@1190
   177
DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem)
icculus@1190
   178
{
icculus@1190
   179
        if ( ! sem ) {
icculus@1190
   180
                SDL_SetError("Passed a NULL sem");
icculus@1190
   181
                return -1;
icculus@1190
   182
        }
icculus@1190
   183
        if ( DosRequestMutexSem(sem->id,SEM_INDEFINITE_WAIT) ) {
icculus@1190
   184
                SDL_SetError("DosRequestMutexSem() failed");
icculus@1190
   185
                return -1;
icculus@1190
   186
        }
icculus@1190
   187
        sem->value++;
icculus@1190
   188
        DosPostEventSem(sem->changed);
icculus@1190
   189
        DosReleaseMutexSem(sem->id);
icculus@1190
   190
        return 0;
icculus@1190
   191
}