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

📄 lock.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 2 页
字号:
    {      lock->owner = (thread_t) 0;      if (mutex_unlock (&lock->mutex) != 0)	abort ();    }}voidglthread_recursive_lock_destroy (gl_recursive_lock_t *lock){  if (lock->owner != (thread_t) 0)    abort ();  if (mutex_destroy (&lock->mutex) != 0)    abort ();}/* -------------------------- gl_once_t datatype -------------------------- */voidglthread_once (gl_once_t *once_control, void (*initfunction) (void)){  if (!once_control->inited)    {      /* Use the mutex to guarantee that if another thread is already calling	 the initfunction, this thread waits until it's finished.  */      if (mutex_lock (&once_control->mutex) != 0)	abort ();      if (!once_control->inited)	{	  once_control->inited = 1;	  initfunction ();	}      if (mutex_unlock (&once_control->mutex) != 0)	abort ();    }}intglthread_once_singlethreaded (gl_once_t *once_control){  /* We know that gl_once_t contains an integer type.  */  if (!once_control->inited)    {      /* First time use of once_control.  Invert the marker.  */      once_control->inited = ~ 0;      return 1;    }  else    return 0;}#endif/* ========================================================================= */#if USE_WIN32_THREADS/* -------------------------- gl_lock_t datatype -------------------------- */voidglthread_lock_init (gl_lock_t *lock){  InitializeCriticalSection (&lock->lock);  lock->guard.done = 1;}voidglthread_lock_lock (gl_lock_t *lock){  if (!lock->guard.done)    {      if (InterlockedIncrement (&lock->guard.started) == 0)	/* This thread is the first one to need this lock.  Initialize it.  */	glthread_lock_init (lock);      else	/* Yield the CPU while waiting for another thread to finish	   initializing this lock.  */	while (!lock->guard.done)	  Sleep (0);    }  EnterCriticalSection (&lock->lock);}voidglthread_lock_unlock (gl_lock_t *lock){  if (!lock->guard.done)    abort ();  LeaveCriticalSection (&lock->lock);}voidglthread_lock_destroy (gl_lock_t *lock){  if (!lock->guard.done)    abort ();  DeleteCriticalSection (&lock->lock);  lock->guard.done = 0;}/* ------------------------- gl_rwlock_t datatype ------------------------- */static inline voidgl_waitqueue_init (gl_waitqueue_t *wq){  wq->array = NULL;  wq->count = 0;  wq->alloc = 0;  wq->offset = 0;}/* Enqueues the current thread, represented by an event, in a wait queue.   Returns INVALID_HANDLE_VALUE if an allocation failure occurs.  */static HANDLEgl_waitqueue_add (gl_waitqueue_t *wq){  HANDLE event;  unsigned int index;  if (wq->count == wq->alloc)    {      unsigned int new_alloc = 2 * wq->alloc + 1;      HANDLE *new_array =	(HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));      if (new_array == NULL)	/* No more memory.  */	return INVALID_HANDLE_VALUE;      /* Now is a good opportunity to rotate the array so that its contents	 starts at offset 0.  */      if (wq->offset > 0)	{	  unsigned int old_count = wq->count;	  unsigned int old_alloc = wq->alloc;	  unsigned int old_offset = wq->offset;	  unsigned int i;	  if (old_offset + old_count > old_alloc)	    {	      unsigned int limit = old_offset + old_count - old_alloc;	      for (i = 0; i < limit; i++)		new_array[old_alloc + i] = new_array[i];	    }	  for (i = 0; i < old_count; i++)	    new_array[i] = new_array[old_offset + i];	  wq->offset = 0;	}      wq->array = new_array;      wq->alloc = new_alloc;    }  event = CreateEvent (NULL, TRUE, FALSE, NULL);  if (event == INVALID_HANDLE_VALUE)    /* No way to allocate an event.  */    return INVALID_HANDLE_VALUE;  index = wq->offset + wq->count;  if (index >= wq->alloc)    index -= wq->alloc;  wq->array[index] = event;  wq->count++;  return event;}/* Notifies the first thread from a wait queue and dequeues it.  */static inline voidgl_waitqueue_notify_first (gl_waitqueue_t *wq){  SetEvent (wq->array[wq->offset + 0]);  wq->offset++;  wq->count--;  if (wq->count == 0 || wq->offset == wq->alloc)    wq->offset = 0;}/* Notifies all threads from a wait queue and dequeues them all.  */static inline voidgl_waitqueue_notify_all (gl_waitqueue_t *wq){  unsigned int i;  for (i = 0; i < wq->count; i++)    {      unsigned int index = wq->offset + i;      if (index >= wq->alloc)	index -= wq->alloc;      SetEvent (wq->array[index]);    }  wq->count = 0;  wq->offset = 0;}voidglthread_rwlock_init (gl_rwlock_t *lock){  InitializeCriticalSection (&lock->lock);  gl_waitqueue_init (&lock->waiting_readers);  gl_waitqueue_init (&lock->waiting_writers);  lock->runcount = 0;  lock->guard.done = 1;}voidglthread_rwlock_rdlock (gl_rwlock_t *lock){  if (!lock->guard.done)    {      if (InterlockedIncrement (&lock->guard.started) == 0)	/* This thread is the first one to need this lock.  Initialize it.  */	glthread_rwlock_init (lock);      else	/* Yield the CPU while waiting for another thread to finish	   initializing this lock.  */	while (!lock->guard.done)	  Sleep (0);    }  EnterCriticalSection (&lock->lock);  /* Test whether only readers are currently running, and whether the runcount     field will not overflow.  */  if (!(lock->runcount + 1 > 0))    {      /* This thread has to wait for a while.  Enqueue it among the	 waiting_readers.  */      HANDLE event = gl_waitqueue_add (&lock->waiting_readers);      if (event != INVALID_HANDLE_VALUE)	{	  DWORD result;	  LeaveCriticalSection (&lock->lock);	  /* Wait until another thread signals this event.  */	  result = WaitForSingleObject (event, INFINITE);	  if (result == WAIT_FAILED || result == WAIT_TIMEOUT)	    abort ();	  CloseHandle (event);	  /* The thread which signalled the event already did the bookkeeping:	     removed us from the waiting_readers, incremented lock->runcount.  */	  if (!(lock->runcount > 0))	    abort ();	  return;	}      else	{	  /* Allocation failure.  Weird.  */	  do	    {	      LeaveCriticalSection (&lock->lock);	      Sleep (1);	      EnterCriticalSection (&lock->lock);	    }	  while (!(lock->runcount + 1 > 0));	}    }  lock->runcount++;  LeaveCriticalSection (&lock->lock);}voidglthread_rwlock_wrlock (gl_rwlock_t *lock){  if (!lock->guard.done)    {      if (InterlockedIncrement (&lock->guard.started) == 0)	/* This thread is the first one to need this lock.  Initialize it.  */	glthread_rwlock_init (lock);      else	/* Yield the CPU while waiting for another thread to finish	   initializing this lock.  */	while (!lock->guard.done)	  Sleep (0);    }  EnterCriticalSection (&lock->lock);  /* Test whether no readers or writers are currently running.  */  if (!(lock->runcount == 0))    {      /* This thread has to wait for a while.  Enqueue it among the	 waiting_writers.  */      HANDLE event = gl_waitqueue_add (&lock->waiting_writers);      if (event != INVALID_HANDLE_VALUE)	{	  DWORD result;	  LeaveCriticalSection (&lock->lock);	  /* Wait until another thread signals this event.  */	  result = WaitForSingleObject (event, INFINITE);	  if (result == WAIT_FAILED || result == WAIT_TIMEOUT)	    abort ();	  CloseHandle (event);	  /* The thread which signalled the event already did the bookkeeping:	     removed us from the waiting_writers, set lock->runcount = -1.  */	  if (!(lock->runcount == -1))	    abort ();	  return;	}      else	{	  /* Allocation failure.  Weird.  */	  do	    {	      LeaveCriticalSection (&lock->lock);	      Sleep (1);	      EnterCriticalSection (&lock->lock);	    }	  while (!(lock->runcount == 0));	}    }  lock->runcount--; /* runcount becomes -1 */  LeaveCriticalSection (&lock->lock);}voidglthread_rwlock_unlock (gl_rwlock_t *lock){  if (!lock->guard.done)    abort ();  EnterCriticalSection (&lock->lock);  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.  */	  lock->runcount--;	  gl_waitqueue_notify_first (&lock->waiting_writers);	}      else	{	  /* Wake up all waiting readers.  */	  lock->runcount += lock->waiting_readers.count;	  gl_waitqueue_notify_all (&lock->waiting_readers);	}    }  LeaveCriticalSection (&lock->lock);}voidglthread_rwlock_destroy (gl_rwlock_t *lock){  if (!lock->guard.done)    abort ();  if (lock->runcount != 0)    abort ();  DeleteCriticalSection (&lock->lock);  if (lock->waiting_readers.array != NULL)    free (lock->waiting_readers.array);  if (lock->waiting_writers.array != NULL)    free (lock->waiting_writers.array);  lock->guard.done = 0;}/* --------------------- gl_recursive_lock_t datatype --------------------- */voidglthread_recursive_lock_init (gl_recursive_lock_t *lock){  lock->owner = 0;  lock->depth = 0;  InitializeCriticalSection (&lock->lock);  lock->guard.done = 1;}voidglthread_recursive_lock_lock (gl_recursive_lock_t *lock){  if (!lock->guard.done)    {      if (InterlockedIncrement (&lock->guard.started) == 0)	/* This thread is the first one to need this lock.  Initialize it.  */	glthread_recursive_lock_init (lock);      else	/* Yield the CPU while waiting for another thread to finish	   initializing this lock.  */	while (!lock->guard.done)	  Sleep (0);    }  {    DWORD self = GetCurrentThreadId ();    if (lock->owner != self)      {	EnterCriticalSection (&lock->lock);	lock->owner = self;      }    if (++(lock->depth) == 0) /* wraparound? */      abort ();  }}voidglthread_recursive_lock_unlock (gl_recursive_lock_t *lock){  if (lock->owner != GetCurrentThreadId ())    abort ();  if (lock->depth == 0)    abort ();  if (--(lock->depth) == 0)    {      lock->owner = 0;      LeaveCriticalSection (&lock->lock);    }}voidglthread_recursive_lock_destroy (gl_recursive_lock_t *lock){  if (lock->owner != 0)    abort ();  DeleteCriticalSection (&lock->lock);  lock->guard.done = 0;}/* -------------------------- gl_once_t datatype -------------------------- */voidglthread_once (gl_once_t *once_control, void (*initfunction) (void)){  if (once_control->inited <= 0)    {      if (InterlockedIncrement (&once_control->started) == 0)	{	  /* This thread is the first one to come to this once_control.  */	  InitializeCriticalSection (&once_control->lock);	  EnterCriticalSection (&once_control->lock);	  once_control->inited = 0;	  initfunction ();	  once_control->inited = 1;	  LeaveCriticalSection (&once_control->lock);	}      else	{	  /* Undo last operation.  */	  InterlockedDecrement (&once_control->started);	  /* Some other thread has already started the initialization.	     Yield the CPU while waiting for the other thread to finish	     initializing and taking the lock.  */	  while (once_control->inited < 0)	    Sleep (0);	  if (once_control->inited <= 0)	    {	      /* Take the lock.  This blocks until the other thread has		 finished calling the initfunction.  */	      EnterCriticalSection (&once_control->lock);	      LeaveCriticalSection (&once_control->lock);	      if (!(once_control->inited > 0))		abort ();	    }	}    }}#endif/* ========================================================================= */

⌨️ 快捷键说明

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