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