123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #ifdef WIN32
- #include "winport.h"
- #include <stdlib.h>
- #include <stdint.h> /* for int64_t */
- #include <winsock2.h> /* must always be included before ws2tcpip.h */
- #include <ws2tcpip.h> /* for SOCKET */
- int pthread_mutex_lock(pthread_mutex_t* _mutex ){
- int rc = WaitForSingleObject( *_mutex, // handle to mutex
- INFINITE); // no time-out interval
- return ((rc == WAIT_OBJECT_0) ? 0: rc);
- }
- int pthread_mutex_unlock( pthread_mutex_t* _mutex ){
- int rc = ReleaseMutex(*_mutex);
- return ((rc != 0)? 0: GetLastError());
- }
- int pthread_mutex_init(pthread_mutex_t* _mutex, void* ignoredAttr){
- //use CreateMutex as we are using the HANDLES in pthread_cond
- *_mutex = CreateMutex(
- NULL, // default security attributes
- FALSE, // initially not owned
- NULL); // unnamed mutex
- return ((*_mutex == NULL) ? GetLastError() : 0);
- }
- int pthread_mutex_destroy(pthread_mutex_t* _mutex)
- {
- int rc = CloseHandle(*_mutex);
- return ((rc != 0)? 0: GetLastError());
- }
- int pthread_create(pthread_t *thread, const pthread_attr_t *attr, unsigned (__stdcall* start_routine)(void* a), void *arg)
- {
- int _intThreadId;
- (*thread).thread_handle = (HANDLE)_beginthreadex( NULL, 0, start_routine , arg, 0, (unsigned int*)&_intThreadId );
- (*thread).thread_id = _intThreadId;
- return (((*thread).thread_handle == 0 ) ? errno : 0 );
- }
- int pthread_equal(pthread_t t1, pthread_t t2){
- //Is there a better way to do this? GetThreadId(handle) is only supported Windows 2003 n above.
- return ((t1.thread_id == t2.thread_id) ? 1:0);
- }
- pthread_t pthread_self(){
- pthread_t thread_self;
- thread_self.thread_handle = GetCurrentThread();
- thread_self.thread_id = GetCurrentThreadId();
- return thread_self;
- }
- int pthread_join(pthread_t _thread, void** ignore)
- {
- int rc = WaitForSingleObject( _thread.thread_handle, INFINITE );
- return ((rc == WAIT_OBJECT_0) ? 0: rc);
- }
- int pthread_detach(pthread_t _thread)
- {
- int rc = CloseHandle(_thread.thread_handle) ;
- return (rc != 0) ? 0: GetLastError();
- }
- void pthread_mutexattr_init(pthread_mutexattr_t* ignore){}
- void pthread_mutexattr_settype(pthread_mutexattr_t* ingore_attr, int ignore){}
- void pthread_mutexattr_destroy(pthread_mutexattr_t* ignore_attr){}
-
- int
- pthread_cond_init (pthread_cond_t *cv,
- const pthread_condattr_t * ignore)
- {
- cv->waiters_count_ = 0;
- cv->was_broadcast_ = 0;
- cv->sema_ = CreateSemaphore (NULL, // no security
- 0, // initially 0
- 0x7fffffff, // max count
- NULL); // unnamed
- if (cv->sema_ == NULL )
- return GetLastError();
- InitializeCriticalSection (&cv->waiters_count_lock_);
- cv->waiters_done_ = CreateEvent (NULL, // no security
- FALSE, // auto-reset
- FALSE, // non-signaled initially
- NULL); // unnamed
- return (cv->waiters_done_ == NULL) ? GetLastError() : 0;
-
- }
- int pthread_cond_destroy(pthread_cond_t *cond)
- {
- CloseHandle( cond->sema_);
- DeleteCriticalSection(&cond->waiters_count_lock_);
- return (CloseHandle( cond->waiters_done_ ) == 0)? GetLastError(): 0 ;
- }
- int
- pthread_cond_signal (pthread_cond_t *cv)
- {
- int have_waiters;
- EnterCriticalSection (& (cv->waiters_count_lock_));
- have_waiters = cv->waiters_count_ > 0;
- LeaveCriticalSection (&cv->waiters_count_lock_);
- // If there aren't any waiters, then this is a no-op.
- if (have_waiters){
- return (ReleaseSemaphore (cv->sema_, 1, 0) == 0 ) ? GetLastError() : 0 ;
- }else
- return 0;
- }
- int
- pthread_cond_broadcast (pthread_cond_t *cv)
- {
- // This is needed to ensure that <waiters_count_> and <was_broadcast_> are
- // consistent relative to each other.
- int have_waiters = 0;
- EnterCriticalSection (&cv->waiters_count_lock_);
-
- if (cv->waiters_count_ > 0) {
- // We are broadcasting, even if there is just one waiter...
- // Record that we are broadcasting, which helps optimize
- // <pthread_cond_wait> for the non-broadcast case.
- cv->was_broadcast_ = 1;
- have_waiters = 1;
- }
- if (have_waiters) {
- // Wake up all the waiters atomically.
- ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);
- LeaveCriticalSection (&cv->waiters_count_lock_);
- // Wait for all the awakened threads to acquire the counting
- // semaphore.
- WaitForSingleObject (cv->waiters_done_, INFINITE);
- // This assignment is okay, even without the <waiters_count_lock_> held
- // because no other waiter threads can wake up to access it.
- cv->was_broadcast_ = 0;
- }
- else
- LeaveCriticalSection (&cv->waiters_count_lock_);
- }
- int
- pthread_cond_wait (pthread_cond_t *cv,
- pthread_mutex_t *external_mutex)
- {
- int last_waiter;
- // Avoid race conditions.
- EnterCriticalSection (&cv->waiters_count_lock_);
- cv->waiters_count_++;
- LeaveCriticalSection (&cv->waiters_count_lock_);
- // This call atomically releases the mutex and waits on the
- // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
- // are called by another thread.
- SignalObjectAndWait (*external_mutex, cv->sema_, INFINITE, FALSE);
- // Reacquire lock to avoid race conditions.
- EnterCriticalSection (&cv->waiters_count_lock_);
- // We're no longer waiting...
- cv->waiters_count_--;
- // Check to see if we're the last waiter after <pthread_cond_broadcast>.
- last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
- LeaveCriticalSection (&cv->waiters_count_lock_);
- // If we're the last waiter thread during this particular broadcast
- // then let all the other threads proceed.
- if (last_waiter)
- // This call atomically signals the <waiters_done_> event and waits until
- // it can acquire the <external_mutex>. This is required to ensure fairness.
- SignalObjectAndWait (cv->waiters_done_, *external_mutex, INFINITE, FALSE);
- else
- // Always regain the external mutex since that's the guarantee we
- // give to our callers.
- WaitForSingleObject (*external_mutex, INFINITE);
- }
- int pthread_key_create(pthread_key_t *key, void (*destructor)(void *) )
- {
- int result = 0;
- pthread_key_t* newkey;
- if ((newkey = (pthread_key_t*) calloc (1, sizeof (pthread_key_t))) == NULL)
- {
- result = ENOMEM;
- }
- else if ((newkey->key = TlsAlloc ()) == TLS_OUT_OF_INDEXES)
- {
- result = EAGAIN;
- free (newkey);
- newkey = NULL;
- }
- else if (destructor != NULL)
- {
- //--we have to store the function pointer for destructor, so that we can call it
- //--to free up the user allocated storage--
- newkey->destructor = destructor;
- }
- key = newkey;
- return (result);
- }
- int pthread_key_delete(pthread_key_t key)
- {
- int rc = 0;
- LPVOID lpvData = TlsGetValue(key.key);
- rc = TlsFree (key.key);
- rc = (rc != 0 ) ? 0 : GetLastError();
- if (key.destructor != NULL && lpvData != 0){
- key.destructor(lpvData); //we take control of calling destructor, instead of calling it on thread exit.
- }
- free (&key);
- return (rc);
- }
- void *pthread_getspecific(pthread_key_t key)
- {
- LPVOID lpvData = TlsGetValue(key.key);
- if ((lpvData == 0) && (GetLastError() != ERROR_SUCCESS))
- return NULL;
- else
- return lpvData;
- }
- int pthread_setspecific(pthread_key_t key, const void *value)
- {
- int rc = TlsSetValue (key.key, value);
- return ((rc != 0 ) ? 0 : GetLastError());
- }
- int gettimeofday(struct timeval *tp, void *tzp) {
- int64_t now = 0;
- if (tzp != 0) { errno = EINVAL; return -1; }
- GetSystemTimeAsFileTime( (LPFILETIME)&now );
- tp->tv_sec = (long)(now / 10000000 - 11644473600LL);
- tp->tv_usec = (now / 10) % 1000000;
- return 0;
- }
- int close(SOCKET fd) {
- return closesocket(fd);
- }
- int Win32WSAStartup()
- {
- WORD wVersionRq;
- WSADATA wsaData;
- int err;
- wVersionRq = MAKEWORD(2,0);
- err = WSAStartup(wVersionRq, &wsaData);
- if (err != 0)
- return 1;
-
- // confirm the version information
- if ((LOBYTE(wsaData.wVersion) != 2) ||
- (HIBYTE(wsaData.wVersion) != 0))
- {
- Win32WSACleanup();
- return 1;
- }
- return 0;
- }
- void Win32WSACleanup()
- {
- WSACleanup();
- }
- double drand48(void)
- {
- return (double)(rand()) / RAND_MAX;
- }
- #endif //WIN32
|