105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Locking in multithreaded situations. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 2005-2012 Free Software Foundation, Inc. 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software; you can redistribute it and/or modify 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang it under the terms of the GNU General Public License as published by 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang the Free Software Foundation; either version 3, or (at your option) 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang any later version. 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang GNU General Public License for more details. 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang along with this program; if not, see <http://www.gnu.org/licenses/>. */ 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Written by Bruno Haible <bruno@clisp.org>, 2005. 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h, 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang gthr-win32.h. */ 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h> 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "glthread/lock.h" 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ========================================================================= */ 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_POSIX_THREADS 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* -------------------------- gl_lock_t datatype -------------------------- */ 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ------------------------- gl_rwlock_t datatype ------------------------- */ 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_PTHREAD_RWLOCK 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if !defined PTHREAD_RWLOCK_INITIALIZER 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_init_multithreaded (gl_rwlock_t *lock) 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_rwlock_init (&lock->rwlock, NULL); 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->initialized = 1; 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_lock (&lock->guard); 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = glthread_rwlock_init_multithreaded (lock); 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->guard); 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_unlock (&lock->guard); 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_rwlock_rdlock (&lock->rwlock); 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_lock (&lock->guard); 8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = glthread_rwlock_init_multithreaded (lock); 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->guard); 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_unlock (&lock->guard); 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_rwlock_wrlock (&lock->rwlock); 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_rwlock_unlock (&lock->rwlock); 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_rwlock_destroy (&lock->rwlock); 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->initialized = 0; 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_init_multithreaded (gl_rwlock_t *lock) 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_init (&lock->lock, NULL); 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_cond_init (&lock->waiting_readers, NULL); 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_cond_init (&lock->waiting_writers, NULL); 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->waiting_writers_count = 0; 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount = 0; 14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 14605436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 14705436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock) 14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_lock (&lock->lock); 15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Test whether only readers are currently running, and whether the runcount 15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang field will not overflow. */ 15605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* POSIX says: "It is implementation-defined whether the calling thread 15705436638acc7c010349a69c3395f1a57c642dc62Ying Wang acquires the lock when a writer does not hold the lock and there are 15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang writers blocked on the lock." Let's say, no: give the writers a higher 15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang priority. */ 16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0)) 16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread has to wait for a while. Enqueue it among the 16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang waiting_readers. */ 16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_cond_wait (&lock->waiting_readers, &lock->lock); 16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->lock); 16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount++; 17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_mutex_unlock (&lock->lock); 17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 17505436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 17605436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock) 17705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 17805436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_lock (&lock->lock); 18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Test whether no readers or writers are currently running. */ 18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!(lock->runcount == 0)) 18505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread has to wait for a while. Enqueue it among the 18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang waiting_writers. */ 18805436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->waiting_writers_count++; 18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_cond_wait (&lock->waiting_writers, &lock->lock); 19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 19105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 19205436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->waiting_writers_count--; 19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->lock); 19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->waiting_writers_count--; 19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount--; /* runcount becomes -1 */ 19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_mutex_unlock (&lock->lock); 20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 20205436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 20305436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock) 20405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 20505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_lock (&lock->lock); 20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->runcount < 0) 21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Drop a writer lock. */ 21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(lock->runcount == -1)) 21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->lock); 21605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 21705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 21805436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount = 0; 21905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 22105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 22205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Drop a reader lock. */ 22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(lock->runcount > 0)) 22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 22505436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->lock); 22605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount--; 22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 23005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->runcount == 0) 23105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 23205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* POSIX recommends that "write locks shall take precedence over read 23305436638acc7c010349a69c3395f1a57c642dc62Ying Wang locks", to avoid "writer starvation". */ 23405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->waiting_writers_count > 0) 23505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 23605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Wake up one of the waiting writers. */ 23705436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_cond_signal (&lock->waiting_writers); 23805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 23905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 24005436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->lock); 24105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 24205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 24305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 24405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 24505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 24605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Wake up all waiting readers. */ 24705436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_cond_broadcast (&lock->waiting_readers); 24805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 24905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 25005436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->lock); 25105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 25205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 25305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 25405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 25505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_mutex_unlock (&lock->lock); 25605436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 25705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 25805436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 25905436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock) 26005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 26105436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 26205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_destroy (&lock->lock); 26405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 26505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 26605436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_cond_destroy (&lock->waiting_readers); 26705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 26805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 26905436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_cond_destroy (&lock->waiting_writers); 27005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 27305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 27405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 27505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 27605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 27705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* --------------------- gl_recursive_lock_t datatype --------------------- */ 27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 27905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if HAVE_PTHREAD_MUTEX_RECURSIVE 28005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 28105436638acc7c010349a69c3395f1a57c642dc62Ying Wang# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 28205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 28305436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 28405436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) 28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutexattr_t attributes; 28705436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 28805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 28905436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutexattr_init (&attributes); 29005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 29105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 29205436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); 29305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 29405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 29505436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutexattr_destroy (&attributes); 29605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 29705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 29805436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_init (lock, &attributes); 29905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 30005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 30105436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutexattr_destroy (&attributes); 30205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 30305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 30405436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutexattr_destroy (&attributes); 30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 30605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 30805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 31005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else 31105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 31205436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 31305436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) 31405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 31505436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutexattr_t attributes; 31605436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 31705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 31805436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutexattr_init (&attributes); 31905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 32005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 32105436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE); 32205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 32405436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutexattr_destroy (&attributes); 32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 32605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_init (&lock->recmutex, &attributes); 32805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 33005436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutexattr_destroy (&attributes); 33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 33205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 33305436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutexattr_destroy (&attributes); 33405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 33505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->initialized = 1; 33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 34005436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 34105436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) 34205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 34305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 34605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 34705436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_lock (&lock->guard); 34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 35005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 35105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 35205436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = glthread_recursive_lock_init_multithreaded (lock); 35305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 35405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 35505436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_mutex_unlock (&lock->guard); 35605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 35705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 35805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 35905436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_unlock (&lock->guard); 36005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 36105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 36205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 36305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_mutex_lock (&lock->recmutex); 36405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 36505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 36605436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 36705436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) 36805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 36905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 37005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 37105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_mutex_unlock (&lock->recmutex); 37205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 37305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 37405436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 37505436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) 37605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 37705436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 37805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 37905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->initialized) 38005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 38105436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_destroy (&lock->recmutex); 38205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 38305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 38405436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->initialized = 0; 38505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 38605436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 38705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 38805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 38905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 39005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# else 39105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 39205436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 39305436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) 39405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 39505436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 39605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 39705436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_init (&lock->mutex, NULL); 39805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 39905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 40005436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = (pthread_t) 0; 40105436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->depth = 0; 40205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 40305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 40405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 40505436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 40605436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) 40705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 40805436638acc7c010349a69c3395f1a57c642dc62Ying Wang pthread_t self = pthread_self (); 40905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != self) 41005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 41105436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 41205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 41305436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = pthread_mutex_lock (&lock->mutex); 41405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 41505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 41605436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = self; 41705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 41805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (++(lock->depth) == 0) /* wraparound? */ 41905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 42005436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->depth--; 42105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EAGAIN; 42205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 42305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 42405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 42505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 42605436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 42705436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) 42805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 42905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != pthread_self ()) 43005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EPERM; 43105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->depth == 0) 43205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 43305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (--(lock->depth) == 0) 43405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 43505436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = (pthread_t) 0; 43605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_mutex_unlock (&lock->mutex); 43705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 43805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 43905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 44005436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 44105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 44205436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 44305436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) 44405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 44505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != (pthread_t) 0) 44605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EBUSY; 44705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return pthread_mutex_destroy (&lock->mutex); 44805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 44905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# endif 45105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* -------------------------- gl_once_t datatype -------------------------- */ 45305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic const pthread_once_t fresh_once = PTHREAD_ONCE_INIT; 45505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 45605436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 45705436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_once_singlethreaded (pthread_once_t *once_control) 45805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 45905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* We don't know whether pthread_once_t is an integer type, a floating-point 46005436638acc7c010349a69c3395f1a57c642dc62Ying Wang type, a pointer type, or a structure type. */ 46105436638acc7c010349a69c3395f1a57c642dc62Ying Wang char *firstbyte = (char *)once_control; 46205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*firstbyte == *(const char *)&fresh_once) 46305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 46405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* First time use of once_control. Invert the first byte. */ 46505436638acc7c010349a69c3395f1a57c642dc62Ying Wang *firstbyte = ~ *(const char *)&fresh_once; 46605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 1; 46705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 46805436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 46905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 47005436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 47105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 47205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 47305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 47405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ========================================================================= */ 47505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 47605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_PTH_THREADS 47705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 47805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Use the GNU Pth threads library. */ 47905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 48005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* -------------------------- gl_lock_t datatype -------------------------- */ 48105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 48205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ------------------------- gl_rwlock_t datatype ------------------------- */ 48305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 48405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* --------------------- gl_recursive_lock_t datatype --------------------- */ 48505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 48605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* -------------------------- gl_once_t datatype -------------------------- */ 48705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 48805436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void 48905436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_once_call (void *arg) 49005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 49105436638acc7c010349a69c3395f1a57c642dc62Ying Wang void (**gl_once_temp_addr) (void) = (void (**) (void)) arg; 49205436638acc7c010349a69c3395f1a57c642dc62Ying Wang void (*initfunction) (void) = *gl_once_temp_addr; 49305436638acc7c010349a69c3395f1a57c642dc62Ying Wang initfunction (); 49405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 49505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 49605436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 49705436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void)) 49805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 49905436638acc7c010349a69c3395f1a57c642dc62Ying Wang void (*temp) (void) = initfunction; 50005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0); 50105436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 50205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 50305436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 50405436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_once_singlethreaded (pth_once_t *once_control) 50505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 50605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* We know that pth_once_t is an integer type. */ 50705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (*once_control == PTH_ONCE_INIT) 50805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 50905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* First time use of once_control. Invert the marker. */ 51005436638acc7c010349a69c3395f1a57c642dc62Ying Wang *once_control = ~ PTH_ONCE_INIT; 51105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 1; 51205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 51305436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 51405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 51505436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 51605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 51705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 51805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 51905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ========================================================================= */ 52005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 52105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_SOLARIS_THREADS 52205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 52305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Use the old Solaris threads library. */ 52405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 52505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* -------------------------- gl_lock_t datatype -------------------------- */ 52605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 52705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ------------------------- gl_rwlock_t datatype ------------------------- */ 52805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 52905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* --------------------- gl_recursive_lock_t datatype --------------------- */ 53005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 53105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 53205436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock) 53305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 53405436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 53505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 53605436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = mutex_init (&lock->mutex, USYNC_THREAD, NULL); 53705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 53805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 53905436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = (thread_t) 0; 54005436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->depth = 0; 54105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 54205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 54305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 54405436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 54505436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock) 54605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 54705436638acc7c010349a69c3395f1a57c642dc62Ying Wang thread_t self = thr_self (); 54805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != self) 54905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 55005436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 55105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 55205436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = mutex_lock (&lock->mutex); 55305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 55405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 55505436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = self; 55605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 55705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (++(lock->depth) == 0) /* wraparound? */ 55805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 55905436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->depth--; 56005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EAGAIN; 56105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 56205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 56305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 56405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 56505436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 56605436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock) 56705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 56805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != thr_self ()) 56905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EPERM; 57005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->depth == 0) 57105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 57205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (--(lock->depth) == 0) 57305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 57405436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = (thread_t) 0; 57505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return mutex_unlock (&lock->mutex); 57605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 57705436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 57805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 57905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 58005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 58105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 58205436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock) 58305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 58405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != (thread_t) 0) 58505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EBUSY; 58605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return mutex_destroy (&lock->mutex); 58705436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 58805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 58905436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* -------------------------- gl_once_t datatype -------------------------- */ 59005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 59105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 59205436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void)) 59305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 59405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!once_control->inited) 59505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 59605436638acc7c010349a69c3395f1a57c642dc62Ying Wang int err; 59705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 59805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Use the mutex to guarantee that if another thread is already calling 59905436638acc7c010349a69c3395f1a57c642dc62Ying Wang the initfunction, this thread waits until it's finished. */ 60005436638acc7c010349a69c3395f1a57c642dc62Ying Wang err = mutex_lock (&once_control->mutex); 60105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (err != 0) 60205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return err; 60305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!once_control->inited) 60405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 60505436638acc7c010349a69c3395f1a57c642dc62Ying Wang once_control->inited = 1; 60605436638acc7c010349a69c3395f1a57c642dc62Ying Wang initfunction (); 60705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 60805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return mutex_unlock (&once_control->mutex); 60905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 61005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 61105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 61205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 61305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 61405436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 61505436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_once_singlethreaded (gl_once_t *once_control) 61605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 61705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* We know that gl_once_t contains an integer type. */ 61805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!once_control->inited) 61905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 62005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* First time use of once_control. Invert the marker. */ 62105436638acc7c010349a69c3395f1a57c642dc62Ying Wang once_control->inited = ~ 0; 62205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 1; 62305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 62405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 62505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 62605436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 62705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 62805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 62905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 63005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ========================================================================= */ 63105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 63205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if USE_WINDOWS_THREADS 63305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 63405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* -------------------------- gl_lock_t datatype -------------------------- */ 63505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 63605436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 63705436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_lock_init_func (gl_lock_t *lock) 63805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 63905436638acc7c010349a69c3395f1a57c642dc62Ying Wang InitializeCriticalSection (&lock->lock); 64005436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->guard.done = 1; 64105436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 64205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 64305436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 64405436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_lock_lock_func (gl_lock_t *lock) 64505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 64605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->guard.done) 64705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 64805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (InterlockedIncrement (&lock->guard.started) == 0) 64905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread is the first one to need this lock. Initialize it. */ 65005436638acc7c010349a69c3395f1a57c642dc62Ying Wang glthread_lock_init (lock); 65105436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 65205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Yield the CPU while waiting for another thread to finish 65305436638acc7c010349a69c3395f1a57c642dc62Ying Wang initializing this lock. */ 65405436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!lock->guard.done) 65505436638acc7c010349a69c3395f1a57c642dc62Ying Wang Sleep (0); 65605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 65705436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&lock->lock); 65805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 65905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 66005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 66105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 66205436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_lock_unlock_func (gl_lock_t *lock) 66305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 66405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->guard.done) 66505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 66605436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 66705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 66805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 66905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 67005436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 67105436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_lock_destroy_func (gl_lock_t *lock) 67205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 67305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->guard.done) 67405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 67505436638acc7c010349a69c3395f1a57c642dc62Ying Wang DeleteCriticalSection (&lock->lock); 67605436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->guard.done = 0; 67705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 67805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 67905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 68005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ------------------------- gl_rwlock_t datatype ------------------------- */ 68105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 68205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* In this file, the waitqueues are implemented as circular arrays. */ 68305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define gl_waitqueue_t gl_carray_waitqueue_t 68405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 68505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void 68605436638acc7c010349a69c3395f1a57c642dc62Ying Wanggl_waitqueue_init (gl_waitqueue_t *wq) 68705436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 68805436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->array = NULL; 68905436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->count = 0; 69005436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->alloc = 0; 69105436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->offset = 0; 69205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 69305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 69405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Enqueues the current thread, represented by an event, in a wait queue. 69505436638acc7c010349a69c3395f1a57c642dc62Ying Wang Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */ 69605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic HANDLE 69705436638acc7c010349a69c3395f1a57c642dc62Ying Wanggl_waitqueue_add (gl_waitqueue_t *wq) 69805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 69905436638acc7c010349a69c3395f1a57c642dc62Ying Wang HANDLE event; 70005436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int index; 70105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 70205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (wq->count == wq->alloc) 70305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 70405436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int new_alloc = 2 * wq->alloc + 1; 70505436638acc7c010349a69c3395f1a57c642dc62Ying Wang HANDLE *new_array = 70605436638acc7c010349a69c3395f1a57c642dc62Ying Wang (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE)); 70705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (new_array == NULL) 70805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* No more memory. */ 70905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return INVALID_HANDLE_VALUE; 71005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Now is a good opportunity to rotate the array so that its contents 71105436638acc7c010349a69c3395f1a57c642dc62Ying Wang starts at offset 0. */ 71205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (wq->offset > 0) 71305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 71405436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int old_count = wq->count; 71505436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int old_alloc = wq->alloc; 71605436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int old_offset = wq->offset; 71705436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int i; 71805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (old_offset + old_count > old_alloc) 71905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 72005436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int limit = old_offset + old_count - old_alloc; 72105436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (i = 0; i < limit; i++) 72205436638acc7c010349a69c3395f1a57c642dc62Ying Wang new_array[old_alloc + i] = new_array[i]; 72305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 72405436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (i = 0; i < old_count; i++) 72505436638acc7c010349a69c3395f1a57c642dc62Ying Wang new_array[i] = new_array[old_offset + i]; 72605436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->offset = 0; 72705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 72805436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->array = new_array; 72905436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->alloc = new_alloc; 73005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 73105436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Whether the created event is a manual-reset one or an auto-reset one, 73205436638acc7c010349a69c3395f1a57c642dc62Ying Wang does not matter, since we will wait on it only once. */ 73305436638acc7c010349a69c3395f1a57c642dc62Ying Wang event = CreateEvent (NULL, TRUE, FALSE, NULL); 73405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (event == INVALID_HANDLE_VALUE) 73505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* No way to allocate an event. */ 73605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return INVALID_HANDLE_VALUE; 73705436638acc7c010349a69c3395f1a57c642dc62Ying Wang index = wq->offset + wq->count; 73805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (index >= wq->alloc) 73905436638acc7c010349a69c3395f1a57c642dc62Ying Wang index -= wq->alloc; 74005436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->array[index] = event; 74105436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->count++; 74205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return event; 74305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 74405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 74505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Notifies the first thread from a wait queue and dequeues it. */ 74605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void 74705436638acc7c010349a69c3395f1a57c642dc62Ying Wanggl_waitqueue_notify_first (gl_waitqueue_t *wq) 74805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 74905436638acc7c010349a69c3395f1a57c642dc62Ying Wang SetEvent (wq->array[wq->offset + 0]); 75005436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->offset++; 75105436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->count--; 75205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (wq->count == 0 || wq->offset == wq->alloc) 75305436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->offset = 0; 75405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 75505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 75605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Notifies all threads from a wait queue and dequeues them all. */ 75705436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void 75805436638acc7c010349a69c3395f1a57c642dc62Ying Wanggl_waitqueue_notify_all (gl_waitqueue_t *wq) 75905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 76005436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int i; 76105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 76205436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (i = 0; i < wq->count; i++) 76305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 76405436638acc7c010349a69c3395f1a57c642dc62Ying Wang unsigned int index = wq->offset + i; 76505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (index >= wq->alloc) 76605436638acc7c010349a69c3395f1a57c642dc62Ying Wang index -= wq->alloc; 76705436638acc7c010349a69c3395f1a57c642dc62Ying Wang SetEvent (wq->array[index]); 76805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 76905436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->count = 0; 77005436638acc7c010349a69c3395f1a57c642dc62Ying Wang wq->offset = 0; 77105436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 77205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 77305436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 77405436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_init_func (gl_rwlock_t *lock) 77505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 77605436638acc7c010349a69c3395f1a57c642dc62Ying Wang InitializeCriticalSection (&lock->lock); 77705436638acc7c010349a69c3395f1a57c642dc62Ying Wang gl_waitqueue_init (&lock->waiting_readers); 77805436638acc7c010349a69c3395f1a57c642dc62Ying Wang gl_waitqueue_init (&lock->waiting_writers); 77905436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount = 0; 78005436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->guard.done = 1; 78105436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 78205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 78305436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 78405436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_rdlock_func (gl_rwlock_t *lock) 78505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 78605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->guard.done) 78705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 78805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (InterlockedIncrement (&lock->guard.started) == 0) 78905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread is the first one to need this lock. Initialize it. */ 79005436638acc7c010349a69c3395f1a57c642dc62Ying Wang glthread_rwlock_init (lock); 79105436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 79205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Yield the CPU while waiting for another thread to finish 79305436638acc7c010349a69c3395f1a57c642dc62Ying Wang initializing this lock. */ 79405436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!lock->guard.done) 79505436638acc7c010349a69c3395f1a57c642dc62Ying Wang Sleep (0); 79605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 79705436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&lock->lock); 79805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Test whether only readers are currently running, and whether the runcount 79905436638acc7c010349a69c3395f1a57c642dc62Ying Wang field will not overflow. */ 80005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(lock->runcount + 1 > 0)) 80105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 80205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread has to wait for a while. Enqueue it among the 80305436638acc7c010349a69c3395f1a57c642dc62Ying Wang waiting_readers. */ 80405436638acc7c010349a69c3395f1a57c642dc62Ying Wang HANDLE event = gl_waitqueue_add (&lock->waiting_readers); 80505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (event != INVALID_HANDLE_VALUE) 80605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 80705436638acc7c010349a69c3395f1a57c642dc62Ying Wang DWORD result; 80805436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 80905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Wait until another thread signals this event. */ 81005436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = WaitForSingleObject (event, INFINITE); 81105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (result == WAIT_FAILED || result == WAIT_TIMEOUT) 81205436638acc7c010349a69c3395f1a57c642dc62Ying Wang abort (); 81305436638acc7c010349a69c3395f1a57c642dc62Ying Wang CloseHandle (event); 81405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The thread which signalled the event already did the bookkeeping: 81505436638acc7c010349a69c3395f1a57c642dc62Ying Wang removed us from the waiting_readers, incremented lock->runcount. */ 81605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(lock->runcount > 0)) 81705436638acc7c010349a69c3395f1a57c642dc62Ying Wang abort (); 81805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 81905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 82005436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 82105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 82205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Allocation failure. Weird. */ 82305436638acc7c010349a69c3395f1a57c642dc62Ying Wang do 82405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 82505436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 82605436638acc7c010349a69c3395f1a57c642dc62Ying Wang Sleep (1); 82705436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&lock->lock); 82805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 82905436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!(lock->runcount + 1 > 0)); 83005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 83105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 83205436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount++; 83305436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 83405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 83505436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 83605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 83705436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 83805436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_wrlock_func (gl_rwlock_t *lock) 83905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 84005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->guard.done) 84105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 84205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (InterlockedIncrement (&lock->guard.started) == 0) 84305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread is the first one to need this lock. Initialize it. */ 84405436638acc7c010349a69c3395f1a57c642dc62Ying Wang glthread_rwlock_init (lock); 84505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 84605436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Yield the CPU while waiting for another thread to finish 84705436638acc7c010349a69c3395f1a57c642dc62Ying Wang initializing this lock. */ 84805436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!lock->guard.done) 84905436638acc7c010349a69c3395f1a57c642dc62Ying Wang Sleep (0); 85005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 85105436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&lock->lock); 85205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Test whether no readers or writers are currently running. */ 85305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(lock->runcount == 0)) 85405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 85505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread has to wait for a while. Enqueue it among the 85605436638acc7c010349a69c3395f1a57c642dc62Ying Wang waiting_writers. */ 85705436638acc7c010349a69c3395f1a57c642dc62Ying Wang HANDLE event = gl_waitqueue_add (&lock->waiting_writers); 85805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (event != INVALID_HANDLE_VALUE) 85905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 86005436638acc7c010349a69c3395f1a57c642dc62Ying Wang DWORD result; 86105436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 86205436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Wait until another thread signals this event. */ 86305436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = WaitForSingleObject (event, INFINITE); 86405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (result == WAIT_FAILED || result == WAIT_TIMEOUT) 86505436638acc7c010349a69c3395f1a57c642dc62Ying Wang abort (); 86605436638acc7c010349a69c3395f1a57c642dc62Ying Wang CloseHandle (event); 86705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The thread which signalled the event already did the bookkeeping: 86805436638acc7c010349a69c3395f1a57c642dc62Ying Wang removed us from the waiting_writers, set lock->runcount = -1. */ 86905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(lock->runcount == -1)) 87005436638acc7c010349a69c3395f1a57c642dc62Ying Wang abort (); 87105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 87205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 87305436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 87405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 87505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Allocation failure. Weird. */ 87605436638acc7c010349a69c3395f1a57c642dc62Ying Wang do 87705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 87805436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 87905436638acc7c010349a69c3395f1a57c642dc62Ying Wang Sleep (1); 88005436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&lock->lock); 88105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 88205436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!(lock->runcount == 0)); 88305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 88405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 88505436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount--; /* runcount becomes -1 */ 88605436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 88705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 88805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 88905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 89005436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 89105436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_unlock_func (gl_rwlock_t *lock) 89205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 89305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->guard.done) 89405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 89505436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&lock->lock); 89605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->runcount < 0) 89705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 89805436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Drop a writer lock. */ 89905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(lock->runcount == -1)) 90005436638acc7c010349a69c3395f1a57c642dc62Ying Wang abort (); 90105436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount = 0; 90205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 90305436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 90405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 90505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Drop a reader lock. */ 90605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(lock->runcount > 0)) 90705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 90805436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 90905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EPERM; 91005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 91105436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount--; 91205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 91305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->runcount == 0) 91405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 91505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* POSIX recommends that "write locks shall take precedence over read 91605436638acc7c010349a69c3395f1a57c642dc62Ying Wang locks", to avoid "writer starvation". */ 91705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->waiting_writers.count > 0) 91805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 91905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Wake up one of the waiting writers. */ 92005436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount--; 92105436638acc7c010349a69c3395f1a57c642dc62Ying Wang gl_waitqueue_notify_first (&lock->waiting_writers); 92205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 92305436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 92405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 92505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Wake up all waiting readers. */ 92605436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->runcount += lock->waiting_readers.count; 92705436638acc7c010349a69c3395f1a57c642dc62Ying Wang gl_waitqueue_notify_all (&lock->waiting_readers); 92805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 92905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 93005436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 93105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 93205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 93305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 93405436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 93505436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_rwlock_destroy_func (gl_rwlock_t *lock) 93605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 93705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->guard.done) 93805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 93905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->runcount != 0) 94005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EBUSY; 94105436638acc7c010349a69c3395f1a57c642dc62Ying Wang DeleteCriticalSection (&lock->lock); 94205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->waiting_readers.array != NULL) 94305436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (lock->waiting_readers.array); 94405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->waiting_writers.array != NULL) 94505436638acc7c010349a69c3395f1a57c642dc62Ying Wang free (lock->waiting_writers.array); 94605436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->guard.done = 0; 94705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 94805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 94905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 95005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* --------------------- gl_recursive_lock_t datatype --------------------- */ 95105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 95205436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 95305436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_init_func (gl_recursive_lock_t *lock) 95405436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 95505436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = 0; 95605436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->depth = 0; 95705436638acc7c010349a69c3395f1a57c642dc62Ying Wang InitializeCriticalSection (&lock->lock); 95805436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->guard.done = 1; 95905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 96005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 96105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 96205436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_lock_func (gl_recursive_lock_t *lock) 96305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 96405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!lock->guard.done) 96505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 96605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (InterlockedIncrement (&lock->guard.started) == 0) 96705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread is the first one to need this lock. Initialize it. */ 96805436638acc7c010349a69c3395f1a57c642dc62Ying Wang glthread_recursive_lock_init (lock); 96905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 97005436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Yield the CPU while waiting for another thread to finish 97105436638acc7c010349a69c3395f1a57c642dc62Ying Wang initializing this lock. */ 97205436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (!lock->guard.done) 97305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Sleep (0); 97405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 97505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 97605436638acc7c010349a69c3395f1a57c642dc62Ying Wang DWORD self = GetCurrentThreadId (); 97705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != self) 97805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 97905436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&lock->lock); 98005436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = self; 98105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 98205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (++(lock->depth) == 0) /* wraparound? */ 98305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 98405436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->depth--; 98505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EAGAIN; 98605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 98705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 98805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 98905436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 99005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 99105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 99205436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock) 99305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 99405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != GetCurrentThreadId ()) 99505436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EPERM; 99605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->depth == 0) 99705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EINVAL; 99805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (--(lock->depth) == 0) 99905436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 100005436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->owner = 0; 100105436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&lock->lock); 100205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 100305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 100405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 100505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 100605436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 100705436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock) 100805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 100905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (lock->owner != 0) 101005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return EBUSY; 101105436638acc7c010349a69c3395f1a57c642dc62Ying Wang DeleteCriticalSection (&lock->lock); 101205436638acc7c010349a69c3395f1a57c642dc62Ying Wang lock->guard.done = 0; 101305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 101405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 101505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 101605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* -------------------------- gl_once_t datatype -------------------------- */ 101705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 101805436638acc7c010349a69c3395f1a57c642dc62Ying Wangvoid 101905436638acc7c010349a69c3395f1a57c642dc62Ying Wangglthread_once_func (gl_once_t *once_control, void (*initfunction) (void)) 102005436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 102105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (once_control->inited <= 0) 102205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 102305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (InterlockedIncrement (&once_control->started) == 0) 102405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 102505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* This thread is the first one to come to this once_control. */ 102605436638acc7c010349a69c3395f1a57c642dc62Ying Wang InitializeCriticalSection (&once_control->lock); 102705436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&once_control->lock); 102805436638acc7c010349a69c3395f1a57c642dc62Ying Wang once_control->inited = 0; 102905436638acc7c010349a69c3395f1a57c642dc62Ying Wang initfunction (); 103005436638acc7c010349a69c3395f1a57c642dc62Ying Wang once_control->inited = 1; 103105436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&once_control->lock); 103205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 103305436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 103405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 103505436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Undo last operation. */ 103605436638acc7c010349a69c3395f1a57c642dc62Ying Wang InterlockedDecrement (&once_control->started); 103705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Some other thread has already started the initialization. 103805436638acc7c010349a69c3395f1a57c642dc62Ying Wang Yield the CPU while waiting for the other thread to finish 103905436638acc7c010349a69c3395f1a57c642dc62Ying Wang initializing and taking the lock. */ 104005436638acc7c010349a69c3395f1a57c642dc62Ying Wang while (once_control->inited < 0) 104105436638acc7c010349a69c3395f1a57c642dc62Ying Wang Sleep (0); 104205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (once_control->inited <= 0) 104305436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 104405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Take the lock. This blocks until the other thread has 104505436638acc7c010349a69c3395f1a57c642dc62Ying Wang finished calling the initfunction. */ 104605436638acc7c010349a69c3395f1a57c642dc62Ying Wang EnterCriticalSection (&once_control->lock); 104705436638acc7c010349a69c3395f1a57c642dc62Ying Wang LeaveCriticalSection (&once_control->lock); 104805436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (!(once_control->inited > 0)) 104905436638acc7c010349a69c3395f1a57c642dc62Ying Wang abort (); 105005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 105105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 105205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 105305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 105405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 105505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 105605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 105705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* ========================================================================= */ 1058