mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	Inline frequently called functions.
This commit is contained in:
		@@ -6,31 +6,156 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 1994, Regents of the University of California
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: valid.h,v 1.7 1997/09/08 21:51:05 momjian Exp $
 | 
			
		||||
 * $Id: valid.h,v 1.8 1997/09/18 14:20:45 momjian Exp $
 | 
			
		||||
 *
 | 
			
		||||
 *-------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
#ifndef VALID_H
 | 
			
		||||
#define VALID_H
 | 
			
		||||
 | 
			
		||||
#include <fmgr.h>
 | 
			
		||||
#include <access/heapam.h>
 | 
			
		||||
#include <access/valid.h>
 | 
			
		||||
#include <utils/tqual.h>
 | 
			
		||||
#include <storage/bufmgr.h>
 | 
			
		||||
#include <storage/bufpage.h>
 | 
			
		||||
#include <utils/rel.h>
 | 
			
		||||
#include <utils/builtins.h>
 | 
			
		||||
 | 
			
		||||
/* ----------------
 | 
			
		||||
 *		extern decl's
 | 
			
		||||
 * ----------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern bool
 | 
			
		||||
heap_keytest(HeapTuple t, TupleDesc tupdesc,
 | 
			
		||||
			 int nkeys, ScanKey keys);
 | 
			
		||||
/* ----------------
 | 
			
		||||
 *		HeapKeyTest
 | 
			
		||||
 *
 | 
			
		||||
 *		Test a heap tuple with respect to a scan key.
 | 
			
		||||
 * ----------------
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern HeapTuple
 | 
			
		||||
heap_tuple_satisfies(ItemId itemId, Relation relation,
 | 
			
		||||
					 Buffer buffer, PageHeader disk_page,
 | 
			
		||||
					 TimeQual qual, int nKeys,
 | 
			
		||||
					 ScanKey key);
 | 
			
		||||
#define HeapKeyTest(tuple, \
 | 
			
		||||
					tupdesc, \
 | 
			
		||||
					nkeys, \
 | 
			
		||||
					keys, \
 | 
			
		||||
					result) \
 | 
			
		||||
do \
 | 
			
		||||
{ \
 | 
			
		||||
/* We use underscores to protect the variable passed in as parameters */ \
 | 
			
		||||
/* We use two underscore here because this macro is included in the \
 | 
			
		||||
   macro below */ \
 | 
			
		||||
	bool		__isnull; \
 | 
			
		||||
	Datum		__atp; \
 | 
			
		||||
	int			__test; \
 | 
			
		||||
	int			__cur_nkeys = (nkeys); \
 | 
			
		||||
	ScanKey		__cur_keys = (keys); \
 | 
			
		||||
 \
 | 
			
		||||
	(result) = true; /* may change */ \
 | 
			
		||||
	for (; __cur_nkeys--; __cur_keys++) \
 | 
			
		||||
	{ \
 | 
			
		||||
		__atp = heap_getattr((tuple), InvalidBuffer, \
 | 
			
		||||
						   __cur_keys->sk_attno, \
 | 
			
		||||
						   (tupdesc), \
 | 
			
		||||
						   &__isnull); \
 | 
			
		||||
 \
 | 
			
		||||
		if (__isnull) \
 | 
			
		||||
		{ \
 | 
			
		||||
			/* XXX eventually should check if SK_ISNULL */ \
 | 
			
		||||
			(result) = false; \
 | 
			
		||||
			break; \
 | 
			
		||||
		} \
 | 
			
		||||
 \
 | 
			
		||||
		if (__cur_keys->sk_flags & SK_ISNULL) \
 | 
			
		||||
		{ \
 | 
			
		||||
			(result) = false; \
 | 
			
		||||
			break; \
 | 
			
		||||
		} \
 | 
			
		||||
 \
 | 
			
		||||
		if (__cur_keys->sk_func == (func_ptr) oideq)	/* optimization */ \
 | 
			
		||||
			__test = (__cur_keys->sk_argument == __atp); \
 | 
			
		||||
		else if (__cur_keys->sk_flags & SK_COMMUTE) \
 | 
			
		||||
			__test = (long) FMGR_PTR2(__cur_keys->sk_func, __cur_keys->sk_procedure, \
 | 
			
		||||
									__cur_keys->sk_argument, __atp); \
 | 
			
		||||
		else \
 | 
			
		||||
			__test = (long) FMGR_PTR2(__cur_keys->sk_func, __cur_keys->sk_procedure, \
 | 
			
		||||
									__atp, __cur_keys->sk_argument); \
 | 
			
		||||
 \
 | 
			
		||||
		if (!__test == !(__cur_keys->sk_flags & SK_NEGATE)) \
 | 
			
		||||
		{ \
 | 
			
		||||
			/* XXX eventually should check if SK_ISNULL */ \
 | 
			
		||||
			(result) = false; \
 | 
			
		||||
			break; \
 | 
			
		||||
		} \
 | 
			
		||||
	} \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
/* ----------------
 | 
			
		||||
 *		HeapTupleSatisfies
 | 
			
		||||
 *
 | 
			
		||||
 *	Returns a valid HeapTuple if it satisfies the timequal and keytest.
 | 
			
		||||
 *	Returns NULL otherwise.  Used to be heap_satisifies (sic) which
 | 
			
		||||
 *	returned a boolean.  It now returns a tuple so that we can avoid doing two
 | 
			
		||||
 *	PageGetItem's per tuple.
 | 
			
		||||
 *
 | 
			
		||||
 *		Complete check of validity including LP_CTUP and keytest.
 | 
			
		||||
 *		This should perhaps be combined with valid somehow in the
 | 
			
		||||
 *		future.  (Also, additional rule tests/time range tests.)
 | 
			
		||||
 *
 | 
			
		||||
 *	on 8/21/92 mao says:  i rearranged the tests here to do keytest before
 | 
			
		||||
 *	SatisfiesTimeQual.	profiling indicated that even for vacuumed relations,
 | 
			
		||||
 *	time qual checking was more expensive than key testing.  time qual is
 | 
			
		||||
 *	least likely to fail, too.	we should really add the time qual test to
 | 
			
		||||
 *	the restriction and optimize it in the normal way.	this has interactions
 | 
			
		||||
 *	with joey's expensive function work.
 | 
			
		||||
 * ----------------
 | 
			
		||||
 */
 | 
			
		||||
#define HeapTupleSatisfies(itemId, \
 | 
			
		||||
						   relation, \
 | 
			
		||||
						   buffer, \
 | 
			
		||||
						   disk_page, \
 | 
			
		||||
						   qual, \
 | 
			
		||||
						   nKeys, \
 | 
			
		||||
						   key, \
 | 
			
		||||
						   result) \
 | 
			
		||||
do \
 | 
			
		||||
{ \
 | 
			
		||||
/* We use underscores to protect the variable passed in as parameters */ \
 | 
			
		||||
	HeapTuple	_tuple; \
 | 
			
		||||
	bool		_res; \
 | 
			
		||||
	TransactionId _old_tmin, \
 | 
			
		||||
				_old_tmax; \
 | 
			
		||||
 \
 | 
			
		||||
	if (!ItemIdIsUsed(itemId)) \
 | 
			
		||||
		(result) = (HeapTuple) NULL; \
 | 
			
		||||
	else \
 | 
			
		||||
	{ \
 | 
			
		||||
		_tuple = (HeapTuple) PageGetItem((Page) (disk_page), (itemId)); \
 | 
			
		||||
	 \
 | 
			
		||||
		if ((key) != NULL) \
 | 
			
		||||
			HeapKeyTest(_tuple, RelationGetTupleDescriptor(relation), \
 | 
			
		||||
							   (nKeys), (key), _res); \
 | 
			
		||||
		else \
 | 
			
		||||
			_res = TRUE; \
 | 
			
		||||
 \
 | 
			
		||||
		(result) = (HeapTuple) NULL; \
 | 
			
		||||
		if (_res) \
 | 
			
		||||
		{ \
 | 
			
		||||
			if ((relation)->rd_rel->relkind == RELKIND_UNCATALOGED) \
 | 
			
		||||
				(result) = _tuple; \
 | 
			
		||||
			else \
 | 
			
		||||
			{ \
 | 
			
		||||
				_old_tmin = _tuple->t_tmin; \
 | 
			
		||||
				_old_tmax = _tuple->t_tmax; \
 | 
			
		||||
				_res = HeapTupleSatisfiesTimeQual(_tuple, (qual)); \
 | 
			
		||||
				if (_tuple->t_tmin != _old_tmin || \
 | 
			
		||||
					_tuple->t_tmax != _old_tmax) \
 | 
			
		||||
					SetBufferCommitInfoNeedsSave(buffer); \
 | 
			
		||||
				if (_res) \
 | 
			
		||||
					(result) = _tuple; \
 | 
			
		||||
			} \
 | 
			
		||||
		} \
 | 
			
		||||
	} \
 | 
			
		||||
} while (0)
 | 
			
		||||
 | 
			
		||||
extern bool TupleUpdatedByCurXactAndCmd(HeapTuple t);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 1994, Regents of the University of California
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: c.h,v 1.19 1997/09/08 21:50:24 momjian Exp $
 | 
			
		||||
 * $Id: c.h,v 1.20 1997/09/18 14:20:40 momjian Exp $
 | 
			
		||||
 *
 | 
			
		||||
 *-------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
@@ -692,6 +692,27 @@ typedef struct Exception
 | 
			
		||||
/* we do this so if the macro is used in an if action, it will work */
 | 
			
		||||
#define strNcpy(dst,src,len)	(strncpy((dst),(src),(len)),*((dst)+(len))='\0')
 | 
			
		||||
 | 
			
		||||
/* Get a bit mask of the bits set in non-int32 aligned addresses */
 | 
			
		||||
#define INT_ALIGN_MASK (sizeof(int32) - 1)
 | 
			
		||||
 | 
			
		||||
/* This function gets call too often, so we inline it if we can */
 | 
			
		||||
#define MemSet(start, val, len)	do \
 | 
			
		||||
								{   /* are we aligned for int32? */ \
 | 
			
		||||
									if (((start) & INT_ALIGN_MASK) == 0 && \
 | 
			
		||||
										((len) & INT_ALIGN_MASK) == 0 && \
 | 
			
		||||
										(val) == 0 && \
 | 
			
		||||
										(len) <= 256) \
 | 
			
		||||
									{ \
 | 
			
		||||
										int32 *i = (int32 *)(start); \
 | 
			
		||||
										int32 *stop = (int32 *)((char *)(start) + (len)); \
 | 
			
		||||
										\
 | 
			
		||||
										while (i < stop) \
 | 
			
		||||
											*i++ = 0; \
 | 
			
		||||
									} \
 | 
			
		||||
									else \
 | 
			
		||||
										memset((start), (val), (len)); \
 | 
			
		||||
								}
 | 
			
		||||
 | 
			
		||||
/* ----------------------------------------------------------------
 | 
			
		||||
 *				Section 9: externs
 | 
			
		||||
 * ----------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 1994, Regents of the University of California
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: ipc.h,v 1.20 1997/09/08 21:54:21 momjian Exp $
 | 
			
		||||
 * $Id: ipc.h,v 1.21 1997/09/18 14:20:54 momjian Exp $
 | 
			
		||||
 *
 | 
			
		||||
 * NOTES
 | 
			
		||||
 *	  This file is very architecture-specific.	This stuff should actually
 | 
			
		||||
@@ -28,10 +28,6 @@
 | 
			
		||||
 | 
			
		||||
#if defined(HAS_TEST_AND_SET)
 | 
			
		||||
 | 
			
		||||
extern void S_LOCK(slock_t *lock);
 | 
			
		||||
extern void S_UNLOCK(slock_t *lock);
 | 
			
		||||
extern void S_INIT_LOCK(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#if (defined(alpha) && !defined(linuxalpha)) || \
 | 
			
		||||
	defined(hpux) || \
 | 
			
		||||
	defined(irix5) || \
 | 
			
		||||
@@ -150,10 +146,6 @@ typedef struct slock
 | 
			
		||||
	struct slock *next;
 | 
			
		||||
} SLock;
 | 
			
		||||
 | 
			
		||||
extern void ExclusiveLock(int lockid);
 | 
			
		||||
extern void ExclusiveUnlock(int lockid);
 | 
			
		||||
extern bool LockIsFree(int lockid);
 | 
			
		||||
 | 
			
		||||
#else							/* HAS_TEST_AND_SET */
 | 
			
		||||
 | 
			
		||||
typedef enum _LockId_
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										808
									
								
								src/include/storage/s_lock.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										808
									
								
								src/include/storage/s_lock.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,808 @@
 | 
			
		||||
/*-------------------------------------------------------------------------
 | 
			
		||||
 *
 | 
			
		||||
 * s_lock.h--
 | 
			
		||||
 *	   This file contains the implementation (if any) for spinlocks.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 1994, Regents of the University of California
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * IDENTIFICATION
 | 
			
		||||
 *	  $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.1 1997/09/18 14:20:59 momjian Exp $
 | 
			
		||||
 *
 | 
			
		||||
 *-------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 *	 DESCRIPTION
 | 
			
		||||
 *		The following code fragment should be written (in assembly
 | 
			
		||||
 *		language) on machines that have a native test-and-set instruction:
 | 
			
		||||
 *
 | 
			
		||||
 *		void
 | 
			
		||||
 *		S_LOCK(char_address)
 | 
			
		||||
 *			char *char_address;
 | 
			
		||||
 *		{
 | 
			
		||||
 *			while (test_and_set(char_address))
 | 
			
		||||
 *				;
 | 
			
		||||
 *		}
 | 
			
		||||
 *
 | 
			
		||||
 *		If this is not done, POSTGRES will default to using System V
 | 
			
		||||
 *		semaphores (and take a large performance hit -- around 40% of
 | 
			
		||||
 *		its time on a DS5000/240 is spent in semop(3)...).
 | 
			
		||||
 *
 | 
			
		||||
 *	 NOTES
 | 
			
		||||
 *		AIX has a test-and-set but the recommended interface is the cs(3)
 | 
			
		||||
 *		system call.  This provides an 8-instruction (plus system call
 | 
			
		||||
 *		overhead) uninterruptible compare-and-set operation.  True
 | 
			
		||||
 *		spinlocks might be faster but using cs(3) still speeds up the
 | 
			
		||||
 *		regression test suite by about 25%.  I don't have an assembler
 | 
			
		||||
 *		manual for POWER in any case.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef S_LOCK_H
 | 
			
		||||
#define S_LOCK_H
 | 
			
		||||
 | 
			
		||||
#include "storage/ipc.h"
 | 
			
		||||
 | 
			
		||||
#if defined(HAS_TEST_AND_SET)
 | 
			
		||||
 | 
			
		||||
#if defined (nextstep)
 | 
			
		||||
/*
 | 
			
		||||
 * NEXTSTEP (mach)
 | 
			
		||||
 * slock_t is defined as a struct mutex.
 | 
			
		||||
 */
 | 
			
		||||
#define	S_LOCK(lock)	mutex_lock(lock)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	mutex_unlock(lock)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	mutex_init(lock)
 | 
			
		||||
 | 
			
		||||
 /* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
 | 
			
		||||
/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
 | 
			
		||||
#define	S_LOCK_FREE(alock)	((alock)->lock == 0)
 | 
			
		||||
 | 
			
		||||
#endif							/* next */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(irix5)
 | 
			
		||||
/*
 | 
			
		||||
 * SGI IRIX 5
 | 
			
		||||
 * slock_t is defined as a struct abilock_t, which has a single unsigned long
 | 
			
		||||
 * member.
 | 
			
		||||
 *
 | 
			
		||||
 * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
 | 
			
		||||
 * assembly from his NECEWS SVR4 port, but we probably ought to retain this
 | 
			
		||||
 * for the R3000 chips out there.
 | 
			
		||||
 */
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (!acquire_lock(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define S_UNLOCK(lock)	release_lock(lock)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	init_lock(lock)
 | 
			
		||||
 | 
			
		||||
/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK_FREE(lock)	(stat_lock(lock) == UNLOCKED)
 | 
			
		||||
 | 
			
		||||
#endif							/* irix5 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * OSF/1 (Alpha AXP)
 | 
			
		||||
 *
 | 
			
		||||
 * Note that slock_t on the Alpha AXP is msemaphore instead of char
 | 
			
		||||
 * (see storage/ipc.h).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(__alpha__) || defined(__alpha)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (msem_lock((lock), MSEM_IF_NOWAIT) < 0) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	msem_unlock((lock), 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	msem_init((lock), MSEM_UNLOCKED)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK_FREE(lock)	(!(lock)->msem_state)
 | 
			
		||||
 | 
			
		||||
#endif							/* alpha */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Solaris 2
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(i386_solaris) || \
 | 
			
		||||
	defined(sparc_solaris)
 | 
			
		||||
/* for xxxxx_solaris, this is defined in port/.../tas.s */
 | 
			
		||||
 | 
			
		||||
static int	tas(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* i86pc_solaris || sparc_solaris */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * AIX (POWER)
 | 
			
		||||
 *
 | 
			
		||||
 * Note that slock_t on POWER/POWER2/PowerPC is int instead of char
 | 
			
		||||
 * (see storage/ipc.h).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(aix)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (cs((int *) (lock), 0, 1)) \ 
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* aix */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * HP-UX (PA-RISC)
 | 
			
		||||
 *
 | 
			
		||||
 * Note that slock_t on PA-RISC is a structure instead of char
 | 
			
		||||
 * (see storage/ipc.h).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(hpux)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
* a "set" slock_t has a single word cleared.  a "clear" slock_t has
 | 
			
		||||
* all words set to non-zero.
 | 
			
		||||
*/
 | 
			
		||||
static slock_t clear_lock = {-1, -1, -1, -1};
 | 
			
		||||
 | 
			
		||||
static int	tas(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = clear_lock)			/* struct assignment */
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK_FREE(lock)	( *(int *) (((long) (lock) + 15) & ~15) != 0)
 | 
			
		||||
 | 
			
		||||
#endif							/* hpux */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * sun3
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(sun3)
 | 
			
		||||
 | 
			
		||||
static int	tas(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#define S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#ifdef NOT_USED
 | 
			
		||||
static int
 | 
			
		||||
tas_dummy()
 | 
			
		||||
{
 | 
			
		||||
	asm("LLA0:");
 | 
			
		||||
	asm("	.data");
 | 
			
		||||
	asm("	.text");
 | 
			
		||||
	asm("|#PROC# 04");
 | 
			
		||||
	asm("	.globl	_tas");
 | 
			
		||||
	asm("_tas:");
 | 
			
		||||
	asm("|#PROLOGUE# 1");
 | 
			
		||||
	asm("	movel   sp@(0x4),a0");
 | 
			
		||||
	asm("	tas	a0@");
 | 
			
		||||
	asm("	beq	LLA1");
 | 
			
		||||
	asm("	moveq   #-128,d0");
 | 
			
		||||
	asm("	rts");
 | 
			
		||||
	asm("LLA1:");
 | 
			
		||||
	asm("	moveq   #0,d0");
 | 
			
		||||
	asm("	rts");
 | 
			
		||||
	asm("	.data");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif							/* sun3 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * sparc machines
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(NEED_SPARC_TAS_ASM)
 | 
			
		||||
 | 
			
		||||
/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
 | 
			
		||||
#if defined(__STRICT_ANSI__)
 | 
			
		||||
#define asm(x)	__asm__(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int	tas(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#ifdef NOT_USED
 | 
			
		||||
static int
 | 
			
		||||
tas_dummy()
 | 
			
		||||
{
 | 
			
		||||
	asm(".seg \"data\"");
 | 
			
		||||
	asm(".seg \"text\"");
 | 
			
		||||
	asm(".global _tas");
 | 
			
		||||
	asm("_tas:");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Sparc atomic test and set (sparc calls it "atomic load-store")
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	asm("ldstub [%r8], %r8");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Did test and set actually do the set?
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	asm("tst %r8");
 | 
			
		||||
 | 
			
		||||
	asm("be,a ReturnZero");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * otherwise, just return.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	asm("clr %r8");
 | 
			
		||||
	asm("mov 0x1, %r8");
 | 
			
		||||
	asm("ReturnZero:");
 | 
			
		||||
	asm("retl");
 | 
			
		||||
	asm("nop");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(addr)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(addr)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * addr should be as in the above S_LOCK routine
 | 
			
		||||
 */
 | 
			
		||||
#define	S_UNLOCK(addr)	(*(addr) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(addr)	(*(addr) = 0)
 | 
			
		||||
 | 
			
		||||
#endif							/* NEED_SPARC_TAS_ASM */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * i386 based things
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(NEED_I386_TAS_ASM)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							slock_t		res; \
 | 
			
		||||
							do \
 | 
			
		||||
							{ \
 | 
			
		||||
				__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1)); \
 | 
			
		||||
							} while (res != 0); \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* NEED_I386_TAS_ASM */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(__alpha__) && defined(linux)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							slock_t		res; \
 | 
			
		||||
							do \
 | 
			
		||||
							{ \
 | 
			
		||||
								__asm__("    ldq   $0, %0	     \n\
 | 
			
		||||
							     bne   $0, already_set   \n\
 | 
			
		||||
							     ldq_l $0, %0	     \n\
 | 
			
		||||
							     bne   $0, already_set   \n\
 | 
			
		||||
							     or    $31, 1, $0	     \n\
 | 
			
		||||
							     stq_c $0, %0	     \n\
 | 
			
		||||
							     beq   $0, stqc_fail     \n\
 | 
			
		||||
					success:     bis   $31, $31, %1      \n\
 | 
			
		||||
							     mb		             \n\
 | 
			
		||||
							     jmp   $31, end	     \n\
 | 
			
		||||
					stqc_fail:   or    $31, 1, $0	     \n\
 | 
			
		||||
					already_set: bis   $0, $0, %1	     \n\
 | 
			
		||||
					end:	     nop      ": "=m"(*lock), "=r"(res): :"0"); \
 | 
			
		||||
							} while (res != 0); \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
						
 | 
			
		||||
#define	S_UNLOCK(lock)	(__asm__("mb"),	*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* defined(__alpha__) && defined(linux) */
 | 
			
		||||
 | 
			
		||||
#if defined(linux) && defined(sparc)
 | 
			
		||||
 | 
			
		||||
#define S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							slock_t		res; \
 | 
			
		||||
							do \
 | 
			
		||||
							{ \
 | 
			
		||||
								__asm__("ldstub [%1], %0" \
 | 
			
		||||
						:		"=&r"(res) \
 | 
			
		||||
						:		"r"(lock)); \
 | 
			
		||||
							} while (!res != 0); \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* defined(linux) && defined(sparc) */
 | 
			
		||||
 | 
			
		||||
#if defined(linux) && defined(PPC)
 | 
			
		||||
 | 
			
		||||
#ifdef NOT_USED
 | 
			
		||||
static int
 | 
			
		||||
tas_dummy()
 | 
			
		||||
{
 | 
			
		||||
	__asm__("	\n\
 | 
			
		||||
tas:			\n\
 | 
			
		||||
	lwarx	5,0,3	\n\
 | 
			
		||||
	cmpwi	5,0	\n\
 | 
			
		||||
	bne	fail	\n\
 | 
			
		||||
	addi	5,5,1	\n\
 | 
			
		||||
        stwcx.  5,0,3	\n\
 | 
			
		||||
        beq	success	\n\
 | 
			
		||||
fail:	li	3,1	\n\
 | 
			
		||||
	blr		\n\
 | 
			
		||||
success:		\n\
 | 
			
		||||
	li 3,0		\n\
 | 
			
		||||
        blr		\n\
 | 
			
		||||
	");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \ 
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* defined(linux) && defined(PPC) */
 | 
			
		||||
 | 
			
		||||
#endif							/* HAS_TEST_AND_SET */
 | 
			
		||||
 | 
			
		||||
#endif							/* S_LOCK_H */ 
 | 
			
		||||
/*-------------------------------------------------------------------------
 | 
			
		||||
 *
 | 
			
		||||
 * s_lock.h--
 | 
			
		||||
 *	   This file contains the implementation (if any) for spinlocks.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 1994, Regents of the University of California
 | 
			
		||||
 *
 | 
			
		||||
 *
 | 
			
		||||
 * IDENTIFICATION
 | 
			
		||||
 *	  $Header: /cvsroot/pgsql/src/include/storage/s_lock.h,v 1.1 1997/09/18 14:20:59 momjian Exp $
 | 
			
		||||
 *
 | 
			
		||||
 *-------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
/*
 | 
			
		||||
 *	 DESCRIPTION
 | 
			
		||||
 *		The following code fragment should be written (in assembly
 | 
			
		||||
 *		language) on machines that have a native test-and-set instruction:
 | 
			
		||||
 *
 | 
			
		||||
 *		void
 | 
			
		||||
 *		S_LOCK(char_address)
 | 
			
		||||
 *			char *char_address;
 | 
			
		||||
 *		{
 | 
			
		||||
 *			while (test_and_set(char_address))
 | 
			
		||||
 *				;
 | 
			
		||||
 *		}
 | 
			
		||||
 *
 | 
			
		||||
 *		If this is not done, POSTGRES will default to using System V
 | 
			
		||||
 *		semaphores (and take a large performance hit -- around 40% of
 | 
			
		||||
 *		its time on a DS5000/240 is spent in semop(3)...).
 | 
			
		||||
 *
 | 
			
		||||
 *	 NOTES
 | 
			
		||||
 *		AIX has a test-and-set but the recommended interface is the cs(3)
 | 
			
		||||
 *		system call.  This provides an 8-instruction (plus system call
 | 
			
		||||
 *		overhead) uninterruptible compare-and-set operation.  True
 | 
			
		||||
 *		spinlocks might be faster but using cs(3) still speeds up the
 | 
			
		||||
 *		regression test suite by about 25%.  I don't have an assembler
 | 
			
		||||
 *		manual for POWER in any case.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
#ifndef S_LOCK_H
 | 
			
		||||
#define S_LOCK_H
 | 
			
		||||
 | 
			
		||||
#include "storage/ipc.h"
 | 
			
		||||
 | 
			
		||||
#if defined(HAS_TEST_AND_SET)
 | 
			
		||||
 | 
			
		||||
#if defined (nextstep)
 | 
			
		||||
/*
 | 
			
		||||
 * NEXTSTEP (mach)
 | 
			
		||||
 * slock_t is defined as a struct mutex.
 | 
			
		||||
 */
 | 
			
		||||
#define	S_LOCK(lock)	mutex_lock(lock)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	mutex_unlock(lock)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	mutex_init(lock)
 | 
			
		||||
 | 
			
		||||
 /* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
 | 
			
		||||
/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
 | 
			
		||||
#define	S_LOCK_FREE(alock)	((alock)->lock == 0)
 | 
			
		||||
 | 
			
		||||
#endif							/* next */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(irix5)
 | 
			
		||||
/*
 | 
			
		||||
 * SGI IRIX 5
 | 
			
		||||
 * slock_t is defined as a struct abilock_t, which has a single unsigned long
 | 
			
		||||
 * member.
 | 
			
		||||
 *
 | 
			
		||||
 * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
 | 
			
		||||
 * assembly from his NECEWS SVR4 port, but we probably ought to retain this
 | 
			
		||||
 * for the R3000 chips out there.
 | 
			
		||||
 */
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (!acquire_lock(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define S_UNLOCK(lock)	release_lock(lock)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	init_lock(lock)
 | 
			
		||||
 | 
			
		||||
/* S_LOCK_FREE should return 1 if lock is free; 0 if lock is locked */
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK_FREE(lock)	(stat_lock(lock) == UNLOCKED)
 | 
			
		||||
 | 
			
		||||
#endif							/* irix5 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * OSF/1 (Alpha AXP)
 | 
			
		||||
 *
 | 
			
		||||
 * Note that slock_t on the Alpha AXP is msemaphore instead of char
 | 
			
		||||
 * (see storage/ipc.h).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(__alpha__) || defined(__alpha)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (msem_lock((lock), MSEM_IF_NOWAIT) < 0) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	msem_unlock((lock), 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	msem_init((lock), MSEM_UNLOCKED)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK_FREE(lock)	(!(lock)->msem_state)
 | 
			
		||||
 | 
			
		||||
#endif							/* alpha */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Solaris 2
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(i386_solaris) || \
 | 
			
		||||
	defined(sparc_solaris)
 | 
			
		||||
/* for xxxxx_solaris, this is defined in port/.../tas.s */
 | 
			
		||||
 | 
			
		||||
static int	tas(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* i86pc_solaris || sparc_solaris */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * AIX (POWER)
 | 
			
		||||
 *
 | 
			
		||||
 * Note that slock_t on POWER/POWER2/PowerPC is int instead of char
 | 
			
		||||
 * (see storage/ipc.h).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(aix)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (cs((int *) (lock), 0, 1)) \ 
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* aix */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * HP-UX (PA-RISC)
 | 
			
		||||
 *
 | 
			
		||||
 * Note that slock_t on PA-RISC is a structure instead of char
 | 
			
		||||
 * (see storage/ipc.h).
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(hpux)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
* a "set" slock_t has a single word cleared.  a "clear" slock_t has
 | 
			
		||||
* all words set to non-zero.
 | 
			
		||||
*/
 | 
			
		||||
static slock_t clear_lock = {-1, -1, -1, -1};
 | 
			
		||||
 | 
			
		||||
static int	tas(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = clear_lock)			/* struct assignment */
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK_FREE(lock)	( *(int *) (((long) (lock) + 15) & ~15) != 0)
 | 
			
		||||
 | 
			
		||||
#endif							/* hpux */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * sun3
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(sun3)
 | 
			
		||||
 | 
			
		||||
static int	tas(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#define S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#ifdef NOT_USED
 | 
			
		||||
static int
 | 
			
		||||
tas_dummy()
 | 
			
		||||
{
 | 
			
		||||
	asm("LLA0:");
 | 
			
		||||
	asm("	.data");
 | 
			
		||||
	asm("	.text");
 | 
			
		||||
	asm("|#PROC# 04");
 | 
			
		||||
	asm("	.globl	_tas");
 | 
			
		||||
	asm("_tas:");
 | 
			
		||||
	asm("|#PROLOGUE# 1");
 | 
			
		||||
	asm("	movel   sp@(0x4),a0");
 | 
			
		||||
	asm("	tas	a0@");
 | 
			
		||||
	asm("	beq	LLA1");
 | 
			
		||||
	asm("	moveq   #-128,d0");
 | 
			
		||||
	asm("	rts");
 | 
			
		||||
	asm("LLA1:");
 | 
			
		||||
	asm("	moveq   #0,d0");
 | 
			
		||||
	asm("	rts");
 | 
			
		||||
	asm("	.data");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif							/* sun3 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * sparc machines
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(NEED_SPARC_TAS_ASM)
 | 
			
		||||
 | 
			
		||||
/* if we're using -ansi w/ gcc, use __asm__ instead of asm */
 | 
			
		||||
#if defined(__STRICT_ANSI__)
 | 
			
		||||
#define asm(x)	__asm__(x)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int	tas(slock_t *lock);
 | 
			
		||||
 | 
			
		||||
#ifdef NOT_USED
 | 
			
		||||
static int
 | 
			
		||||
tas_dummy()
 | 
			
		||||
{
 | 
			
		||||
	asm(".seg \"data\"");
 | 
			
		||||
	asm(".seg \"text\"");
 | 
			
		||||
	asm(".global _tas");
 | 
			
		||||
	asm("_tas:");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Sparc atomic test and set (sparc calls it "atomic load-store")
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	asm("ldstub [%r8], %r8");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Did test and set actually do the set?
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	asm("tst %r8");
 | 
			
		||||
 | 
			
		||||
	asm("be,a ReturnZero");
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * otherwise, just return.
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	asm("clr %r8");
 | 
			
		||||
	asm("mov 0x1, %r8");
 | 
			
		||||
	asm("ReturnZero:");
 | 
			
		||||
	asm("retl");
 | 
			
		||||
	asm("nop");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(addr)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(addr)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * addr should be as in the above S_LOCK routine
 | 
			
		||||
 */
 | 
			
		||||
#define	S_UNLOCK(addr)	(*(addr) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(addr)	(*(addr) = 0)
 | 
			
		||||
 | 
			
		||||
#endif							/* NEED_SPARC_TAS_ASM */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * i386 based things
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(NEED_I386_TAS_ASM)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							slock_t		res; \
 | 
			
		||||
							do \
 | 
			
		||||
							{ \
 | 
			
		||||
				__asm__("xchgb %0,%1": "=q"(res), "=m"(*lock):"0"(0x1)); \
 | 
			
		||||
							} while (res != 0); \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* NEED_I386_TAS_ASM */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if defined(__alpha__) && defined(linux)
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							slock_t		res; \
 | 
			
		||||
							do \
 | 
			
		||||
							{ \
 | 
			
		||||
								__asm__("    ldq   $0, %0	     \n\
 | 
			
		||||
							     bne   $0, already_set   \n\
 | 
			
		||||
							     ldq_l $0, %0	     \n\
 | 
			
		||||
							     bne   $0, already_set   \n\
 | 
			
		||||
							     or    $31, 1, $0	     \n\
 | 
			
		||||
							     stq_c $0, %0	     \n\
 | 
			
		||||
							     beq   $0, stqc_fail     \n\
 | 
			
		||||
					success:     bis   $31, $31, %1      \n\
 | 
			
		||||
							     mb		             \n\
 | 
			
		||||
							     jmp   $31, end	     \n\
 | 
			
		||||
					stqc_fail:   or    $31, 1, $0	     \n\
 | 
			
		||||
					already_set: bis   $0, $0, %1	     \n\
 | 
			
		||||
					end:	     nop      ": "=m"(*lock), "=r"(res): :"0"); \
 | 
			
		||||
							} while (res != 0); \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
						
 | 
			
		||||
#define	S_UNLOCK(lock)	(__asm__("mb"),	*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* defined(__alpha__) && defined(linux) */
 | 
			
		||||
 | 
			
		||||
#if defined(linux) && defined(sparc)
 | 
			
		||||
 | 
			
		||||
#define S_LOCK(lock)	do \
 | 
			
		||||
						{ \
 | 
			
		||||
							slock_t		res; \
 | 
			
		||||
							do \
 | 
			
		||||
							{ \
 | 
			
		||||
								__asm__("ldstub [%1], %0" \
 | 
			
		||||
						:		"=&r"(res) \
 | 
			
		||||
						:		"r"(lock)); \
 | 
			
		||||
							} while (!res != 0); \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* defined(linux) && defined(sparc) */
 | 
			
		||||
 | 
			
		||||
#if defined(linux) && defined(PPC)
 | 
			
		||||
 | 
			
		||||
#ifdef NOT_USED
 | 
			
		||||
static int
 | 
			
		||||
tas_dummy()
 | 
			
		||||
{
 | 
			
		||||
	__asm__("	\n\
 | 
			
		||||
tas:			\n\
 | 
			
		||||
	lwarx	5,0,3	\n\
 | 
			
		||||
	cmpwi	5,0	\n\
 | 
			
		||||
	bne	fail	\n\
 | 
			
		||||
	addi	5,5,1	\n\
 | 
			
		||||
        stwcx.  5,0,3	\n\
 | 
			
		||||
        beq	success	\n\
 | 
			
		||||
fail:	li	3,1	\n\
 | 
			
		||||
	blr		\n\
 | 
			
		||||
success:		\n\
 | 
			
		||||
	li 3,0		\n\
 | 
			
		||||
        blr		\n\
 | 
			
		||||
	");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	S_LOCK(lock)	do \ 
 | 
			
		||||
						{ \
 | 
			
		||||
							while (tas(lock)) \
 | 
			
		||||
								; \
 | 
			
		||||
						} while (0)
 | 
			
		||||
 | 
			
		||||
#define	S_UNLOCK(lock)	(*(lock) = 0)
 | 
			
		||||
 | 
			
		||||
#define	S_INIT_LOCK(lock)	S_UNLOCK(lock)
 | 
			
		||||
 | 
			
		||||
#endif							/* defined(linux) && defined(PPC) */
 | 
			
		||||
 | 
			
		||||
#endif							/* HAS_TEST_AND_SET */
 | 
			
		||||
 | 
			
		||||
#endif							/* S_LOCK_H */ 
 | 
			
		||||
@@ -6,7 +6,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 1994, Regents of the University of California
 | 
			
		||||
 *
 | 
			
		||||
 * $Id: spin.h,v 1.5 1997/09/08 02:39:14 momjian Exp $
 | 
			
		||||
 * $Id: spin.h,v 1.6 1997/09/18 14:21:02 momjian Exp $
 | 
			
		||||
 *
 | 
			
		||||
 *-------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
@@ -29,7 +29,7 @@ typedef int SPINLOCK;
 | 
			
		||||
 | 
			
		||||
extern bool CreateSpinlocks(IPCKey key);
 | 
			
		||||
extern bool InitSpinLocks(int init, IPCKey key);
 | 
			
		||||
extern void SpinAcquire(SPINLOCK lock);
 | 
			
		||||
extern void SpinRelease(SPINLOCK lock);
 | 
			
		||||
extern void SpinAcquire(SPINLOCK lockid);
 | 
			
		||||
extern void SpinRelease(SPINLOCK lockid);
 | 
			
		||||
 | 
			
		||||
#endif							/* SPIN_H */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user