745 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			745 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*  $Id$
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Part of the SWI-Prolog Semweb package
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    Author:        Jan Wielemaker
							 | 
						||
| 
								 | 
							
								    E-mail:        wielemak@science.uva.nl
							 | 
						||
| 
								 | 
							
								    WWW:           http://www.swi-prolog.org
							 | 
						||
| 
								 | 
							
								    Copyright (C): 2006, University of Amsterdam
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    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
							 | 
						||
| 
								 | 
							
								    of the License, 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 Lesser General Public
							 | 
						||
| 
								 | 
							
								    License along with this library; if not, write to the Free Software
							 | 
						||
| 
								 | 
							
								    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <SWI-Stream.h>
							 | 
						||
| 
								 | 
							
								#include <SWI-Prolog.h>
							 | 
						||
| 
								 | 
							
								#include "lock.h"
							 | 
						||
| 
								 | 
							
								#include "debug.h"
							 | 
						||
| 
								 | 
							
								#include <assert.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int
							 | 
						||
| 
								 | 
							
								permission_error(const char *op, const char *type, const char *obj,
							 | 
						||
| 
								 | 
							
										 const char *msg)
							 | 
						||
| 
								 | 
							
								{ term_t ex, ctx;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( !(ex = PL_new_term_ref()) ||
							 | 
						||
| 
								 | 
							
								       !(ctx = PL_new_term_ref()) )
							 | 
						||
| 
								 | 
							
								    return FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( msg )
							 | 
						||
| 
								 | 
							
								  { if ( !PL_unify_term(ctx, PL_FUNCTOR_CHARS, "context", 2,
							 | 
						||
| 
								 | 
							
											       PL_VARIABLE,
							 | 
						||
| 
								 | 
							
											       PL_CHARS, msg) )
							 | 
						||
| 
								 | 
							
								      return FALSE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( !PL_unify_term(ex, PL_FUNCTOR_CHARS, "error", 2,
							 | 
						||
| 
								 | 
							
										      PL_FUNCTOR_CHARS, "permission_error", 3,
							 | 
						||
| 
								 | 
							
										        PL_CHARS, op,
							 | 
						||
| 
								 | 
							
										        PL_CHARS, type,
							 | 
						||
| 
								 | 
							
										        PL_CHARS, obj,
							 | 
						||
| 
								 | 
							
										      PL_TERM, ctx) )
							 | 
						||
| 
								 | 
							
								    return FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return PL_raise_exception(ex);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef _REENTRANT
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										 /*******************************
							 | 
						||
| 
								 | 
							
										 *	   COMMON STUFF		*
							 | 
						||
| 
								 | 
							
										 *******************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static void
							 | 
						||
| 
								 | 
							
								register_reader(rwlock *lock, int tid)
							 | 
						||
| 
								 | 
							
								{ while ( tid >= lock->thread_max )
							 | 
						||
| 
								 | 
							
								  { size_t osize = lock->thread_max*sizeof(lock->read_by_thread[0]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lock->read_by_thread = realloc(lock->read_by_thread, osize*2);
							 | 
						||
| 
								 | 
							
								    memset((char*)lock->read_by_thread+osize, 0, osize);
							 | 
						||
| 
								 | 
							
								    lock->thread_max *= 2;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->read_by_thread[tid]++;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										 /*******************************
							 | 
						||
| 
								 | 
							
										 *	 WINDOWS VERSION	*
							 | 
						||
| 
								 | 
							
										 *******************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __WINDOWS__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <windows.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
							 | 
						||
| 
								 | 
							
								This  is  a  slightly  simplified  version  of  the  condition  variable
							 | 
						||
| 
								 | 
							
								emulation used in SWI-Prolog. We have   deleted the broadcast facilities
							 | 
						||
| 
								 | 
							
								of the CVs as this is not used in this code.
							 | 
						||
| 
								 | 
							
								- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int
							 | 
						||
| 
								 | 
							
								win32_cond_init(win32_cond_t *cv)
							 | 
						||
| 
								 | 
							
								{ cv->events[SIGNAL]    = CreateEvent(NULL, FALSE, FALSE, NULL);
							 | 
						||
| 
								 | 
							
								  cv->waiters = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int
							 | 
						||
| 
								 | 
							
								win32_cond_destroy(win32_cond_t *cv)
							 | 
						||
| 
								 | 
							
								{ CloseHandle(cv->events[SIGNAL]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define WAIT_INTR (-1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int
							 | 
						||
| 
								 | 
							
								win32_cond_wait(win32_cond_t *cv,
							 | 
						||
| 
								 | 
							
										CRITICAL_SECTION *external_mutex)
							 | 
						||
| 
								 | 
							
								{ int rc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  cv->waiters++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  LeaveCriticalSection(external_mutex);
							 | 
						||
| 
								 | 
							
								  rc = MsgWaitForMultipleObjects(1,
							 | 
						||
| 
								 | 
							
												 cv->events,
							 | 
						||
| 
								 | 
							
												 FALSE,	/* wait for either event */
							 | 
						||
| 
								 | 
							
												 INFINITE,
							 | 
						||
| 
								 | 
							
												 QS_ALLINPUT);
							 | 
						||
| 
								 | 
							
								  if ( rc == WAIT_OBJECT_0+1 )
							 | 
						||
| 
								 | 
							
								  { MSG msg;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
							 | 
						||
| 
								 | 
							
								    { TranslateMessage(&msg);
							 | 
						||
| 
								 | 
							
								      DispatchMessage(&msg);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( PL_handle_signals() < 0 )
							 | 
						||
| 
								 | 
							
								    { EnterCriticalSection(external_mutex);
							 | 
						||
| 
								 | 
							
								      return WAIT_INTR;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  EnterCriticalSection(external_mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  cv->waiters--;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static int
							 | 
						||
| 
								 | 
							
								win32_cond_signal(win32_cond_t *cv)	/* must be holding associated mutex */
							 | 
						||
| 
								 | 
							
								{ if ( cv->waiters > 0 )
							 | 
						||
| 
								 | 
							
								    SetEvent(cv->events[SIGNAL]);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								rdlock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ int self = PL_thread_self();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->writer == self )
							 | 
						||
| 
								 | 
							
								  { lock->lock_level++;			/* read nested in write */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  EnterCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->allow_readers == TRUE )
							 | 
						||
| 
								 | 
							
								  { ok:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lock->readers++;
							 | 
						||
| 
								 | 
							
								    register_reader(lock, self);
							 | 
						||
| 
								 | 
							
								    LeaveCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->waiting_readers++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(;;)
							 | 
						||
| 
								 | 
							
								  { int rc = win32_cond_wait(&lock->rdcondvar, &lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( rc == WAIT_INTR )
							 | 
						||
| 
								 | 
							
								    { lock->waiting_readers--;
							 | 
						||
| 
								 | 
							
								      LeaveCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								      return FALSE;
							 | 
						||
| 
								 | 
							
								    } else if ( rc == 0 )
							 | 
						||
| 
								 | 
							
								    { if ( lock->allow_readers == TRUE )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_readers--;
							 | 
						||
| 
								 | 
							
									goto ok;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else
							 | 
						||
| 
								 | 
							
								    { assert(0);			/* TBD: OS errors */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								wrlock(rwlock *lock, int allow_readers)
							 | 
						||
| 
								 | 
							
								{ int self = PL_thread_self();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->writer == self )		/* recursive write lock, used for */
							 | 
						||
| 
								 | 
							
								  { lock->lock_level++;			/* nested transactions */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  EnterCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->writer == -1 && lock->readers == 0 )
							 | 
						||
| 
								 | 
							
								  { ok:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lock->writer = self;
							 | 
						||
| 
								 | 
							
								    lock->lock_level = 1;
							 | 
						||
| 
								 | 
							
								    lock->allow_readers = allow_readers;
							 | 
						||
| 
								 | 
							
								    LeaveCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								    DEBUG(3, Sdprintf("WRLOCK(%d): OK\n", self));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( self < lock->thread_max && lock->read_by_thread[self] > 0 )
							 | 
						||
| 
								 | 
							
								  { LeaveCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								    return permission_error("write", "rdf_db", "default",
							 | 
						||
| 
								 | 
							
											    "Operation would deadlock");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->waiting_writers++;
							 | 
						||
| 
								 | 
							
								  DEBUG(3, Sdprintf("WRLOCK(%d): waiting ...\n", self));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(;;)
							 | 
						||
| 
								 | 
							
								  { int rc = win32_cond_wait(&lock->wrcondvar, &lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( rc == WAIT_INTR )
							 | 
						||
| 
								 | 
							
								    { lock->waiting_writers--;
							 | 
						||
| 
								 | 
							
								      LeaveCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								      return FALSE;
							 | 
						||
| 
								 | 
							
								    } else if ( rc == 0 )
							 | 
						||
| 
								 | 
							
								    { if ( lock->writer == -1 && lock->readers == 0 )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_writers--;
							 | 
						||
| 
								 | 
							
									goto ok;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else
							 | 
						||
| 
								 | 
							
								    { assert(0);			/* TBD: OS errors */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								lockout_readers(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ EnterCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->readers == 0 )
							 | 
						||
| 
								 | 
							
								  { ok:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lock->allow_readers = FALSE;
							 | 
						||
| 
								 | 
							
								    LeaveCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->waiting_upgrade++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(;;)
							 | 
						||
| 
								 | 
							
								  { int rc = win32_cond_wait(&lock->upcondvar, &lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( rc == WAIT_INTR )
							 | 
						||
| 
								 | 
							
								    { lock->waiting_upgrade--;
							 | 
						||
| 
								 | 
							
								      LeaveCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								      return FALSE;
							 | 
						||
| 
								 | 
							
								    } else if ( rc == 0 )
							 | 
						||
| 
								 | 
							
								    { if ( lock->readers == 0 )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_upgrade--;
							 | 
						||
| 
								 | 
							
									goto ok;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else
							 | 
						||
| 
								 | 
							
								    { assert(0);			/* TBD: OS errors */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void
							 | 
						||
| 
								 | 
							
								reallow_readers(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ EnterCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								  lock->allow_readers = TRUE;
							 | 
						||
| 
								 | 
							
								  LeaveCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								unlock(rwlock *lock, int rd)
							 | 
						||
| 
								 | 
							
								{ int self = PL_thread_self();
							 | 
						||
| 
								 | 
							
								  int signal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->writer == self && lock->lock_level > 1 )
							 | 
						||
| 
								 | 
							
								  { lock->lock_level--;
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  EnterCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								  if ( rd )				/* must be a read lock */
							 | 
						||
| 
								 | 
							
								  { lock->readers--;
							 | 
						||
| 
								 | 
							
								    lock->read_by_thread[self]--;
							 | 
						||
| 
								 | 
							
								    signal = (lock->readers == 0);
							 | 
						||
| 
								 | 
							
								  } else
							 | 
						||
| 
								 | 
							
								  { lock->writer = -1;
							 | 
						||
| 
								 | 
							
								    lock->allow_readers = TRUE;
							 | 
						||
| 
								 | 
							
								    signal = TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( signal )
							 | 
						||
| 
								 | 
							
								  { enum { NONE, READ, WRITE, UPGRADE } waiting;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    waiting = (lock->waiting_upgrade ? UPGRADE :
							 | 
						||
| 
								 | 
							
									       lock->waiting_writers ? WRITE :
							 | 
						||
| 
								 | 
							
									       lock->waiting_readers ? READ : NONE);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch(waiting)
							 | 
						||
| 
								 | 
							
								    { case UPGRADE:
							 | 
						||
| 
								 | 
							
									win32_cond_signal(&lock->upcondvar);
							 | 
						||
| 
								 | 
							
									break;
							 | 
						||
| 
								 | 
							
								      case WRITE:
							 | 
						||
| 
								 | 
							
									win32_cond_signal(&lock->wrcondvar);
							 | 
						||
| 
								 | 
							
									break;
							 | 
						||
| 
								 | 
							
								      case READ:
							 | 
						||
| 
								 | 
							
									win32_cond_signal(&lock->rdcondvar);
							 | 
						||
| 
								 | 
							
									break;
							 | 
						||
| 
								 | 
							
								      default:
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  LeaveCriticalSection(&lock->mutex);	/* In our __WINDOWS__ emulation we */
							 | 
						||
| 
								 | 
							
													/* must hold the associated mutex */
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								lock_misc(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ EnterCriticalSection(&lock->misc_mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								unlock_misc(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ LeaveCriticalSection(&lock->misc_mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								init_lock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ InitializeCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								  InitializeCriticalSection(&lock->misc_mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( !win32_cond_init(&lock->wrcondvar) == 0 ||
							 | 
						||
| 
								 | 
							
								       !win32_cond_init(&lock->rdcondvar) == 0 ||
							 | 
						||
| 
								 | 
							
								       !win32_cond_init(&lock->upcondvar) == 0 )
							 | 
						||
| 
								 | 
							
								  {					/* TBD: System error */
							 | 
						||
| 
								 | 
							
								    return FALSE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->writer          = -1;
							 | 
						||
| 
								 | 
							
								  lock->allow_readers   = TRUE;
							 | 
						||
| 
								 | 
							
								  lock->readers         = 0;
							 | 
						||
| 
								 | 
							
								  lock->waiting_readers = 0;
							 | 
						||
| 
								 | 
							
								  lock->waiting_writers = 0;
							 | 
						||
| 
								 | 
							
								  lock->waiting_upgrade = 0;
							 | 
						||
| 
								 | 
							
								  lock->lock_level      = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->thread_max = 4;
							 | 
						||
| 
								 | 
							
								  if ( !(lock->read_by_thread = malloc(lock->thread_max*sizeof(int))) )
							 | 
						||
| 
								 | 
							
								    return FALSE;
							 | 
						||
| 
								 | 
							
								  memset(lock->read_by_thread, 0, lock->thread_max*sizeof(int));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								destroy_lock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ DeleteCriticalSection(&lock->mutex);
							 | 
						||
| 
								 | 
							
								  DeleteCriticalSection(&lock->misc_mutex);
							 | 
						||
| 
								 | 
							
								  win32_cond_destroy(&lock->wrcondvar);
							 | 
						||
| 
								 | 
							
								  win32_cond_destroy(&lock->rdcondvar);
							 | 
						||
| 
								 | 
							
								  win32_cond_destroy(&lock->upcondvar);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  free(lock->read_by_thread);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else /*__WINDOWS__*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										 /*******************************
							 | 
						||
| 
								 | 
							
										 *	   POSIX VERSION	*
							 | 
						||
| 
								 | 
							
										 *******************************/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <errno.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								rdlock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ int self = PL_thread_self();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->writer == self )
							 | 
						||
| 
								 | 
							
								  { lock->lock_level++;			/* read nested in write */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pthread_mutex_lock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->allow_readers == TRUE )
							 | 
						||
| 
								 | 
							
								  { ok:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lock->readers++;
							 | 
						||
| 
								 | 
							
								    register_reader(lock, self);
							 | 
						||
| 
								 | 
							
								    pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->waiting_readers++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(;;)
							 | 
						||
| 
								 | 
							
								  { int rc = pthread_cond_wait(&lock->rdcondvar, &lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( rc == EINTR )
							 | 
						||
| 
								 | 
							
								    { if ( PL_handle_signals() < 0 )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_readers--;
							 | 
						||
| 
								 | 
							
									pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
									return FALSE;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    } else if ( rc == 0 )
							 | 
						||
| 
								 | 
							
								    { if ( lock->allow_readers == TRUE )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_readers--;
							 | 
						||
| 
								 | 
							
									goto ok;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else
							 | 
						||
| 
								 | 
							
								    { assert(0);			/* TBD: OS errors */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
							 | 
						||
| 
								 | 
							
								WRLOCK() and LOCKOUT_READERS() can be  used   in  two ways. Conventional
							 | 
						||
| 
								 | 
							
								write locks are established using   WRLOCK(db,  FALSE) ... WRUNLOCK(db).
							 | 
						||
| 
								 | 
							
								For transactions, we allow concurrent  readers   until  we  are ready to
							 | 
						||
| 
								 | 
							
								commit, in which case we use  WRLOCK(db, TRUE) ... LOCKOUT_READERS() ...
							 | 
						||
| 
								 | 
							
								WRUNLOCK(db)
							 | 
						||
| 
								 | 
							
								- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								wrlock(rwlock *lock, int allow_readers)
							 | 
						||
| 
								 | 
							
								{ int self = PL_thread_self();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->writer == self )		/* recursive write lock, used for */
							 | 
						||
| 
								 | 
							
								  { lock->lock_level++;			/* nested transactions */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pthread_mutex_lock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->writer == -1 && lock->readers == 0 )
							 | 
						||
| 
								 | 
							
								  { ok:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lock->writer = self;
							 | 
						||
| 
								 | 
							
								    lock->lock_level = 1;
							 | 
						||
| 
								 | 
							
								    lock->allow_readers = allow_readers;
							 | 
						||
| 
								 | 
							
								    pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								    DEBUG(3, Sdprintf("WRLOCK(%d): OK\n", self));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( self < lock->thread_max && lock->read_by_thread[self] > 0 )
							 | 
						||
| 
								 | 
							
								  { DEBUG(1, Sdprintf("SELF(%d) has %d readers\n",
							 | 
						||
| 
								 | 
							
										      self, lock->read_by_thread[self]));
							 | 
						||
| 
								 | 
							
								    pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								    return permission_error("write", "rdf_db", "default",
							 | 
						||
| 
								 | 
							
											    "Operation would deadlock");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->waiting_writers++;
							 | 
						||
| 
								 | 
							
								  DEBUG(3, Sdprintf("WRLOCK(%d): waiting ...\n", self));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(;;)
							 | 
						||
| 
								 | 
							
								  { int rc = pthread_cond_wait(&lock->wrcondvar, &lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( rc == EINTR )
							 | 
						||
| 
								 | 
							
								    { if ( PL_handle_signals() < 0 )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_writers--;
							 | 
						||
| 
								 | 
							
									pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
									return FALSE;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    } else if ( rc == 0 )
							 | 
						||
| 
								 | 
							
								    { if ( lock->writer == -1 && lock->readers == 0 )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_writers--;
							 | 
						||
| 
								 | 
							
									goto ok;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else
							 | 
						||
| 
								 | 
							
								    { assert(0);			/* TBD: OS errors */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								lockout_readers(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ pthread_mutex_lock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->readers == 0 )
							 | 
						||
| 
								 | 
							
								  { ok:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    lock->allow_readers = FALSE;
							 | 
						||
| 
								 | 
							
								    pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->waiting_upgrade++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(;;)
							 | 
						||
| 
								 | 
							
								  { int rc = pthread_cond_wait(&lock->upcondvar, &lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ( rc == EINTR )
							 | 
						||
| 
								 | 
							
								    { if ( PL_handle_signals() < 0 )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_upgrade--;
							 | 
						||
| 
								 | 
							
									pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
									return FALSE;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    } else if ( rc == 0 )
							 | 
						||
| 
								 | 
							
								    { if ( lock->readers == 0 )
							 | 
						||
| 
								 | 
							
								      { lock->waiting_upgrade--;
							 | 
						||
| 
								 | 
							
									goto ok;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else
							 | 
						||
| 
								 | 
							
								    { assert(0);			/* TBD: OS errors */
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void
							 | 
						||
| 
								 | 
							
								reallow_readers(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ pthread_mutex_lock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								  lock->allow_readers = TRUE;
							 | 
						||
| 
								 | 
							
								  pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								unlock(rwlock *lock, int rd)		/* TRUE: read lock */
							 | 
						||
| 
								 | 
							
								{ int self = PL_thread_self();
							 | 
						||
| 
								 | 
							
								  int signal;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( lock->writer == self && lock->lock_level > 1 )
							 | 
						||
| 
								 | 
							
								  { lock->lock_level--;
							 | 
						||
| 
								 | 
							
								    return TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  pthread_mutex_lock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								  if ( rd )				/* read lock */
							 | 
						||
| 
								 | 
							
								  { lock->readers--;
							 | 
						||
| 
								 | 
							
								    lock->read_by_thread[self]--;
							 | 
						||
| 
								 | 
							
								    signal = (lock->readers == 0);
							 | 
						||
| 
								 | 
							
								  } else
							 | 
						||
| 
								 | 
							
								  { lock->writer = -1;
							 | 
						||
| 
								 | 
							
								    lock->allow_readers = TRUE;
							 | 
						||
| 
								 | 
							
								    signal = TRUE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if ( signal )
							 | 
						||
| 
								 | 
							
								  { enum { NONE, READ, WRITE, UPGRADE } waiting;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    waiting = (lock->waiting_upgrade ? UPGRADE :
							 | 
						||
| 
								 | 
							
									       lock->waiting_writers ? WRITE :
							 | 
						||
| 
								 | 
							
									       lock->waiting_readers ? READ : NONE);
							 | 
						||
| 
								 | 
							
								    pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch(waiting)
							 | 
						||
| 
								 | 
							
								    { case UPGRADE:
							 | 
						||
| 
								 | 
							
									pthread_cond_signal(&lock->upcondvar);
							 | 
						||
| 
								 | 
							
									break;
							 | 
						||
| 
								 | 
							
								      case WRITE:
							 | 
						||
| 
								 | 
							
									pthread_cond_signal(&lock->wrcondvar);
							 | 
						||
| 
								 | 
							
									break;
							 | 
						||
| 
								 | 
							
								      case READ:
							 | 
						||
| 
								 | 
							
									pthread_cond_signal(&lock->rdcondvar);
							 | 
						||
| 
								 | 
							
									break;
							 | 
						||
| 
								 | 
							
								      default:
							 | 
						||
| 
								 | 
							
									;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  } else
							 | 
						||
| 
								 | 
							
								  { pthread_mutex_unlock(&lock->mutex);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								lock_misc(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ return pthread_mutex_lock(&lock->misc_mutex) == 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								unlock_misc(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ return pthread_mutex_unlock(&lock->misc_mutex) == 0;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								init_lock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ if ( !pthread_mutex_init(&lock->mutex, NULL) == 0 ||
							 | 
						||
| 
								 | 
							
								       !pthread_mutex_init(&lock->misc_mutex, NULL) == 0 ||
							 | 
						||
| 
								 | 
							
								       !pthread_cond_init(&lock->wrcondvar, NULL) == 0 ||
							 | 
						||
| 
								 | 
							
								       !pthread_cond_init(&lock->rdcondvar, NULL) == 0 ||
							 | 
						||
| 
								 | 
							
								       !pthread_cond_init(&lock->upcondvar, NULL) == 0 )
							 | 
						||
| 
								 | 
							
								  {					/* TBD: System error */
							 | 
						||
| 
								 | 
							
								    return FALSE;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->writer          = -1;
							 | 
						||
| 
								 | 
							
								  lock->readers	        = 0;
							 | 
						||
| 
								 | 
							
								  lock->allow_readers   = TRUE;
							 | 
						||
| 
								 | 
							
								  lock->waiting_readers = 0;
							 | 
						||
| 
								 | 
							
								  lock->waiting_writers = 0;
							 | 
						||
| 
								 | 
							
								  lock->waiting_upgrade = 0;
							 | 
						||
| 
								 | 
							
								  lock->lock_level      = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->thread_max = 4;
							 | 
						||
| 
								 | 
							
								  if ( !(lock->read_by_thread = malloc(lock->thread_max*sizeof(int))) )
							 | 
						||
| 
								 | 
							
								    return FALSE;
							 | 
						||
| 
								 | 
							
								  memset(lock->read_by_thread, 0, lock->thread_max*sizeof(int));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								destroy_lock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ if ( !pthread_mutex_destroy(&lock->mutex) ||
							 | 
						||
| 
								 | 
							
								       !pthread_mutex_destroy(&lock->misc_mutex) ||
							 | 
						||
| 
								 | 
							
								       !pthread_cond_destroy(&lock->wrcondvar) ||
							 | 
						||
| 
								 | 
							
								       !pthread_cond_destroy(&lock->rdcondvar) ||
							 | 
						||
| 
								 | 
							
								       !pthread_cond_destroy(&lock->upcondvar) )
							 | 
						||
| 
								 | 
							
								    return FALSE;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  free(lock->read_by_thread);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /*__WINDOWS__*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else /*_REENTRANT*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								rdlock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ lock->readers++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								wrlock(rwlock *lock, int allow_readers)
							 | 
						||
| 
								 | 
							
								{ if ( lock->readers )
							 | 
						||
| 
								 | 
							
								    return permission_error("write", "rdf_db", "default",
							 | 
						||
| 
								 | 
							
											    "Operation would deadlock");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  lock->writer = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								unlock(rwlock *lock, int rd)
							 | 
						||
| 
								 | 
							
								{ if ( rd )
							 | 
						||
| 
								 | 
							
								  { lock->readers--;
							 | 
						||
| 
								 | 
							
								  } else
							 | 
						||
| 
								 | 
							
								  { lock->writer = -1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								lock_misc(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								unlock_misc(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								init_lock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ lock->writer = -1;
							 | 
						||
| 
								 | 
							
								  lock->readers = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								lockout_readers(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void
							 | 
						||
| 
								 | 
							
								reallow_readers(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int
							 | 
						||
| 
								 | 
							
								destroy_lock(rwlock *lock)
							 | 
						||
| 
								 | 
							
								{ return TRUE;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /*_REENTRANT*/
							 | 
						||
| 
								 | 
							
								
							 |