📄 lislocks.c
字号:
/************************************************************************* LiS Locks *************************************************************************** ** Copyright (C) 2000 David Grothe, Gcom, Inc <dave@gcom.com> ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Library 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 ** Library General Public License for more details. ** ** You should have received a copy of the GNU Library General Public ** License along with this library; if not, write to the ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, ** Cambridge, MA 02139, USA. ** *************************************************************************/#ident "@(#) LiS lislocks.c 1.25 12/27/03"#include <sys/LiS/linux-mdep.h>#include <sys/LiS/strmdbg.h>#include <sys/lislocks.h>#include <sys/lismem.h>#include <linux/sched.h>#if defined(KERNEL_2_3) /* 2.3 kernel or later */#include <linux/spinlock.h>#elif defined(KERNEL_2_1) /* 2.1 and 2.2 kernels */#include <asm/spinlock.h>#else /* earlier kernels */ /* there will be syntax errors */#endif#if defined(KERNEL_2_5)#if defined(CONFIG_DEV)#define SAVE_FLAGS(x) local_save_flags(x)#else #define SAVE_FLAGS(x)#endif#else#if defined(CONFIG_DEV)#define SAVE_FLAGS(x) save_flags(x)#else #define SAVE_FLAGS(x)#endif#endif#define FL char *file, int line#if defined(CONFIG_DEV)#define SET_SPINNER \ lock->spinner_file = file ; \ lock->spinner_line = line ; \ lock->spinner_cntr = ++lis_seq_cntr ; #define SET_OWNER \ lock->owner_file = file ; \ lock->owner_line = line ; \ lock->owner_cntr = ++lis_seq_cntr ;#define SET_SPIN_UNLOCK \ lock->unlocker_file = file ; \ lock->unlocker_line = line ; \ lock->unlocker_cntr = ++lis_seq_cntr ;#define SPIN_FILL lis_spin_lock_fill(lock, name, file, line) #define RW_LOCK_FILL lis_rw_lock_fill(lock, name, file, line) #define SET_UPSEM \ lsem->upper_file = file ; \ lsem->upper_line = line ; \ lsem->upper_cntr = ++lis_seq_cntr ;#define SET_DSEM \ lsem->downer_file = file ; \ lsem->downer_line = line ; \ lsem->downer_cntr = ++lis_seq_cntr ;#define SET_SEMOWNER \ lsem->owner_file = file ; \ lsem->owner_line = line ; \ lsem->owner_cntr = ++lis_seq_cntr ;#else#define SET_SPINNER (void) prev ;#define SET_OWNER (void) prev ;#define SET_SPIN_UNLOCK (void) prev ;#define SET_UPSEM#define SET_DSEM#define SET_SEMOWNER#define SPIN_FILL lis_spin_lock_fill(lock, name) #define RW_LOCK_FILL lis_rw_lock_fill(lock, name) #endif/************************************************************************* Lock Contention *************************************************************************** ** Some global counters to keep track of spin lock contention. ** *************************************************************************/lis_atomic_t lis_spin_lock_count ;lis_atomic_t lis_spin_lock_contention_count ;/************************************************************************* SPL Implementation *************************************************************************** ** We use a global LiS spin lock to implement the SPL functions. ** *************************************************************************/lis_spin_lock_t lis_spl_lock ; /* for simulating spl fcns */lis_flags_t lis_psw0 ; /* base level psw value */#define USE_SPINLOCK 0#if defined(KERNEL_2_3) /* 2.4 kernel or later */#define THELOCK lock /* use passed-in lock */#define DCL_r rwlock_t *r = (rwlock_t *) lock->rw_lock_mem #else /* 2.2 kernel */#define THELOCK (&lis_spl_lock) /* use global lock */#endif#define DCL_l spinlock_t *l = (spinlock_t *) THELOCK->spin_lock_mem /************************************************************************* SPL Tracking *************************************************************************** ** The following structure is used to track SPL usage. ** *************************************************************************/typedef struct{ int type ; int cpu ; void *addr ; /* of lock or semaphore */ void *tskp ; /* current task */ lis_flags_t flags ; int state ; char *file ; int line ; int cntr ;} spl_track_t ;/* * Types */#define TRACK_SPLSTR 1 /* splstr call */#define TRACK_SPLX 2 /* splx call */#define TRACK_LOCK 3 /* some spinlock call */#define TRACK_UNLOCK 4 /* some unlock call */#define TRACK_DOWN 5 /* semaphore down */#define TRACK_UP 6 /* semaphore up */#define SPL_TRACK_SIZE 4096 /* power of 2 */spl_track_t lis_spl_track[SPL_TRACK_SIZE] ;spl_track_t *lis_spl_track_ptr = lis_spl_track ;/* * Note: this is a kernel lock, not an LiS lock. */spinlock_t lis_spl_track_lock = SPIN_LOCK_UNLOCKED ;#if defined(CONFIG_DEV)#define LOCK_ENTRY(lock,typ,fil,lin,flgs) \ if ( LIS_DEBUG_SPL_TRACE ) \ { \ spl_track_t *p ; \ lis_flags_t flags ; \ \ spin_lock_irqsave(&lis_spl_track_lock, flags) ; \ p = lis_spl_track_ptr ; \ if (++lis_spl_track_ptr >= &lis_spl_track[SPL_TRACK_SIZE]) \ lis_spl_track_ptr = lis_spl_track ; \ spin_unlock_irqrestore(&lis_spl_track_lock, flags) ; \ \ p->addr = (void *) (lock) ; \ p->tskp = (void *) (current) ; \ p->file = fil ; \ p->line = lin ; \ p->type = typ ; \ p->flags = flgs ; \ p->cntr = ++lis_seq_cntr ; \ p->cpu = smp_processor_id(); \ p->state = (lock)->nest ; \ }#define LOCK_EXIT(lock,typ,fil,lin,flgs) \ if ( LIS_DEBUG_SPL_TRACE ) \ { \ spl_track_t *p ; \ lis_flags_t flags ; \ \ spin_lock_irqsave(&lis_spl_track_lock, flags) ; \ p = lis_spl_track_ptr ; \ if (++lis_spl_track_ptr >= &lis_spl_track[SPL_TRACK_SIZE]) \ lis_spl_track_ptr = lis_spl_track ; \ spin_unlock_irqrestore(&lis_spl_track_lock, flags) ; \ \ p->addr = (void *) (lock) ; \ p->tskp = (void *) (current) ; \ p->file = fil ; \ p->line = lin ; \ p->type = typ ; \ p->flags = flgs ; \ p->cntr = ++lis_seq_cntr ; \ p->cpu = smp_processor_id(); \ p->state = (lock)->nest ; \ }#define SEM_ENTRY(sem,typ,fil,lin,flgs) \ if ( LIS_DEBUG_SPL_TRACE ) \ { \ spl_track_t *p ; \ lis_flags_t flags ; \ \ spin_lock_irqsave(&lis_spl_track_lock, flags) ; \ p = lis_spl_track_ptr ; \ if (++lis_spl_track_ptr >= &lis_spl_track[SPL_TRACK_SIZE]) \ lis_spl_track_ptr = lis_spl_track ; \ spin_unlock_irqrestore(&lis_spl_track_lock, flags) ; \ \ p->addr = (void *) (sem) ; \ p->tskp = (void *) (current) ; \ p->file = fil ; \ p->line = lin ; \ p->type = typ ; \ p->flags = flgs ; \ p->cntr = ++lis_seq_cntr ; \ p->cpu = smp_processor_id(); \ p->state = atomic_read(&((struct semaphore *) &sem->sem_mem)->count); \ }#define SEM_EXIT(sem,typ,fil,lin,flgs) \ if ( LIS_DEBUG_SPL_TRACE ) \ { \ spl_track_t *p ; \ lis_flags_t flags ; \ \ spin_lock_irqsave(&lis_spl_track_lock, flags) ; \ p = lis_spl_track_ptr ; \ if (++lis_spl_track_ptr >= &lis_spl_track[SPL_TRACK_SIZE]) \ lis_spl_track_ptr = lis_spl_track ; \ spin_unlock_irqrestore(&lis_spl_track_lock, flags) ; \ \ p->addr = (void *) (sem) ; \ p->tskp = (void *) (current) ; \ p->file = fil ; \ p->line = lin ; \ p->type = typ ; \ p->flags = flgs ; \ p->cntr = ++lis_seq_cntr ; \ p->cpu = smp_processor_id(); \ p->state = atomic_read(&((struct semaphore *) &sem->sem_mem)->count); \ }#else #define LOCK_ENTRY(lock,typ,fil,lin,flgs)#define LOCK_EXIT(lock,typ,fil,lin,flgs)#define SEM_ENTRY(sem,typ,fil,lin,flgs)#define SEM_EXIT(sem,typ,fil,lin,flgs)#endif /* CONFIG_DEV *//************************************************************************* Prototypes *************************************************************************/extern unsigned long lis_hitime(void); /* usec res; 64s cycle */extern int lis_seq_cntr ;/************************************************************************* lis_print_spl_track *************************************************************************** ** Print out the spl tracking table. ** *************************************************************************/void lis_print_spl_track(void){ spl_track_t *p ; char *typep ; int n ; printk("lis_print_spl_track: %lx lis_spl_track_ptr=%lx\n", (long)lis_spl_track, (long)lis_spl_track_ptr) ; for (p = lis_spl_track_ptr, n = SPL_TRACK_SIZE; n--;) { if (p->type != 0) { switch (p->type) { case TRACK_SPLSTR: typep = "splstr" ; break ; case TRACK_SPLX: typep = "splx " ; break ; case TRACK_LOCK: typep = "lock " ; break ; case TRACK_UNLOCK: typep = "unlock" ; break ; case TRACK_DOWN: typep = "down " ; break ; case TRACK_UP: typep = "up " ; break ; default: typep = "Unkwn " ; break ; } printk("%u:%s State=%d "#ifdef INT_PSW "Flgs=%03x "#else "Flgs=%03lx "#endif "%s #%u\n", p->cntr, typep, p->state, p->flags & 0x200, p->file, p->line) ; } if (++p >= &lis_spl_track[SPL_TRACK_SIZE]) p = lis_spl_track ; } printk("lis_print_spl_track: end of output\n") ; } /* lis_print_spl_track *//************************************************************************* lis_splstr *************************************************************************** ** Disable interrupts, return the previous state. ** *************************************************************************/lis_flags_t lis_splstr_fcn(char *file, int line){ lis_flags_t prev ; lis_spin_lock_irqsave_fcn(&lis_spl_lock, &prev, file, line) ; return(prev) ;} /* lis_splstr *//************************************************************************* lis_splx *************************************************************************** ** Restore state. ** *************************************************************************/void lis_splx_fcn(lis_flags_t x, char *file, int line){ lis_spin_unlock_irqrestore_fcn(&lis_spl_lock, &x, file, line) ;} /* lis_splx *//************************************************************************* lis_spl0 *************************************************************************** ** Go all the way back to base level. ** *************************************************************************/void lis_spl0_fcn(char *file, int line)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -