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

📄 spinlock.c

📁 自己精简过的PPPD代码。在嵌入中应用可以更好的发挥。比原先的小了很多
💻 C
字号:
/*    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*/#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"#include "spinlock.h"#define DEBUG#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. */#ifdef STANDALONE/* MIPSPro 7.3 has "__inline" as an extension, but not "inline. */#define inline __inline#endif /* STANDALONE *//* 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 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 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;}#elseint 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

⌨️ 快捷键说明

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