Home | History | Annotate | Download | only in os2
      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 (at) libsdl.org
     21 */
     22 #include "SDL_config.h"
     23 
     24 /* Semaphore functions using the OS/2 API */
     25 
     26 #define INCL_DOS
     27 #define INCL_DOSERRORS
     28 #define INCL_DOSSEMAPHORES
     29 #include <os2.h>
     30 
     31 #include "SDL_thread.h"
     32 #include "SDL_timer.h"
     33 
     34 
     35 struct SDL_semaphore {
     36         HMTX id;
     37         HEV  changed;
     38         Uint32 value;
     39 };
     40 
     41 
     42 /* Create a semaphore */
     43 DECLSPEC SDL_sem * SDLCALL SDL_CreateSemaphore(Uint32 initial_value)
     44 {
     45         SDL_sem *sem;
     46         ULONG ulrc;
     47 
     48         /* Allocate sem memory */
     49         sem = (SDL_sem *)SDL_malloc(sizeof(*sem));
     50         if ( sem ) {
     51                 /* Create the mutex semaphore */
     52                 ulrc = DosCreateMutexSem(NULL,&(sem->id),0,TRUE);
     53                 if ( ulrc ) {
     54                         SDL_SetError("Couldn't create semaphore");
     55                         SDL_free(sem);
     56                         sem = NULL;
     57                 } else
     58                 {
     59                     DosCreateEventSem(NULL, &(sem->changed), 0, FALSE);
     60                     sem->value = initial_value;
     61                     DosReleaseMutexSem(sem->id);
     62                 }
     63         } else {
     64                 SDL_OutOfMemory();
     65         }
     66         return(sem);
     67 }
     68 
     69 /* Free the semaphore */
     70 DECLSPEC void SDLCALL SDL_DestroySemaphore(SDL_sem *sem)
     71 {
     72         if ( sem ) {
     73                 if ( sem->id ) {
     74                         DosCloseEventSem(sem->changed);
     75                         DosCloseMutexSem(sem->id);
     76                         sem->id = 0;
     77                 }
     78                 SDL_free(sem);
     79         }
     80 }
     81 
     82 DECLSPEC int SDLCALL SDL_SemWaitTimeout(SDL_sem *sem, Uint32 timeout)
     83 {
     84         ULONG ulrc;
     85 
     86         if ( ! sem ) {
     87                 SDL_SetError("Passed a NULL sem");
     88                 return -1;
     89         }
     90 
     91         if ( timeout == SDL_MUTEX_MAXWAIT ) {
     92            while (1) {
     93               ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
     94               if (ulrc) {
     95                  /* if error waiting mutex */
     96                  SDL_SetError("DosRequestMutexSem() failed");
     97                  return -1;
     98               } else if (sem->value) {
     99                         sem->value--;
    100                         DosReleaseMutexSem(sem->id);
    101                         return 0;
    102                      } else {
    103                         ULONG ulPostCount;
    104                         DosResetEventSem(sem->changed, &ulPostCount);
    105                         DosReleaseMutexSem(sem->id);
    106                         /* continue waiting until somebody posts the semaphore */
    107                         DosWaitEventSem(sem->changed, SEM_INDEFINITE_WAIT);
    108                      }
    109            }
    110         } else
    111         if ( timeout == 0 )
    112         {
    113             ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
    114             if (ulrc==NO_ERROR)
    115             {
    116                 if (sem->value)
    117                 {
    118                     sem->value--;
    119                     DosReleaseMutexSem(sem->id);
    120                     return 0;
    121                 } else
    122                 {
    123                     DosReleaseMutexSem(sem->id);
    124                     return SDL_MUTEX_TIMEDOUT;
    125                 }
    126             } else
    127             {
    128                 SDL_SetError("DosRequestMutexSem() failed");
    129                 return -1;
    130             }
    131         } else {
    132             ulrc = DosRequestMutexSem(sem->id, SEM_INDEFINITE_WAIT);
    133             if (ulrc) {
    134                /* if error waiting mutex */
    135                SDL_SetError("DosRequestMutexSem() failed");
    136                return -1;
    137             } else
    138               if (sem->value) {
    139                 sem->value--;
    140                 DosReleaseMutexSem(sem->id);
    141                 return 0;
    142               } else {
    143                 ULONG ulPostCount;
    144                 DosResetEventSem(sem->changed, &ulPostCount);
    145                 DosReleaseMutexSem(sem->id);
    146                 /* continue waiting until somebody posts the semaphore */
    147                 ulrc = DosWaitEventSem(sem->changed, timeout);
    148                 if (ulrc==NO_ERROR)
    149                   return 0;
    150                 else
    151                   return SDL_MUTEX_TIMEDOUT;
    152               }
    153         }
    154         /* never reached */
    155         return -1;
    156 }
    157 
    158 DECLSPEC int SDLCALL SDL_SemTryWait(SDL_sem *sem)
    159 {
    160         return SDL_SemWaitTimeout(sem, 0);
    161 }
    162 
    163 DECLSPEC int SDLCALL SDL_SemWait(SDL_sem *sem)
    164 {
    165         return SDL_SemWaitTimeout(sem, SDL_MUTEX_MAXWAIT);
    166 }
    167 
    168 /* Returns the current count of the semaphore */
    169 DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem *sem)
    170 {
    171         if ( ! sem ) {
    172                 SDL_SetError("Passed a NULL sem");
    173                 return 0;
    174         }
    175         return sem->value;
    176 }
    177 
    178 DECLSPEC int SDLCALL SDL_SemPost(SDL_sem *sem)
    179 {
    180         if ( ! sem ) {
    181                 SDL_SetError("Passed a NULL sem");
    182                 return -1;
    183         }
    184         if ( DosRequestMutexSem(sem->id,SEM_INDEFINITE_WAIT) ) {
    185                 SDL_SetError("DosRequestMutexSem() failed");
    186                 return -1;
    187         }
    188         sem->value++;
    189         DosPostEventSem(sem->changed);
    190         DosReleaseMutexSem(sem->id);
    191         return 0;
    192 }
    193