mirror of
https://github.com/samba-team/samba.git
synced 2025-03-01 04:58:35 +03:00
Changed to sourceforge tdb code. This includes spinlocks (so we now have
a --with-spinlocks option to configure, this does mean the on-disk tdb format has changed, so 2.2alphaX sites will need to re-create their tdb's. The upside is no more tdb fragmentation and a +5% on netbench. Swings and roundabouts.... Jeremy. (This used to be commit 9dea7b7c257db487f8ced7dad3fce92fba03ea91)
This commit is contained in:
parent
1cd8538b7a
commit
7e4c4721b4
@ -95,7 +95,7 @@ QUOTAOBJS=@QUOTAOBJS@
|
||||
# object file lists
|
||||
######################################################################
|
||||
|
||||
TDB_OBJ = tdb/tdb.o tdb/tdbutil.o
|
||||
TDB_OBJ = tdb/tdb.o tdb/spinlock.o tdb/tdbutil.o
|
||||
|
||||
LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
|
||||
lib/getsmbpass.o lib/interface.o lib/kanji.o lib/md4.o \
|
||||
|
@ -132,3 +132,8 @@
|
||||
#undef PUTUTLINE_RETURNS_UTMP
|
||||
#undef COMPILER_SUPPORTS_LL
|
||||
#undef HAVE_YP_GET_DEFAULT_DOMAIN
|
||||
#undef USE_SPINLOCKS
|
||||
#undef SPARC_SPINLOCKS
|
||||
#undef INTEL_SPINLOCKS
|
||||
#undef MIPS_SPINLOCKS
|
||||
#undef POWERPC_SPINLOCKS
|
||||
|
1345
source3/configure
vendored
1345
source3/configure
vendored
File diff suppressed because it is too large
Load Diff
@ -1902,6 +1902,29 @@ else
|
||||
echo "no"
|
||||
fi
|
||||
|
||||
AC_ARG_WITH(spinlocks, [ --with-spinlocks use spin locks instead of fcntl locks ])
|
||||
if test "x$with_spinlocks" = "xyes"; then
|
||||
AC_DEFINE(USE_SPINLOCKS)
|
||||
|
||||
case "$host_cpu" in
|
||||
sparc)
|
||||
AC_DEFINE(SPARC_SPINLOCKS)
|
||||
;;
|
||||
|
||||
i386|i486|i586|i686)
|
||||
AC_DEFINE(INTEL_SPINLOCKS)
|
||||
;;
|
||||
|
||||
mips)
|
||||
AC_DEFINE(MIPS_SPINLOCKS)
|
||||
;;
|
||||
|
||||
powerpc)
|
||||
AC_DEFINE(POWERPC_SPINLOCKS)
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo "checking configure summary"
|
||||
AC_TRY_RUN([#include "${srcdir-.}/tests/summary.c"],
|
||||
echo "configure OK";,
|
||||
|
@ -195,6 +195,11 @@
|
||||
#undef PUTUTLINE_RETURNS_UTMP
|
||||
#undef COMPILER_SUPPORTS_LL
|
||||
#undef HAVE_YP_GET_DEFAULT_DOMAIN
|
||||
#undef USE_SPINLOCKS
|
||||
#undef SPARC_SPINLOCKS
|
||||
#undef INTEL_SPINLOCKS
|
||||
#undef MIPS_SPINLOCKS
|
||||
#undef POWERPC_SPINLOCKS
|
||||
|
||||
/* The number of bytes in a int. */
|
||||
#undef SIZEOF_INT
|
||||
|
@ -606,6 +606,7 @@ extern int errno;
|
||||
#include "ubi_dLinkList.h"
|
||||
#include "dlinklist.h"
|
||||
#include "../tdb/tdb.h"
|
||||
#include "../tdb/spinlock.h"
|
||||
#include "talloc.h"
|
||||
#include "interfaces.h"
|
||||
#include "hash.h"
|
||||
|
@ -4006,23 +4006,34 @@ int smbw_stat_printjob(struct smbw_server *srv,char *path,
|
||||
int smbw_fstat(int fd, struct stat *st);
|
||||
int smbw_stat(const char *fname, struct stat *st);
|
||||
|
||||
/*The following definitions come from tdb/spinlock.c */
|
||||
|
||||
int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
|
||||
int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
|
||||
int tdb_create_rwlocks(int fd, unsigned int hash_size);
|
||||
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
|
||||
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
|
||||
|
||||
/*The following definitions come from tdb/tdb.c */
|
||||
|
||||
char *tdb_error(TDB_CONTEXT *tdb);
|
||||
int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf);
|
||||
void tdb_printfreelist(TDB_CONTEXT *tdb);
|
||||
const char *tdb_errorstr(TDB_CONTEXT *tdb);
|
||||
TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
int tdb_traverse(TDB_CONTEXT *tdb, int (*fn)(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void* state), void* state);
|
||||
int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state);
|
||||
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
|
||||
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey);
|
||||
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
|
||||
TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
|
||||
int open_flags, mode_t mode);
|
||||
int tdb_close(TDB_CONTEXT *tdb);
|
||||
int tdb_lockchain(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
int tdb_unlockchain(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
void tdb_printfreelist(TDB_CONTEXT *tdb);
|
||||
int tdb_lockall(TDB_CONTEXT *tdb);
|
||||
void tdb_unlockall(TDB_CONTEXT *tdb);
|
||||
int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]);
|
||||
void tdb_unlockkeys(TDB_CONTEXT *tdb);
|
||||
int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
void tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
|
||||
/*The following definitions come from tdb/tdbutil.c */
|
||||
|
||||
|
@ -174,7 +174,7 @@ BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len, BOOL dupli
|
||||
kbuf = message_key_pid(pid);
|
||||
|
||||
/* lock the record for the destination */
|
||||
tdb_lockchain(tdb, kbuf);
|
||||
tdb_chainlock(tdb, kbuf);
|
||||
|
||||
dbuf = tdb_fetch(tdb, kbuf);
|
||||
|
||||
@ -208,7 +208,7 @@ BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len, BOOL dupli
|
||||
if (!len || (len && !memcmp( ptr + sizeof(rec), (char *)buf, len))) {
|
||||
DEBUG(10,("message_send_pid: discarding duplicate message.\n"));
|
||||
free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
@ -232,11 +232,11 @@ BOOL message_send_pid(pid_t pid, int msg_type, void *buf, size_t len, BOOL dupli
|
||||
free(dbuf.dptr);
|
||||
|
||||
ok:
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return message_notify(pid);
|
||||
|
||||
failed:
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -253,7 +253,7 @@ static BOOL message_recv(int *msg_type, pid_t *src, void **buf, size_t *len)
|
||||
|
||||
kbuf = message_key_pid(sys_getpid());
|
||||
|
||||
tdb_lockchain(tdb, kbuf);
|
||||
tdb_chainlock(tdb, kbuf);
|
||||
|
||||
dbuf = tdb_fetch(tdb, kbuf);
|
||||
if (dbuf.dptr == NULL || dbuf.dsize == 0) goto failed;
|
||||
@ -288,11 +288,11 @@ static BOOL message_recv(int *msg_type, pid_t *src, void **buf, size_t *len)
|
||||
tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
|
||||
|
||||
free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return True;
|
||||
|
||||
failed:
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return False;
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat
|
||||
struct lock_key *key;
|
||||
int count, i;
|
||||
|
||||
tdb_lockchain(tdb, kbuf);
|
||||
tdb_chainlock(tdb, kbuf);
|
||||
|
||||
locks = (struct lock_struct *)dbuf.dptr;
|
||||
key = (struct lock_key *)kbuf.dptr;
|
||||
@ -147,7 +147,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat
|
||||
tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
|
||||
}
|
||||
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
|
||||
|
||||
dbuf.dptr = NULL;
|
||||
|
||||
tdb_lockchain(tdb, kbuf);
|
||||
tdb_chainlock(tdb, kbuf);
|
||||
dbuf = tdb_fetch(tdb, kbuf);
|
||||
|
||||
lock.context.smbpid = smbpid;
|
||||
@ -218,12 +218,12 @@ BOOL brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
|
||||
tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
|
||||
|
||||
free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return True;
|
||||
|
||||
fail:
|
||||
if (dbuf.dptr) free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -244,7 +244,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
|
||||
|
||||
dbuf.dptr = NULL;
|
||||
|
||||
tdb_lockchain(tdb, kbuf);
|
||||
tdb_chainlock(tdb, kbuf);
|
||||
dbuf = tdb_fetch(tdb, kbuf);
|
||||
|
||||
if (!dbuf.dptr) {
|
||||
@ -292,7 +292,7 @@ smbpid = %u, pid = %u, tid = %u\n",
|
||||
}
|
||||
|
||||
free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return True;
|
||||
}
|
||||
}
|
||||
@ -301,7 +301,7 @@ smbpid = %u, pid = %u, tid = %u\n",
|
||||
|
||||
fail:
|
||||
if (dbuf.dptr) free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -322,7 +322,7 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
|
||||
|
||||
dbuf.dptr = NULL;
|
||||
|
||||
tdb_lockchain(tdb, kbuf);
|
||||
tdb_chainlock(tdb, kbuf);
|
||||
dbuf = tdb_fetch(tdb, kbuf);
|
||||
|
||||
lock.context.smbpid = smbpid;
|
||||
@ -346,12 +346,12 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
|
||||
|
||||
/* no conflicts - we could have added it */
|
||||
free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return True;
|
||||
|
||||
fail:
|
||||
if (dbuf.dptr) free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
return False;
|
||||
}
|
||||
|
||||
@ -369,7 +369,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
|
||||
|
||||
dbuf.dptr = NULL;
|
||||
|
||||
tdb_lockchain(tdb, kbuf);
|
||||
tdb_chainlock(tdb, kbuf);
|
||||
dbuf = tdb_fetch(tdb, kbuf);
|
||||
|
||||
if (!dbuf.dptr) goto fail;
|
||||
@ -404,7 +404,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
|
||||
/* we didn't find it */
|
||||
fail:
|
||||
if (dbuf.dptr) free(dbuf.dptr);
|
||||
tdb_unlockchain(tdb, kbuf);
|
||||
tdb_chainunlock(tdb, kbuf);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -274,7 +274,7 @@ static TDB_DATA locking_key_fsp(files_struct *fsp)
|
||||
BOOL lock_share_entry(connection_struct *conn,
|
||||
SMB_DEV_T dev, SMB_INO_T inode)
|
||||
{
|
||||
return tdb_lockchain(tdb, locking_key(dev, inode)) == 0;
|
||||
return tdb_chainlock(tdb, locking_key(dev, inode)) == 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -283,7 +283,7 @@ BOOL lock_share_entry(connection_struct *conn,
|
||||
BOOL unlock_share_entry(connection_struct *conn,
|
||||
SMB_DEV_T dev, SMB_INO_T inode)
|
||||
{
|
||||
return tdb_unlockchain(tdb, locking_key(dev, inode)) == 0;
|
||||
return tdb_chainunlock(tdb, locking_key(dev, inode)) == 0;
|
||||
}
|
||||
|
||||
|
||||
@ -292,7 +292,7 @@ BOOL unlock_share_entry(connection_struct *conn,
|
||||
******************************************************************/
|
||||
BOOL lock_share_entry_fsp(files_struct *fsp)
|
||||
{
|
||||
return tdb_lockchain(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
|
||||
return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
@ -300,7 +300,7 @@ BOOL lock_share_entry_fsp(files_struct *fsp)
|
||||
******************************************************************/
|
||||
BOOL unlock_share_entry_fsp(files_struct *fsp)
|
||||
{
|
||||
return tdb_unlockchain(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
|
||||
return tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
|
@ -8,14 +8,14 @@ PROGS = tdbtest tdbtool tdbtorture
|
||||
|
||||
default: $(PROGS)
|
||||
|
||||
tdbtest: tdbtest.o tdb.o
|
||||
$(CC) $(CFLAGS) -o tdbtest tdbtest.o tdb.o -lgdbm
|
||||
tdbtest: tdbtest.o tdb.o spinlock.o
|
||||
$(CC) $(CFLAGS) -o tdbtest tdbtest.o tdb.o spinlock.o -lgdbm
|
||||
|
||||
tdbtool: tdbtool.o tdb.o
|
||||
$(CC) $(CFLAGS) -o tdbtool tdbtool.o tdb.o
|
||||
tdbtool: tdbtool.o tdb.o spinlock.o
|
||||
$(CC) $(CFLAGS) -o tdbtool tdbtool.o tdb.o spinlock.o
|
||||
|
||||
tdbtorture: tdbtorture.o tdb.o
|
||||
$(CC) $(CFLAGS) -o tdbtorture tdbtorture.o tdb.o
|
||||
$(CC) $(CFLAGS) -o tdbtorture tdbtorture.o tdb.o spinlock.o
|
||||
|
||||
clean:
|
||||
rm -f $(PROGS) *.o *~ *% core test.db test.tdb test.gdbm
|
||||
|
403
source3/tdb/spinlock.c
Normal file
403
source3/tdb/spinlock.c
Normal file
@ -0,0 +1,403 @@
|
||||
#if STANDALONE
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#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 "tdb.h"
|
||||
#include "spinlock.h"
|
||||
|
||||
#define DEBUG
|
||||
#else
|
||||
#include "includes.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)
|
||||
{
|
||||
*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)
|
||||
{
|
||||
int result;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
" eieio;"
|
||||
"0: lwarx %0,0,%1;"
|
||||
" cmpwi 0,%0,0;"
|
||||
" bne- 1f;"
|
||||
" stwcx. %2,0,%1;"
|
||||
" bne- 0b;"
|
||||
" sync;"
|
||||
"1:"
|
||||
: "=&r"(result)
|
||||
: "r"(lock), "r"(1)
|
||||
: "cr0", "memory");
|
||||
|
||||
return (result == 0) ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
static inline void __spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
asm volatile("sync");
|
||||
*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));
|
||||
return oldval > 0 ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
static inline void __spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
*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)
|
||||
|
||||
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));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void __spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
*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)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(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(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(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(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)
|
||||
{
|
||||
rwlock_t *rwlocks;
|
||||
|
||||
if (!tdb->map_ptr) return -1;
|
||||
rwlocks = (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)
|
||||
{
|
||||
rwlock_t *rwlocks;
|
||||
|
||||
if (!tdb->map_ptr) return -1;
|
||||
rwlocks = (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 size, i;
|
||||
rwlock_t *rwlocks;
|
||||
|
||||
size = (hash_size + 1) * sizeof(rwlock_t);
|
||||
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)
|
||||
{
|
||||
rwlock_t *rwlocks;
|
||||
unsigned i;
|
||||
|
||||
if (tdb->header.rwlocks == 0) return 0;
|
||||
if (!tdb->map_ptr) return -1;
|
||||
|
||||
/* We're mmapped here */
|
||||
rwlocks = (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
|
55
source3/tdb/spinlock.h
Normal file
55
source3/tdb/spinlock.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef __SPINLOCK_H__
|
||||
#define __SPINLOCK_H__
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "tdb.h"
|
||||
|
||||
#ifdef USE_SPINLOCKS
|
||||
|
||||
#define RWLOCK_BIAS 0x1000UL
|
||||
|
||||
/* OS SPECIFIC */
|
||||
#define MAX_BUSY_LOOPS 1000
|
||||
#undef USE_SCHED_YIELD
|
||||
|
||||
/* ARCH SPECIFIC */
|
||||
/* We should make sure these are padded to a cache line */
|
||||
#if defined(SPARC_SPINLOCKS)
|
||||
typedef volatile char spinlock_t;
|
||||
#elif defined(POWERPC_SPINLOCKS)
|
||||
typedef volatile unsigned long spinlock_t;
|
||||
#elif defined(INTEL_SPINLOCKS)
|
||||
typedef volatile int spinlock_t;
|
||||
#elif defined(MIPS_SPINLOCKS)
|
||||
typedef volatile unsigned long spinlock_t;
|
||||
#else
|
||||
#error Need to implement spinlock code in spinlock.h
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
spinlock_t lock;
|
||||
volatile int count;
|
||||
} rwlock_t;
|
||||
|
||||
int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
|
||||
int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
|
||||
int tdb_create_rwlocks(int fd, unsigned int hash_size);
|
||||
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
|
||||
|
||||
#else /* !USE_SPINLOCKS */
|
||||
#if 0
|
||||
#define tdb_create_rwlocks(fd, hash_size) 0
|
||||
#define tdb_spinlock(tdb, list, rw_type) (-1)
|
||||
#define tdb_spinunlock(tdb, list, rw_type) (-1)
|
||||
#else
|
||||
int tdb_spinlock(TDB_CONTEXT *tdb, int list, int rw_type);
|
||||
int tdb_spinunlock(TDB_CONTEXT *tdb, int list, int rw_type);
|
||||
int tdb_create_rwlocks(int fd, unsigned int hash_size);
|
||||
#endif
|
||||
int tdb_clear_spinlocks(TDB_CONTEXT *tdb);
|
||||
#endif
|
||||
|
||||
#endif
|
2336
source3/tdb/tdb.c
2336
source3/tdb/tdb.c
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,6 @@
|
||||
#ifndef __TDB_H__
|
||||
#define __TDB_H__
|
||||
|
||||
/*
|
||||
Unix SMB/Netbios implementation.
|
||||
Version 3.0
|
||||
@ -19,41 +22,10 @@
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
typedef unsigned tdb_len;
|
||||
typedef unsigned tdb_off;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TDB_MAGIC_FOOD "TDB file\n"
|
||||
|
||||
/* this is stored at the front of every database */
|
||||
struct tdb_header {
|
||||
char magic_food[32]; /* for /etc/magic */
|
||||
unsigned version; /* version of the code */
|
||||
unsigned hash_size; /* number of hash entries */
|
||||
tdb_off reserved[32];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char *dptr;
|
||||
size_t dsize;
|
||||
} TDB_DATA;
|
||||
|
||||
struct tdb_lock_type {
|
||||
unsigned count;
|
||||
unsigned ltype;
|
||||
};
|
||||
|
||||
/* this is the context structure that is returned from a db open */
|
||||
typedef struct {
|
||||
char *name; /* the name of the database */
|
||||
void *map_ptr; /* where it is currently mapped */
|
||||
int fd; /* open file descriptor for the database */
|
||||
tdb_len map_size; /* how much space has been mapped */
|
||||
int read_only; /* opened read-only */
|
||||
struct tdb_lock_type *locked; /* set if we have a chain locked */
|
||||
int ecode; /* error code for last tdb error */
|
||||
struct tdb_header header; /* a cached copy of the header */
|
||||
unsigned flags; /* the flags passed to tdb_open */
|
||||
} TDB_CONTEXT;
|
||||
|
||||
/* flags to tdb_store() */
|
||||
#define TDB_REPLACE 1
|
||||
@ -61,31 +33,94 @@ typedef struct {
|
||||
#define TDB_MODIFY 3
|
||||
|
||||
/* flags for tdb_open() */
|
||||
#define TDB_DEFAULT 0 /* just a readability place holder */
|
||||
#define TDB_CLEAR_IF_FIRST 1
|
||||
#define TDB_INTERNAL 2 /* don't store on disk */
|
||||
#define TDB_NOLOCK 4 /* don't do any locking */
|
||||
#define TDB_NOMMAP 8 /* don't use mmap */
|
||||
#define TDB_CONVERT 16 /* convert endian (internal use) */
|
||||
|
||||
#define TDB_ERRCODE(code, ret) ((tdb->ecode = (code)), ret)
|
||||
|
||||
/* error codes */
|
||||
enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
|
||||
TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOEXIST };
|
||||
TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOEXIST, TDB_ERR_NOLOCK };
|
||||
|
||||
#ifndef u32
|
||||
#define u32 unsigned
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *dptr;
|
||||
size_t dsize;
|
||||
} TDB_DATA;
|
||||
|
||||
typedef u32 tdb_len;
|
||||
typedef u32 tdb_off;
|
||||
|
||||
/* this is stored at the front of every database */
|
||||
struct tdb_header {
|
||||
char magic_food[32]; /* for /etc/magic */
|
||||
u32 version; /* version of the code */
|
||||
u32 hash_size; /* number of hash entries */
|
||||
tdb_off rwlocks;
|
||||
tdb_off reserved[31];
|
||||
};
|
||||
|
||||
struct tdb_lock_type {
|
||||
u32 count;
|
||||
u32 ltype;
|
||||
};
|
||||
|
||||
struct tdb_traverse_lock {
|
||||
struct tdb_traverse_lock *next;
|
||||
u32 off;
|
||||
u32 hash;
|
||||
};
|
||||
|
||||
/* this is the context structure that is returned from a db open */
|
||||
typedef struct tdb_context {
|
||||
char *name; /* the name of the database */
|
||||
void *map_ptr; /* where it is currently mapped */
|
||||
int fd; /* open file descriptor for the database */
|
||||
tdb_len map_size; /* how much space has been mapped */
|
||||
int read_only; /* opened read-only */
|
||||
struct tdb_lock_type *locked; /* array of chain locks */
|
||||
enum TDB_ERROR ecode; /* error code for last tdb error */
|
||||
struct tdb_header header; /* a cached copy of the header */
|
||||
u32 flags; /* the flags passed to tdb_open */
|
||||
u32 *lockedkeys; /* array of locked keys: first is #keys */
|
||||
struct tdb_traverse_lock travlocks; /* current traversal locks */
|
||||
struct tdb_context *next; /* all tdbs to avoid multiple opens */
|
||||
dev_t device; /* uniquely identifies this tdb */
|
||||
ino_t inode; /* uniquely identifies this tdb */
|
||||
} TDB_CONTEXT;
|
||||
|
||||
typedef int (*tdb_traverse_func)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *);
|
||||
|
||||
#if STANDALONE
|
||||
TDB_CONTEXT *tdb_open(char *name, int hash_size, int tdb_flags,
|
||||
int open_flags, mode_t mode);
|
||||
char *tdb_error(TDB_CONTEXT *tdb);
|
||||
int tdb_writelock(TDB_CONTEXT *tdb);
|
||||
int tdb_writeunlock(TDB_CONTEXT *tdb);
|
||||
enum TDB_ERROR tdb_error(TDB_CONTEXT *tdb);
|
||||
const char *tdb_errorstr(TDB_CONTEXT *tdb);
|
||||
TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
|
||||
int tdb_close(TDB_CONTEXT *tdb);
|
||||
TDB_DATA tdb_firstkey(TDB_CONTEXT *tdb);
|
||||
TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
int tdb_traverse(TDB_CONTEXT *tdb,
|
||||
int (*fn)(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state),
|
||||
void *state);
|
||||
int tdb_traverse(TDB_CONTEXT *tdb, tdb_traverse_func fn, void *state);
|
||||
int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
int tdb_lockkeys(TDB_CONTEXT *tdb, u32 number, TDB_DATA keys[]);
|
||||
void tdb_unlockkeys(TDB_CONTEXT *tdb);
|
||||
int tdb_lockall(TDB_CONTEXT *tdb);
|
||||
void tdb_unlockall(TDB_CONTEXT *tdb);
|
||||
|
||||
/* Low level locking functions: use with care */
|
||||
int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
void tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key);
|
||||
extern TDB_DATA tdb_null;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* tdb.h */
|
||||
|
@ -32,7 +32,7 @@ int tdb_lock_bystring(TDB_CONTEXT *tdb, char *keyval)
|
||||
key.dptr = keyval;
|
||||
key.dsize = strlen(keyval)+1;
|
||||
|
||||
return tdb_lockchain(tdb, key);
|
||||
return tdb_chainlock(tdb, key);
|
||||
}
|
||||
|
||||
/* unlock a chain by string */
|
||||
@ -43,7 +43,7 @@ int tdb_unlock_bystring(TDB_CONTEXT *tdb, char *keyval)
|
||||
key.dptr = keyval;
|
||||
key.dsize = strlen(keyval)+1;
|
||||
|
||||
return tdb_unlockchain(tdb, key);
|
||||
return tdb_chainunlock(tdb, key);
|
||||
}
|
||||
|
||||
/* lock a chain by string key */
|
||||
|
Loading…
x
Reference in New Issue
Block a user