// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
// Copyright (c) 2001-2007 International Computer Science Institute
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software")
// to deal in the Software without restriction, subject to the conditions
// listed in the XORP LICENSE file. These conditions include: you must
// preserve this copyright notice, and you cannot mention the copyright
// holders in advertising related to the Software without their permission.
// The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
// notice is a summary of the XORP LICENSE file; the license in that file is
// legally binding.
#ident "$XORP: xorp/libxorp/callback.cc,v 1.10 2007/02/16 22:46:16 pavlin Exp $"
#include "libxorp_module.h"
#include "libxorp/xorp.h"
/*
* This code is only compiled if DEBUG_CALLBACKS is defined in
* config.h via 'configure --enable-callback-debug'. All callback
* debugging entails is watching that individual callbacks do not take
* too long in their dispatch method. Since XORP is event and timer
* driven taking anything more than a few seconds is potentially bad.
* Ideally the longest dispatch times should be of the order of 10-50
* milliseconds.
*/
#ifdef DEBUG_CALLBACKS
#include "libxorp/xlog.h"
#include "libxorp/callback.hh"
#include "libxorp/c_format.hh"
#include "libxorp/timeval.hh"
#include "libxorp/timer.hh"
#include <stack>
/**
* Maximum callback dispatch duration.
*/
static const TimeVal MAX_CALLBACK_DURATION(5, 0);
/**
* Stack because one callback can dispatch another and callback data
* structures can be deleted so we can't rely on file and line stored
* there.
*/
struct CBStackElement {
TimeVal start;
const char* file;
int line;
CBStackElement(const TimeVal& now, const char* f, int l)
: start(now), file(f), line(l)
{}
};
static stack<CBStackElement> cb_stack;
void
trace_dispatch_enter(const char* file, int line)
{
TimeVal now;
TimerList::system_gettimeofday(&now);
cb_stack.push(CBStackElement(now, file, line));
}
void
trace_dispatch_leave()
{
XLOG_ASSERT(cb_stack.empty() == false);
TimeVal now;
TimerList::system_gettimeofday(&now);
const CBStackElement& e = cb_stack.top();
TimeVal delta = now - e.start;
if (delta >= MAX_CALLBACK_DURATION) {
string s = c_format("Callback originating at %s:%d took "
"%d.%06d seconds\n",
e.file, e.line, delta.secs(), delta.usecs());
if (xlog_is_running()) {
XLOG_ERROR("%s", s.c_str());
} else {
fprintf(stderr, "ERROR: %s\n", s.c_str());
}
}
cb_stack.pop();
}
#endif /* DEBUG_CALLBACKS */
syntax highlighted by Code2HTML, v. 0.9.1