#if !defined(__LOG_H__)
#define __LOG_H__
#if defined(X86_BOOT_CODE) && defined([31mCONFIG_ESS_LOCK_ANALYSIS[0m)
#undef [31mCONFIG_ESS_LOCK_ANALYSIS[0m
#endif
#ifdef [31mCONFIG_ESS_LOCK_ANALYSIS[0m
#include <linux/kernel.h>
#include <linux/irqflags.h>
#include <linux/spinlock.h>
#include <linux/seqlock_types.h>
#include <linux/semaphore.h>
#include <linux/log_event.h>
#define DELIMITER "#"
#define DELIMITER_CHAR '#'
#define PING_CHAR 'p'
#define MK_STRING(x) #x
#define IO_PORT_LOG (0x00e9)
#define log_lock(_acquire,_lockmember,_ptr,_file,_line,_function,_irqsync) { \
spinlock_t *__spinlock; \
raw_spinlock_t *__rawspinlock; \
rwlock_t *__rwlock; \
struct mutex *__mutex; \
seqlock_t *__seqlock; \
const seqlock_t *__constseqlock; \
seqcount_t *__seqcount; \
const seqcount_t *__constseqcount; \
struct semaphore *__semaphore; \
struct rw_semaphore *__rwsemaphore; \
unsigned long *__bitspinlock; \
int status = log_preempt_count(); \
if (_ptr == (void*)PSEUDOLOCK_ADDR_RCU) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function,PSEUDOLOCK_NAME_RCU,status,_irqsync); \
} else if (_ptr == (void*)PSEUDOLOCK_ADDR_HARDIRQ) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function,PSEUDOLOCK_NAME_HARDIRQ,status,_irqsync); \
} else if (_ptr == (void*)PSEUDOLOCK_ADDR_SOFTIRQ) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function,PSEUDOLOCK_NAME_SOFTIRQ,status,_irqsync); \
} else if (__same_type(_ptr,__spinlock)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function,"spinlock_t",status,_irqsync); \
} else if (__same_type(_ptr,__rwlock)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function,"rwlock_t",status,_irqsync); \
} else if (__same_type(_ptr,__mutex)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function,"mutex",status,_irqsync); \
} else if (__same_type(_ptr,__seqlock) || __same_type(_ptr,__constseqlock)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function, "seqlock_t",status,_irqsync); \
} else if (__same_type(_ptr,__seqcount) || __same_type(_ptr,__constseqcount)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function, "seqcount_t",status,_irqsync); \
} else if (__same_type(_ptr,__rawspinlock)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function, "raw_spinlock_t",status,_irqsync); \
} else if (__same_type(_ptr,__semaphore)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function, "semaphore",status,_irqsync); \
} else if (__same_type(_ptr,__rwsemaphore)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function, "rw_semaphore",status,_irqsync); \
} else if (__same_type(_ptr,__bitspinlock)) { \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function, "bit_spin_lock",status,_irqsync); \
} else{ \
__log_lock(_acquire,_lockmember,_ptr,_file,_line,_function, "unknown",status,_irqsync); \
} \
}
extern struct log_action la_buffer;
int log_preempt_count(void);
/* Basic port I/O */
static inline void outb_(u8 v, u16 port)
{
asm volatile("outb %0,%1" : : "a" (v), "dN" (port));
}
static inline void log_memory(int alloc, const char *datatype, const void *ptr, size_t size) {
unsigned long flags;
raw_local_irq_save(flags);
memset(&la_buffer,0,sizeof(la_buffer));
la_buffer.action = (alloc == 1 ? 'a' : 'f');
la_buffer.ptr = (unsigned long)ptr;
la_buffer.size = size;
/*
* One could use a more safe string function, e.g., strlcpy.
* However, we want these *log* functions to be fast.
* We therefore skip all sanity checks, and all that stuff.
* To ensure any string buffer contains a valid string, we
* always write a NULL byte at its end.
*/
strncpy(la_buffer.type,datatype,LOG_CHAR_BUFFER_LEN);
la_buffer.type[LOG_CHAR_BUFFER_LEN - 1] = '\0';
outb_(PING_CHAR,IO_PORT_LOG);
raw_local_irq_restore(flags);
}
/*
* The parameter irqsync should actually be an enum IRQ_SYNC. To avoid circular dependencies in include/linux/{irqflags,bottom_half}.h which contains
* a declaration of this function, this parameter has to be an int.
*/
static inline void __log_lock(int lock_op, const char *lock_member, const void *ptr, const char *file, int line, const char *function, const char *lock_type, int preempt_count, int irq_sync) {
unsigned long flags;
raw_local_irq_save(flags);
memset(&la_buffer,0,sizeof(la_buffer));
la_buffer.action = 'l';
la_buffer.lock_op = lock_op;
la_buffer.ptr = (unsigned long)ptr;
strncpy(la_buffer.type,lock_type,LOG_CHAR_BUFFER_LEN);
la_buffer.type[LOG_CHAR_BUFFER_LEN - 1] = '\0';
strncpy(la_buffer.lock_member,lock_member,LOG_CHAR_BUFFER_LEN);
la_buffer.lock_member[LOG_CHAR_BUFFER_LEN - 1] = '\0';
strncpy(la_buffer.file,file,LOG_CHAR_BUFFER_LEN);
la_buffer.file[LOG_CHAR_BUFFER_LEN - 1] = '\0';
strncpy(la_buffer.function,function,LOG_CHAR_BUFFER_LEN);
la_buffer.line = line;
la_buffer.function[LOG_CHAR_BUFFER_LEN - 1] = '\0';
la_buffer.preempt_count = preempt_count;
la_buffer.irq_sync = irq_sync;
outb_(PING_CHAR,IO_PORT_LOG);
raw_local_irq_restore(flags);
}
#else
#define MK_STRING(x) #x
#define log_lock(_acquire,_lockmember,_ptr,_file,_line,_function,_logFn)
#define log_memory(alloc, datatype, ptr, size)
#endif /* !CONFIG_ESS_LOCK_ANALYSIS */
#endif // __LOG_H__