summaryrefslogtreecommitdiff
path: root/source4/lib/tdb/common/spinlock.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-09-16 03:52:42 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:38:12 -0500
commit0868b7c77d42efd5f361f605bfc0d8d46841db95 (patch)
treee73b6ca6bb895ff3b9af1006ffd566e7f2ee7ea8 /source4/lib/tdb/common/spinlock.c
parent95040e934175eb877ce6d83690fd06ce5d2b028c (diff)
downloadsamba-0868b7c77d42efd5f361f605bfc0d8d46841db95.tar.gz
samba-0868b7c77d42efd5f361f605bfc0d8d46841db95.tar.bz2
samba-0868b7c77d42efd5f361f605bfc0d8d46841db95.zip
r10253: a fairly large tdb cleanup and re-organise. Nearly all of this change
just involves splitting up the core tdb.c code into separate files on logical boundaries, but there are some minor functional changes as well: - move the 'struct tdb_context' into tdb_private.h, hiding it from users. This was done to allow the structure to change without breaking code that uses tdb. - added accessor functions tdb_fd(), tdb_name(), and tdb_log_fn() to access the elements of struct tdb_context that were used by external code but are no longer visible - simplied tdb_append() to use tdb_fetch()/tdb_store(), which is just as good due to the way tdb locks work - changed some of the types (such as tdb_off to tdb_off_t) to make syntax highlighting work better - removed the old optional spinlock code. It was a bad idea. - fixed a bug in tdb_reopen_all() that caused tdbtorture to sometimes fail or report nasty looking errors. This is the only real bug fixed in this commit. Jeremy/Jerry, you might like to pickup this change for Samba3, as that could definately affect smbd in Samba3. The aim of all of these changes is to make the tdb transactions/journaling code I am working on easier to write. I started to write it on top of the existing tdb.c code and it got very messy. Splitting up the code makes it much easier to follow. There are more cleanups we could do in tdb, such as using uint32_t instead of u32 (suggested by metze). I'll leave those for another day. (This used to be commit 4673cdd0d261614e707b72a7a348bb0e7dbb2482)
Diffstat (limited to 'source4/lib/tdb/common/spinlock.c')
-rw-r--r--source4/lib/tdb/common/spinlock.c482
1 files changed, 0 insertions, 482 deletions
diff --git a/source4/lib/tdb/common/spinlock.c b/source4/lib/tdb/common/spinlock.c
deleted file mode 100644
index 232cd8dfc6..0000000000
--- a/source4/lib/tdb/common/spinlock.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- trivial database library
-
- Copyright (C) Anton Blanchard 2001
-
- ** NOTE! The following LGPL license applies to the tdb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library 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
- Lesser 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
-*/
-#if HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#ifndef _SAMBA_BUILD_
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <signal.h>
-#include "tdb.h"
-
-#define DEBUG
-#else
-#include "includes.h"
-#include "lib/tdb/include/tdb.h"
-#include "system/filesys.h"
-#endif
-
-#ifdef USE_SPINLOCKS
-
-/*
- * ARCH SPECIFIC
- */
-
-#if defined(SPARC_SPINLOCKS)
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
- unsigned int result;
-
- asm volatile("ldstub [%1], %0"
- : "=r" (result)
- : "r" (lock)
- : "memory");
-
- return (result == 0) ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- asm volatile("":::"memory");
- *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- return (*lock != 0);
-}
-
-#elif defined(POWERPC_SPINLOCKS)
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
- unsigned int result;
-
- __asm__ __volatile__(
-"1: lwarx %0,0,%1\n\
- cmpwi 0,%0,0\n\
- li %0,0\n\
- bne- 2f\n\
- li %0,1\n\
- stwcx. %0,0,%1\n\
- bne- 1b\n\
- isync\n\
-2:" : "=&r"(result)
- : "r"(lock)
- : "cr0", "memory");
-
- return (result == 1) ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- asm volatile("eieio":::"memory");
- *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- return (*lock != 0);
-}
-
-#elif defined(INTEL_SPINLOCKS)
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
- int oldval;
-
- asm volatile("xchgl %0,%1"
- : "=r" (oldval), "=m" (*lock)
- : "0" (0)
- : "memory");
-
- return oldval > 0 ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- asm volatile("":::"memory");
- *lock = 1;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- *lock = 1;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- return (*lock != 1);
-}
-
-#elif defined(MIPS_SPINLOCKS) && defined(sgi) && (_COMPILER_VERSION >= 730)
-
-/* Implement spinlocks on IRIX using the MIPSPro atomic fetch operations. See
- * sync(3) for the details of the intrinsic operations.
- *
- * "sgi" and "_COMPILER_VERSION" are always defined by MIPSPro.
- */
-
-#ifndef _SAMBA_BUILD_
-
-/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */
-#define inline __inline
-
-#endif /* _SAMBA_BUILD_ */
-
-/* Returns 0 if the lock is acquired, EBUSY otherwise. */
-static inline int __spin_trylock(spinlock_t *lock)
-{
- unsigned int val;
- val = __lock_test_and_set(lock, 1);
- return val == 0 ? 0 : EBUSY;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- __lock_release(lock);
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- __lock_release(lock);
-}
-
-/* Returns 1 if the lock is held, 0 otherwise. */
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- unsigned int val;
- val = __add_and_fetch(lock, 0);
- return val;
-}
-
-#elif defined(MIPS_SPINLOCKS)
-
-static inline unsigned int load_linked(unsigned long addr)
-{
- unsigned int res;
-
- __asm__ __volatile__("ll\t%0,(%1)"
- : "=r" (res)
- : "r" (addr));
-
- return res;
-}
-
-static inline unsigned int store_conditional(unsigned long addr, unsigned int value)
-{
- unsigned int res;
-
- __asm__ __volatile__("sc\t%0,(%2)"
- : "=r" (res)
- : "0" (value), "r" (addr));
- return res;
-}
-
-static inline int __spin_trylock(spinlock_t *lock)
-{
- unsigned int mw;
-
- do {
- mw = load_linked(lock);
- if (mw)
- return EBUSY;
- } while (!store_conditional(lock, 1));
-
- asm volatile("":::"memory");
-
- return 0;
-}
-
-static inline void __spin_unlock(spinlock_t *lock)
-{
- asm volatile("":::"memory");
- *lock = 0;
-}
-
-static inline void __spin_lock_init(spinlock_t *lock)
-{
- *lock = 0;
-}
-
-static inline int __spin_is_locked(spinlock_t *lock)
-{
- return (*lock != 0);
-}
-
-#else
-#error Need to implement spinlock code in spinlock.c
-#endif
-
-/*
- * OS SPECIFIC
- */
-
-static void yield_cpu(void)
-{
- struct timespec tm;
-
-#ifdef USE_SCHED_YIELD
- sched_yield();
-#else
- /* Linux will busy loop for delays < 2ms on real time tasks */
- tm.tv_sec = 0;
- tm.tv_nsec = 2000000L + 1;
- nanosleep(&tm, NULL);
-#endif
-}
-
-static int this_is_smp(void)
-{
-#if defined(HAVE_SYSCONF) && defined(SYSCONF_SC_NPROC_ONLN)
- return (sysconf(_SC_NPROC_ONLN) > 1) ? 1 : 0;
-#else
- return 0;
-#endif
-}
-
-/*
- * GENERIC
- */
-
-static int smp_machine = 0;
-
-static inline void __spin_lock(spinlock_t *lock)
-{
- int ntries = 0;
-
- while(__spin_trylock(lock)) {
- while(__spin_is_locked(lock)) {
- if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
- continue;
- yield_cpu();
- }
- }
-}
-
-static void __read_lock(tdb_rwlock_t *rwlock)
-{
- int ntries = 0;
-
- while(1) {
- __spin_lock(&rwlock->lock);
-
- if (!(rwlock->count & RWLOCK_BIAS)) {
- rwlock->count++;
- __spin_unlock(&rwlock->lock);
- return;
- }
-
- __spin_unlock(&rwlock->lock);
-
- while(rwlock->count & RWLOCK_BIAS) {
- if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
- continue;
- yield_cpu();
- }
- }
-}
-
-static void __write_lock(tdb_rwlock_t *rwlock)
-{
- int ntries = 0;
-
- while(1) {
- __spin_lock(&rwlock->lock);
-
- if (rwlock->count == 0) {
- rwlock->count |= RWLOCK_BIAS;
- __spin_unlock(&rwlock->lock);
- return;
- }
-
- __spin_unlock(&rwlock->lock);
-
- while(rwlock->count != 0) {
- if (smp_machine && ntries++ < MAX_BUSY_LOOPS)
- continue;
- yield_cpu();
- }
- }
-}
-
-static void __write_unlock(tdb_rwlock_t *rwlock)
-{
- __spin_lock(&rwlock->lock);
-
-#ifdef DEBUG
- if (!(rwlock->count & RWLOCK_BIAS))
- fprintf(stderr, "bug: write_unlock\n");
-#endif
-
- rwlock->count &= ~RWLOCK_BIAS;
- __spin_unlock(&rwlock->lock);
-}
-
-static void __read_unlock(tdb_rwlock_t *rwlock)
-{
- __spin_lock(&rwlock->lock);
-
-#ifdef DEBUG
- if (!rwlock->count)
- fprintf(stderr, "bug: read_unlock\n");
-
- if (rwlock->count & RWLOCK_BIAS)
- fprintf(stderr, "bug: read_unlock\n");
-#endif
-
- rwlock->count--;
- __spin_unlock(&rwlock->lock);
-}
-
-/* TDB SPECIFIC */
-
-/* lock a list in the database. list -1 is the alloc list */
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type)
-{
- tdb_rwlock_t *rwlocks;
-
- if (!tdb->map_ptr) return -1;
- rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-
- switch(rw_type) {
- case F_RDLCK:
- __read_lock(&rwlocks[list+1]);
- break;
-
- case F_WRLCK:
- __write_lock(&rwlocks[list+1]);
- break;
-
- default:
- return TDB_ERRCODE(TDB_ERR_LOCK, -1);
- }
- return 0;
-}
-
-/* unlock the database. */
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type)
-{
- tdb_rwlock_t *rwlocks;
-
- if (!tdb->map_ptr) return -1;
- rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
-
- switch(rw_type) {
- case F_RDLCK:
- __read_unlock(&rwlocks[list+1]);
- break;
-
- case F_WRLCK:
- __write_unlock(&rwlocks[list+1]);
- break;
-
- default:
- return TDB_ERRCODE(TDB_ERR_LOCK, -1);
- }
-
- return 0;
-}
-
-int tdb_create_rwlocks(int fd, unsigned int hash_size)
-{
- unsigned int size, i;
- tdb_rwlock_t *rwlocks;
-
- size = TDB_SPINLOCK_SIZE(hash_size);
- rwlocks = malloc(size);
- if (!rwlocks)
- return -1;
-
- for(i = 0; i < hash_size+1; i++) {
- __spin_lock_init(&rwlocks[i].lock);
- rwlocks[i].count = 0;
- }
-
- /* Write it out (appending to end) */
- if (write(fd, rwlocks, size) != size) {
- free(rwlocks);
- return -1;
- }
- smp_machine = this_is_smp();
- free(rwlocks);
- return 0;
-}
-
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
-{
- tdb_rwlock_t *rwlocks;
- unsigned int i;
-
- if (tdb->header.rwlocks == 0) return 0;
- if (!tdb->map_ptr) return -1;
-
- /* We're mmapped here */
- rwlocks = (tdb_rwlock_t *)((char *)tdb->map_ptr + tdb->header.rwlocks);
- for(i = 0; i < tdb->header.hash_size+1; i++) {
- __spin_lock_init(&rwlocks[i].lock);
- rwlocks[i].count = 0;
- }
- return 0;
-}
-#else
-int tdb_create_rwlocks(int fd, unsigned int hash_size) { return 0; }
-int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
-int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type) { return -1; }
-
-/* Non-spinlock version: remove spinlock pointer */
-int tdb_clear_spinlocks(TDB_CONTEXT *tdb)
-{
- tdb_off off = (tdb_off)((char *)&tdb->header.rwlocks
- - (char *)&tdb->header);
-
- tdb->header.rwlocks = 0;
- if (lseek(tdb->fd, off, SEEK_SET) != off
- || write(tdb->fd, (void *)&tdb->header.rwlocks,
- sizeof(tdb->header.rwlocks))
- != sizeof(tdb->header.rwlocks))
- return -1;
- return 0;
-}
-#endif