winport.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #ifdef WIN32
  19. #include "winport.h"
  20. #include <stdlib.h>
  21. #include <stdint.h> /* for int64_t */
  22. #include <winsock2.h> /* must always be included before ws2tcpip.h */
  23. #include <ws2tcpip.h> /* for SOCKET */
  24. int pthread_mutex_lock(pthread_mutex_t* _mutex ){
  25. int rc = WaitForSingleObject( *_mutex, // handle to mutex
  26. INFINITE); // no time-out interval
  27. return ((rc == WAIT_OBJECT_0) ? 0: rc);
  28. }
  29. int pthread_mutex_unlock( pthread_mutex_t* _mutex ){
  30. int rc = ReleaseMutex(*_mutex);
  31. return ((rc != 0)? 0: GetLastError());
  32. }
  33. int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr){
  34. //use CreateMutex as we are using the HANDLES in pthread_cond
  35. *_mutex = CreateMutex(
  36. NULL, // default security attributes
  37. FALSE, // initially not owned
  38. NULL); // unnamed mutex
  39. return ((*_mutex == NULL) ? GetLastError() : 0);
  40. }
  41. int pthread_mutex_destroy(pthread_mutex_t* _mutex)
  42. {
  43. int rc = CloseHandle(*_mutex);
  44. return ((rc != 0)? 0: GetLastError());
  45. }
  46. int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg)
  47. {
  48. int _intThreadId;
  49. (*thread).thread_handle = (HANDLE)_beginthreadex( NULL, 0, start_routine , arg, 0, (unsigned int*)&_intThreadId );
  50. (*thread).thread_id = _intThreadId;
  51. return (((*thread).thread_handle == 0 ) ? errno : 0 );
  52. }
  53. int pthread_equal(pthread_t t1, pthread_t t2){
  54. //Is there a better way to do this? GetThreadId(handle) is only supported Windows 2003 n above.
  55. return ((t1.thread_id == t2.thread_id) ? 1:0);
  56. }
  57. pthread_t pthread_self(){
  58. pthread_t thread_self;
  59. thread_self.thread_handle = GetCurrentThread();
  60. thread_self.thread_id = GetCurrentThreadId();
  61. return thread_self;
  62. }
  63. int pthread_join(pthread_t _thread, void** ignore)
  64. {
  65. int rc = WaitForSingleObject( _thread.thread_handle, INFINITE );
  66. return ((rc == WAIT_OBJECT_0) ? 0: rc);
  67. }
  68. int pthread_detach(pthread_t _thread)
  69. {
  70. int rc = CloseHandle(_thread.thread_handle) ;
  71. return (rc != 0) ? 0: GetLastError();
  72. }
  73. void pthread_mutexattr_init(pthread_mutexattr_t* ignore){}
  74. void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore){}
  75. void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr){}
  76. int
  77. pthread_cond_init (pthread_cond_t *cv,
  78. const pthread_condattr_t * ignore)
  79. {
  80. cv->waiters_count_ = 0;
  81. cv->was_broadcast_ = 0;
  82. cv->sema_ = CreateSemaphore (NULL, // no security
  83. 0, // initially 0
  84. 0x7fffffff, // max count
  85. NULL); // unnamed
  86. if (cv->sema_ == NULL )
  87. return GetLastError();
  88. InitializeCriticalSection (&cv->waiters_count_lock_);
  89. cv->waiters_done_ = CreateEvent (NULL, // no security
  90. FALSE, // auto-reset
  91. FALSE, // non-signaled initially
  92. NULL); // unnamed
  93. return (cv->waiters_done_ == NULL) ? GetLastError() : 0;
  94. }
  95. int pthread_cond_destroy(pthread_cond_t *cond)
  96. {
  97. CloseHandle( cond->sema_);
  98. DeleteCriticalSection(&cond->waiters_count_lock_);
  99. return (CloseHandle( cond->waiters_done_ ) == 0)? GetLastError(): 0 ;
  100. }
  101. int
  102. pthread_cond_signal (pthread_cond_t *cv)
  103. {
  104. int have_waiters;
  105. EnterCriticalSection (& (cv->waiters_count_lock_));
  106. have_waiters = cv->waiters_count_ > 0;
  107. LeaveCriticalSection (&cv->waiters_count_lock_);
  108. // If there aren't any waiters, then this is a no-op.
  109. if (have_waiters){
  110. return (ReleaseSemaphore (cv->sema_, 1, 0) == 0 ) ? GetLastError() : 0 ;
  111. }else
  112. return 0;
  113. }
  114. int
  115. pthread_cond_broadcast (pthread_cond_t *cv)
  116. {
  117. // This is needed to ensure that <waiters_count_> and <was_broadcast_> are
  118. // consistent relative to each other.
  119. int have_waiters = 0;
  120. EnterCriticalSection (&cv->waiters_count_lock_);
  121. if (cv->waiters_count_ > 0) {
  122. // We are broadcasting, even if there is just one waiter...
  123. // Record that we are broadcasting, which helps optimize
  124. // <pthread_cond_wait> for the non-broadcast case.
  125. cv->was_broadcast_ = 1;
  126. have_waiters = 1;
  127. }
  128. if (have_waiters) {
  129. // Wake up all the waiters atomically.
  130. ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);
  131. LeaveCriticalSection (&cv->waiters_count_lock_);
  132. // Wait for all the awakened threads to acquire the counting
  133. // semaphore.
  134. WaitForSingleObject (cv->waiters_done_, INFINITE);
  135. // This assignment is okay, even without the <waiters_count_lock_> held
  136. // because no other waiter threads can wake up to access it.
  137. cv->was_broadcast_ = 0;
  138. }
  139. else
  140. LeaveCriticalSection (&cv->waiters_count_lock_);
  141. }
  142. int
  143. pthread_cond_wait (pthread_cond_t *cv,
  144. pthread_mutex_t *external_mutex)
  145. {
  146. int last_waiter;
  147. // Avoid race conditions.
  148. EnterCriticalSection (&cv->waiters_count_lock_);
  149. cv->waiters_count_++;
  150. LeaveCriticalSection (&cv->waiters_count_lock_);
  151. // This call atomically releases the mutex and waits on the
  152. // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
  153. // are called by another thread.
  154. SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE);
  155. // Reacquire lock to avoid race conditions.
  156. EnterCriticalSection (&cv->waiters_count_lock_);
  157. // We're no longer waiting...
  158. cv->waiters_count_--;
  159. // Check to see if we're the last waiter after <pthread_cond_broadcast>.
  160. last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
  161. LeaveCriticalSection (&cv->waiters_count_lock_);
  162. // If we're the last waiter thread during this particular broadcast
  163. // then let all the other threads proceed.
  164. if (last_waiter)
  165. // This call atomically signals the <waiters_done_> event and waits until
  166. // it can acquire the <external_mutex>. This is required to ensure fairness.
  167. SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE);
  168. else
  169. // Always regain the external mutex since that's the guarantee we
  170. // give to our callers.
  171. WaitForSingleObject (*external_mutex, INFINITE);
  172. }
  173. int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) )
  174. {
  175. int result = 0;
  176. pthread_key_t* newkey;
  177. if ((newkey = (pthread_key_t*) calloc (1, sizeof (pthread_key_t))) == NULL)
  178. {
  179. result = ENOMEM;
  180. }
  181. else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES)
  182. {
  183. result = EAGAIN;
  184. free (newkey);
  185. newkey = NULL;
  186. }
  187. else if (destructor != NULL)
  188. {
  189. //--we have to store the function pointer for destructor, so that we can call it
  190. //--to free up the user allocated storage--
  191. newkey->destructor = destructor;
  192. }
  193. key = newkey;
  194. return (result);
  195. }
  196. int pthread_key_delete(pthread_key_t key)
  197. {
  198. int rc = 0;
  199. LPVOID lpvData = TlsGetValue(key.key);
  200. rc = TlsFree (key.key);
  201. rc = (rc != 0 ) ? 0 : GetLastError();
  202. if (key.destructor != NULL && lpvData != 0){
  203. key.destructor(lpvData); //we take control of calling destructor, instead of calling it on thread exit.
  204. }
  205. free (&key);
  206. return (rc);
  207. }
  208. void *pthread_getspecific(pthread_key_t key)
  209. {
  210. LPVOID lpvData = TlsGetValue(key.key);
  211. if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
  212. return NULL;
  213. else
  214. return lpvData;
  215. }
  216. int pthread_setspecific(pthread_key_t key, const void *value)
  217. {
  218. int rc = TlsSetValue (key.key, value);
  219. return ((rc != 0 ) ? 0 : GetLastError());
  220. }
  221. int gettimeofday(struct timeval *tp, void *tzp) {
  222. int64_t now = 0;
  223. if (tzp != 0) { errno = EINVAL; return -1; }
  224. GetSystemTimeAsFileTime( (LPFILETIME)&now );
  225. tp->tv_sec = (long)(now / 10000000 - 11644473600LL);
  226. tp->tv_usec = (now / 10) % 1000000;
  227. return 0;
  228. }
  229. int close(SOCKET fd) {
  230. return closesocket(fd);
  231. }
  232. int Win32WSAStartup()
  233. {
  234. WORD wVersionRq;
  235. WSADATA wsaData;
  236. int err;
  237. wVersionRq = MAKEWORD(2,0);
  238. err = WSAStartup(wVersionRq, &wsaData);
  239. if (err != 0)
  240. return 1;
  241. // confirm the version information
  242. if ((LOBYTE(wsaData.wVersion) != 2) ||
  243. (HIBYTE(wsaData.wVersion) != 0))
  244. {
  245. Win32WSACleanup();
  246. return 1;
  247. }
  248. return 0;
  249. }
  250. void Win32WSACleanup()
  251. {
  252. WSACleanup();
  253. }
  254. double drand48(void)
  255. {
  256. return (double)(rand()) / RAND_MAX;
  257. }
  258. #endif //WIN32