Stack usage is my enemy. Trade cpu cycles in the debug code to

ensure I never add anything to the stack I don't absolutely need.
All this debug code could be removed from a production build
anyway so I'm not so worried about the performance impact.  We
may also consider revisting the mutex and condvar implementation
to ensure no additional stack is used there.

Initial indications are I have reduced the worst case stack
usage to 9080 bytes.  Still to large for the default 8k stacks
so I have been forced to run with 16k stacks until I can
reduce the worst offenders.



git-svn-id: https://outreach.scidac.gov/svn/spl/trunk@83 7e1ea52c-4ff2-0310-8f11-9dd32ca42a1c
This commit is contained in:
behlendo 2008-04-22 16:55:26 +00:00
parent 7fea96c04f
commit b831734a43
3 changed files with 55 additions and 62 deletions

View File

@ -52,8 +52,8 @@ typedef struct splat_cmd {
/* Valid configuration commands */ /* Valid configuration commands */
#define SPLAT_CFG_BUFFER_CLEAR 0x001 /* Clear text buffer */ #define SPLAT_CFG_BUFFER_CLEAR 0x001 /* Clear text buffer */
#define SPLAT_CFG_BUFFER_SIZE 0x002 /* Resize text buffer */ #define SPLAT_CFG_BUFFER_SIZE 0x002 /* Resize text buffer */
#define SPLAT_CFG_SUBSYSTEM_COUNT 0x101 /* Number of subsystem */ #define SPLAT_CFG_SUBSYSTEM_COUNT 0x101 /* Number of subsystem */
#define SPLAT_CFG_SUBSYSTEM_LIST 0x102 /* List of N subsystems */ #define SPLAT_CFG_SUBSYSTEM_LIST 0x102 /* List of N subsystems */
#define SPLAT_CFG_TEST_COUNT 0x201 /* Number of tests */ #define SPLAT_CFG_TEST_COUNT 0x201 /* Number of tests */
#define SPLAT_CFG_TEST_LIST 0x202 /* List of N tests */ #define SPLAT_CFG_TEST_LIST 0x202 /* List of N tests */

View File

@ -56,16 +56,16 @@ extern long spl_console_min_delay;
extern unsigned int spl_console_backoff; extern unsigned int spl_console_backoff;
extern unsigned int spl_debug_stack; extern unsigned int spl_debug_stack;
#define TCD_MAX_PAGES (5 << (20 - PAGE_SHIFT)) #define TCD_MAX_PAGES (5 << (20 - PAGE_SHIFT))
#define TCD_STOCK_PAGES (TCD_MAX_PAGES) #define TCD_STOCK_PAGES (TCD_MAX_PAGES)
#define TRACE_CONSOLE_BUFFER_SIZE 1024 #define TRACE_CONSOLE_BUFFER_SIZE 1024
#define SPL_DEFAULT_MAX_DELAY (600 * HZ) #define SPL_DEFAULT_MAX_DELAY (600 * HZ)
#define SPL_DEFAULT_MIN_DELAY ((HZ + 1) / 2) #define SPL_DEFAULT_MIN_DELAY ((HZ + 1) / 2)
#define SPL_DEFAULT_BACKOFF 2 #define SPL_DEFAULT_BACKOFF 2
#define DL_NOTHREAD 0x0001 /* Do not create a new thread */ #define DL_NOTHREAD 0x0001 /* Do not create a new thread */
#define DL_SINGLE_CPU 0x0002 /* Collect pages from this CPU */ #define DL_SINGLE_CPU 0x0002 /* Collect pages from this CPU */
typedef struct dumplog_priv { typedef struct dumplog_priv {
wait_queue_head_t dp_waitq; wait_queue_head_t dp_waitq;
@ -157,7 +157,7 @@ struct page_collection {
int pc_want_daemon_pages; int pc_want_daemon_pages;
}; };
#define SBUG() spl_debug_bug(__FILE__, __FUNCTION__, __LINE__, 0); #define SBUG() spl_debug_bug(__FILE__, __FUNCTION__, __LINE__, 0);
#ifdef __ia64__ #ifdef __ia64__
#define CDEBUG_STACK() (THREAD_SIZE - \ #define CDEBUG_STACK() (THREAD_SIZE - \
@ -169,85 +169,83 @@ struct page_collection {
(THREAD_SIZE - 1))) (THREAD_SIZE - 1)))
# endif /* __ia64__ */ # endif /* __ia64__ */
/* DL_NOTHREAD and DL_SINGLE_CPU flags are passed to spl_debug_bug() /* DL_SINGLE_CPU flag is passed to spl_debug_bug() because we are about
* because we have over run our stack and likely damaged at least one * to over run our stack and likely damage at least one other unknown
* other unknown threads stack. We must finish generating the needed * thread stack. We must finish generating the needed debug info within
* debug info within this thread context because once we yeild the CPU * this thread context because once we yeild the CPU its very likely
* its very likely the system will crash. * the system will crash.
*/ */
#define __CHECK_STACK(file, func, line) \ #define __CHECK_STACK(file, func, line) \
do { \ do { \
unsigned long _stack = CDEBUG_STACK(); \ if (unlikely(CDEBUG_STACK() > spl_debug_stack)) { \
unsigned long _soft_limit = (8 * THREAD_SIZE) / 10; \ spl_debug_stack = CDEBUG_STACK(); \
\ \
if (unlikely(_stack > _soft_limit && _stack > spl_debug_stack)){\ if (unlikely(CDEBUG_STACK() > (4 * THREAD_SIZE) / 5)) { \
spl_debug_stack = _stack; \ spl_debug_msg(NULL, D_TRACE, D_WARNING, \
spl_debug_msg(NULL, D_TRACE, D_WARNING, \ file, func, line, "Error " \
file, func, line, "Error exceeded " \ "exceeded maximum safe stack " \
"maximum safe stack size (%lu/%lu)\n", \ "size (%lu/%lu)\n", \
_stack, THREAD_SIZE); \ CDEBUG_STACK(), THREAD_SIZE); \
spl_debug_bug(file, func, line, DL_SINGLE_CPU); \ spl_debug_bug(file, func, line, DL_SINGLE_CPU); \
} \
} \ } \
} while (0) } while (0)
#define CHECK_STACK() __CHECK_STACK(__FILE__, __func__, __LINE__) #define CHECK_STACK() __CHECK_STACK(__FILE__, __func__, __LINE__)
/* ASSERTION that is safe to use within the debug system */ /* ASSERTION that is safe to use within the debug system */
#define __ASSERT(cond) \ #define __ASSERT(cond) \
do { \ do { \
if (unlikely(!(cond))) { \ if (unlikely(!(cond))) { \
printk(KERN_ERR "ASSERTION("#cond") failed"); \ printk(KERN_ERR "ASSERTION(" #cond ") failed"); \
SBUG(); \ SBUG(); \
} \ } \
} while (0) } while (0)
#define __ASSERT_TAGE_INVARIANT(tage) \ #define __ASSERT_TAGE_INVARIANT(tage) \
do { \ do { \
__ASSERT(tage != NULL); \ __ASSERT(tage != NULL); \
__ASSERT(tage->page != NULL); \ __ASSERT(tage->page != NULL); \
__ASSERT(tage->used <= PAGE_SIZE); \ __ASSERT(tage->used <= PAGE_SIZE); \
__ASSERT(page_count(tage->page) > 0); \ __ASSERT(page_count(tage->page) > 0); \
} while(0) } while(0)
/* ASSERTION that will debug log used outside the debug sysytem */ /* ASSERTION that will debug log used outside the debug sysytem */
#define ASSERT(cond) \ #define ASSERT(cond) \
do { \ do { \
CHECK_STACK(); \ CHECK_STACK(); \
\ \
if (unlikely(!(cond))) { \ if (unlikely(!(cond))) { \
spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \ spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \
__FILE__, __FUNCTION__, __LINE__, \ __FILE__, __FUNCTION__, __LINE__, \
"ASSERTION(" #cond ") failed\n"); \ "ASSERTION(" #cond ") failed\n"); \
SBUG(); \ SBUG(); \
} \ } \
} while (0) } while (0)
#define ASSERTF(cond, fmt, a...) \ #define ASSERTF(cond, fmt, a...) \
do { \ do { \
CHECK_STACK(); \ CHECK_STACK(); \
\ \
if (unlikely(!(cond))) { \ if (unlikely(!(cond))) { \
spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \ spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \
__FILE__, __FUNCTION__, __LINE__, \ __FILE__, __FUNCTION__, __LINE__, \
"ASSERTION(" #cond ") failed:" fmt, \ "ASSERTION(" #cond ") failed:" fmt, \
## a); \ ## a); \
SBUG(); \ SBUG(); \
} \ } \
} while (0) } while (0)
#define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE, FMT, CAST) \ #define VERIFY3_IMPL(LEFT, OP, RIGHT, TYPE, FMT, CAST) \
do { \ do { \
const TYPE __left = (TYPE)(LEFT); \ CHECK_STACK(); \
const TYPE __right = (TYPE)(RIGHT); \ \
\ if (!((TYPE)(LEFT) OP (TYPE)(RIGHT))) { \
CHECK_STACK(); \
\
if (!(__left OP __right)) { \
spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \ spl_debug_msg(NULL, DEBUG_SUBSYSTEM, D_EMERG, \
__FILE__, __FUNCTION__, __LINE__, \ __FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" FMT " " #OP " " FMT ")\n", \ "VERIFY3(" FMT " " #OP " " FMT ")\n", \
CAST __left, CAST __right); \ CAST (LEFT), CAST (RIGHT)); \
SBUG(); \ SBUG(); \
} \ } \
} while (0) } while (0)
@ -259,7 +257,7 @@ do { \
#define ASSERT3U(x,y,z) VERIFY3U(x, y, z) #define ASSERT3U(x,y,z) VERIFY3U(x, y, z)
#define ASSERT3P(x,y,z) VERIFY3P(x, y, z) #define ASSERT3P(x,y,z) VERIFY3P(x, y, z)
#define VERIFY(x) ASSERT(x) #define VERIFY(x) ASSERT(x)
#define spl_debug_msg(cdls, subsys, mask, file, fn, line, format, a...) \ #define spl_debug_msg(cdls, subsys, mask, file, fn, line, format, a...) \
spl_debug_vmsg(cdls, subsys, mask, file, fn, \ spl_debug_vmsg(cdls, subsys, mask, file, fn, \
@ -323,8 +321,8 @@ do { \
} while(0) } while(0)
extern int spl_debug_vmsg(spl_debug_limit_state_t *cdls, int subsys, int mask, extern int spl_debug_vmsg(spl_debug_limit_state_t *cdls, int subsys, int mask,
const char *file, const char *fn, const int line, const char *file, const char *fn, const int line,
const char *format1, va_list args, const char *format2, ...); const char *format1, va_list args, const char *format2, ...);
extern unsigned long spl_debug_set_mask(unsigned long mask); extern unsigned long spl_debug_set_mask(unsigned long mask);
extern unsigned long spl_debug_get_mask(void); extern unsigned long spl_debug_get_mask(void);

View File

@ -142,8 +142,9 @@ typedef struct modldrv {
#define mod_driverops NULL #define mod_driverops NULL
#define ddi_prop_op NULL #define ddi_prop_op NULL
#define getminor MINOR #define getminor(x) (x)
#define getmajor MAJOR #define getmajor(x) (x)
#define ddi_driver_major(di) getmajor(di->di_dev)
#define mod_install(x) 0 #define mod_install(x) 0
#define mod_remove(x) 0 #define mod_remove(x) 0
@ -158,12 +159,6 @@ extern int __mod_remove(struct modlinkage *modlp);
static __inline__ void ddi_report_dev(dev_info_t *d) { } static __inline__ void ddi_report_dev(dev_info_t *d) { }
static __inline__ void ddi_prop_remove_all(dev_info_t *dip) { } static __inline__ void ddi_prop_remove_all(dev_info_t *dip) { }
static __inline__ major_t
ddi_driver_major(dev_info_t *di)
{
return getmajor(di->di_dev);
}
static __inline__ int static __inline__ int
ddi_create_minor_node(dev_info_t *di, char *name, int spec_type, ddi_create_minor_node(dev_info_t *di, char *name, int spec_type,
minor_t minor_num, char *node_type, int flag) minor_t minor_num, char *node_type, int flag)