⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lock.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Locking in multithreaded situations.   Copyright (C) 2005-2006 Free Software Foundation, Inc.   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2, or (at your option)   any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software Foundation,   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  *//* Written by Bruno Haible <bruno@clisp.org>, 2005.   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,   gthr-win32.h.  */#include <config.h>#include "lock.h"/* ========================================================================= */#if USE_POSIX_THREADS/* Use the POSIX threads library.  */# if PTHREAD_IN_USE_DETECTION_HARD/* The function to be executed by a dummy thread.  */static void *dummy_thread_func (void *arg){  return arg;}intglthread_in_use (void){  static int tested;  static int result; /* 1: linked with -lpthread, 0: only with libc */  if (!tested)    {      pthread_t thread;      if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0)	/* Thread creation failed.  */	result = 0;      else	{	  /* Thread creation works.  */	  void *retval;	  if (pthread_join (thread, &retval) != 0)	    abort ();	  result = 1;	}      tested = 1;    }  return result;}# endif/* -------------------------- gl_lock_t datatype -------------------------- *//* ------------------------- gl_rwlock_t datatype ------------------------- */# if HAVE_PTHREAD_RWLOCK#  if !defined PTHREAD_RWLOCK_INITIALIZERvoidglthread_rwlock_init (gl_rwlock_t *lock){  if (pthread_rwlock_init (&lock->rwlock, NULL) != 0)    abort ();  lock->initialized = 1;}voidglthread_rwlock_rdlock (gl_rwlock_t *lock){  if (!lock->initialized)    {      if (pthread_mutex_lock (&lock->guard) != 0)	abort ();      if (!lock->initialized)	glthread_rwlock_init (lock);      if (pthread_mutex_unlock (&lock->guard) != 0)	abort ();    }  if (pthread_rwlock_rdlock (&lock->rwlock) != 0)    abort ();}voidglthread_rwlock_wrlock (gl_rwlock_t *lock){  if (!lock->initialized)    {      if (pthread_mutex_lock (&lock->guard) != 0)	abort ();      if (!lock->initialized)	glthread_rwlock_init (lock);      if (pthread_mutex_unlock (&lock->guard) != 0)	abort ();    }  if (pthread_rwlock_wrlock (&lock->rwlock) != 0)    abort ();}voidglthread_rwlock_unlock (gl_rwlock_t *lock){  if (!lock->initialized)    abort ();  if (pthread_rwlock_unlock (&lock->rwlock) != 0)    abort ();}voidglthread_rwlock_destroy (gl_rwlock_t *lock){  if (!lock->initialized)    abort ();  if (pthread_rwlock_destroy (&lock->rwlock) != 0)    abort ();  lock->initialized = 0;}#  endif# elsevoidglthread_rwlock_init (gl_rwlock_t *lock){  if (pthread_mutex_init (&lock->lock, NULL) != 0)    abort ();  if (pthread_cond_init (&lock->waiting_readers, NULL) != 0)    abort ();  if (pthread_cond_init (&lock->waiting_writers, NULL) != 0)    abort ();  lock->waiting_writers_count = 0;  lock->runcount = 0;}voidglthread_rwlock_rdlock (gl_rwlock_t *lock){  if (pthread_mutex_lock (&lock->lock) != 0)    abort ();  /* Test whether only readers are currently running, and whether the runcount     field will not overflow.  */  /* POSIX says: "It is implementation-defined whether the calling thread     acquires the lock when a writer does not hold the lock and there are     writers blocked on the lock."  Let's say, no: give the writers a higher     priority.  */  while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))    {      /* This thread has to wait for a while.  Enqueue it among the	 waiting_readers.  */      if (pthread_cond_wait (&lock->waiting_readers, &lock->lock) != 0)	abort ();    }  lock->runcount++;  if (pthread_mutex_unlock (&lock->lock) != 0)    abort ();}voidglthread_rwlock_wrlock (gl_rwlock_t *lock){  if (pthread_mutex_lock (&lock->lock) != 0)    abort ();  /* Test whether no readers or writers are currently running.  */  while (!(lock->runcount == 0))    {      /* This thread has to wait for a while.  Enqueue it among the	 waiting_writers.  */      lock->waiting_writers_count++;      if (pthread_cond_wait (&lock->waiting_writers, &lock->lock) != 0)	abort ();      lock->waiting_writers_count--;    }  lock->runcount--; /* runcount becomes -1 */  if (pthread_mutex_unlock (&lock->lock) != 0)    abort ();}voidglthread_rwlock_unlock (gl_rwlock_t *lock){  if (pthread_mutex_lock (&lock->lock) != 0)    abort ();  if (lock->runcount < 0)    {      /* Drop a writer lock.  */      if (!(lock->runcount == -1))	abort ();      lock->runcount = 0;    }  else    {      /* Drop a reader lock.  */      if (!(lock->runcount > 0))	abort ();      lock->runcount--;    }  if (lock->runcount == 0)    {      /* POSIX recommends that "write locks shall take precedence over read	 locks", to avoid "writer starvation".  */      if (lock->waiting_writers_count > 0)	{	  /* Wake up one of the waiting writers.  */	  if (pthread_cond_signal (&lock->waiting_writers) != 0)	    abort ();	}      else	{	  /* Wake up all waiting readers.  */	  if (pthread_cond_broadcast (&lock->waiting_readers) != 0)	    abort ();	}    }  if (pthread_mutex_unlock (&lock->lock) != 0)    abort ();}voidglthread_rwlock_destroy (gl_rwlock_t *lock){  if (pthread_mutex_destroy (&lock->lock) != 0)    abort ();  if (pthread_cond_destroy (&lock->waiting_readers) != 0)    abort ();  if (pthread_cond_destroy (&lock->waiting_writers) != 0)    abort ();}# endif/* --------------------- gl_recursive_lock_t datatype --------------------- */# if HAVE_PTHREAD_MUTEX_RECURSIVE#  if !(defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)voidglthread_recursive_lock_init (gl_recursive_lock_t *lock){  pthread_mutexattr_t attributes;  if (pthread_mutexattr_init (&attributes) != 0)    abort ();  if (pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE) != 0)    abort ();  if (pthread_mutex_init (&lock->recmutex, &attributes) != 0)    abort ();  if (pthread_mutexattr_destroy (&attributes) != 0)    abort ();  lock->initialized = 1;}voidglthread_recursive_lock_lock (gl_recursive_lock_t *lock){  if (!lock->initialized)    {      if (pthread_mutex_lock (&lock->guard) != 0)	abort ();      if (!lock->initialized)	glthread_recursive_lock_init (lock);      if (pthread_mutex_unlock (&lock->guard) != 0)	abort ();    }  if (pthread_mutex_lock (&lock->recmutex) != 0)    abort ();}voidglthread_recursive_lock_unlock (gl_recursive_lock_t *lock){  if (!lock->initialized)    abort ();  if (pthread_mutex_unlock (&lock->recmutex) != 0)    abort ();}voidglthread_recursive_lock_destroy (gl_recursive_lock_t *lock){  if (!lock->initialized)    abort ();  if (pthread_mutex_destroy (&lock->recmutex) != 0)    abort ();  lock->initialized = 0;}#  endif# elsevoidglthread_recursive_lock_init (gl_recursive_lock_t *lock){  if (pthread_mutex_init (&lock->mutex, NULL) != 0)    abort ();  lock->owner = (pthread_t) 0;  lock->depth = 0;}voidglthread_recursive_lock_lock (gl_recursive_lock_t *lock){  pthread_t self = pthread_self ();  if (lock->owner != self)    {      if (pthread_mutex_lock (&lock->mutex) != 0)	abort ();      lock->owner = self;    }  if (++(lock->depth) == 0) /* wraparound? */    abort ();}voidglthread_recursive_lock_unlock (gl_recursive_lock_t *lock){  if (lock->owner != pthread_self ())    abort ();  if (lock->depth == 0)    abort ();  if (--(lock->depth) == 0)    {      lock->owner = (pthread_t) 0;      if (pthread_mutex_unlock (&lock->mutex) != 0)	abort ();    }}voidglthread_recursive_lock_destroy (gl_recursive_lock_t *lock){  if (lock->owner != (pthread_t) 0)    abort ();  if (pthread_mutex_destroy (&lock->mutex) != 0)    abort ();}# endif/* -------------------------- gl_once_t datatype -------------------------- */static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT;intglthread_once_singlethreaded (pthread_once_t *once_control){  /* We don't know whether pthread_once_t is an integer type, a floating-point     type, a pointer type, or a structure type.  */  char *firstbyte = (char *)once_control;  if (*firstbyte == *(const char *)&fresh_once)    {      /* First time use of once_control.  Invert the first byte.  */      *firstbyte = ~ *(const char *)&fresh_once;      return 1;    }  else    return 0;}#endif/* ========================================================================= */#if USE_PTH_THREADS/* Use the GNU Pth threads library.  *//* -------------------------- gl_lock_t datatype -------------------------- *//* ------------------------- gl_rwlock_t datatype ------------------------- *//* --------------------- gl_recursive_lock_t datatype --------------------- *//* -------------------------- gl_once_t datatype -------------------------- */voidglthread_once_call (void *arg){  void (**gl_once_temp_addr) (void) = (void (**) (void)) arg;  void (*initfunction) (void) = *gl_once_temp_addr;  initfunction ();}intglthread_once_singlethreaded (pth_once_t *once_control){  /* We know that pth_once_t is an integer type.  */  if (*once_control == PTH_ONCE_INIT)    {      /* First time use of once_control.  Invert the marker.  */      *once_control = ~ PTH_ONCE_INIT;      return 1;    }  else    return 0;}#endif/* ========================================================================= */#if USE_SOLARIS_THREADS/* Use the old Solaris threads library.  *//* -------------------------- gl_lock_t datatype -------------------------- *//* ------------------------- gl_rwlock_t datatype ------------------------- *//* --------------------- gl_recursive_lock_t datatype --------------------- */voidglthread_recursive_lock_init (gl_recursive_lock_t *lock){  if (mutex_init (&lock->mutex, USYNC_THREAD, NULL) != 0)    abort ();  lock->owner = (thread_t) 0;  lock->depth = 0;}voidglthread_recursive_lock_lock (gl_recursive_lock_t *lock){  thread_t self = thr_self ();  if (lock->owner != self)    {      if (mutex_lock (&lock->mutex) != 0)	abort ();      lock->owner = self;    }  if (++(lock->depth) == 0) /* wraparound? */    abort ();}voidglthread_recursive_lock_unlock (gl_recursive_lock_t *lock){  if (lock->owner != thr_self ())    abort ();  if (lock->depth == 0)    abort ();  if (--(lock->depth) == 0)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -