1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 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 #include <sys/time.h> 25 #include <unistd.h> 26 #include <errno.h> 27 #include <pthread.h> 28 29 #include "SDL_thread.h" 30 #include "SDL_sysmutex_c.h" 31 32 struct SDL_cond 33 { 34 pthread_cond_t cond; 35 }; 36 37 /* Create a condition variable */ 38 SDL_cond * SDL_CreateCond(void) 39 { 40 SDL_cond *cond; 41 42 cond = (SDL_cond *) SDL_malloc(sizeof(SDL_cond)); 43 if ( cond ) { 44 if ( pthread_cond_init(&cond->cond, NULL) < 0 ) { 45 SDL_SetError("pthread_cond_init() failed"); 46 SDL_free(cond); 47 cond = NULL; 48 } 49 } 50 return(cond); 51 } 52 53 /* Destroy a condition variable */ 54 void SDL_DestroyCond(SDL_cond *cond) 55 { 56 if ( cond ) { 57 pthread_cond_destroy(&cond->cond); 58 SDL_free(cond); 59 } 60 } 61 62 /* Restart one of the threads that are waiting on the condition variable */ 63 int SDL_CondSignal(SDL_cond *cond) 64 { 65 int retval; 66 67 if ( ! cond ) { 68 SDL_SetError("Passed a NULL condition variable"); 69 return -1; 70 } 71 72 retval = 0; 73 if ( pthread_cond_signal(&cond->cond) != 0 ) { 74 SDL_SetError("pthread_cond_signal() failed"); 75 retval = -1; 76 } 77 return retval; 78 } 79 80 /* Restart all threads that are waiting on the condition variable */ 81 int SDL_CondBroadcast(SDL_cond *cond) 82 { 83 int retval; 84 85 if ( ! cond ) { 86 SDL_SetError("Passed a NULL condition variable"); 87 return -1; 88 } 89 90 retval = 0; 91 if ( pthread_cond_broadcast(&cond->cond) != 0 ) { 92 SDL_SetError("pthread_cond_broadcast() failed"); 93 retval = -1; 94 } 95 return retval; 96 } 97 98 int SDL_CondWaitTimeout(SDL_cond *cond, SDL_mutex *mutex, Uint32 ms) 99 { 100 int retval; 101 struct timeval delta; 102 struct timespec abstime; 103 104 if ( ! cond ) { 105 SDL_SetError("Passed a NULL condition variable"); 106 return -1; 107 } 108 109 gettimeofday(&delta, NULL); 110 111 abstime.tv_sec = delta.tv_sec + (ms/1000); 112 abstime.tv_nsec = (delta.tv_usec + (ms%1000) * 1000) * 1000; 113 if ( abstime.tv_nsec > 1000000000 ) { 114 abstime.tv_sec += 1; 115 abstime.tv_nsec -= 1000000000; 116 } 117 118 tryagain: 119 retval = pthread_cond_timedwait(&cond->cond, &mutex->id, &abstime); 120 switch (retval) { 121 case EINTR: 122 goto tryagain; 123 break; 124 case ETIMEDOUT: 125 retval = SDL_MUTEX_TIMEDOUT; 126 break; 127 case 0: 128 break; 129 default: 130 SDL_SetError("pthread_cond_timedwait() failed"); 131 retval = -1; 132 break; 133 } 134 return retval; 135 } 136 137 /* Wait on the condition variable, unlocking the provided mutex. 138 The mutex must be locked before entering this function! 139 */ 140 int SDL_CondWait(SDL_cond *cond, SDL_mutex *mutex) 141 { 142 int retval; 143 144 if ( ! cond ) { 145 SDL_SetError("Passed a NULL condition variable"); 146 return -1; 147 } 148 149 retval = 0; 150 if ( pthread_cond_wait(&cond->cond, &mutex->id) != 0 ) { 151 SDL_SetError("pthread_cond_wait() failed"); 152 retval = -1; 153 } 154 return retval; 155 } 156