#include <climits>
#include <cstddef>
-#if USE_CBDATA_DEBUG
-#include <algorithm>
-#include <vector>
-#endif
-
#if WITH_VALGRIND
#include <map>
#endif
static int cbdataCount = 0;
-#if USE_CBDATA_DEBUG
-dlink_list cbdataEntries;
-#endif
-
-#if USE_CBDATA_DEBUG
-
-class CBDataCall
-{
-
-public:
- CBDataCall (char const *callLabel, char const *aFile, int aLine) : label(callLabel), file(aFile), line(aLine) {}
-
- char const *label;
- char const *file;
- int line;
-};
-
-#endif
/**
* Manage a set of registered callback data pointers.
/* TODO: examine making cbdata templated on this - so we get type
* safe access to data - RBC 20030902 */
public:
-#if USE_CBDATA_DEBUG
-
- void dump(StoreEntry *)const;
-#endif
cbdata() :
valid(0),
locks(0),
type(CBDATA_UNKNOWN),
-#if USE_CBDATA_DEBUG
- file(nullptr),
- line(0),
-#endif
cookie(0),
data(nullptr)
{}
int valid;
int32_t locks;
cbdata_type type;
-#if USE_CBDATA_DEBUG
-
- void addHistory(char const *label, char const *aFile, int aLine) {
- if (calls.size() > 1000)
- return;
-
- calls.push_back(new CBDataCall(label, aFile, aLine));
- }
-
- dlink_node link;
- const char *file;
- int line;
- std::vector<CBDataCall*> calls; // used as a stack with random access operator
-#endif
/* cookie used while debugging */
long cookie;
const long cbdata::Cookie((long)0xDEADBEEF);
-static OBJH cbdataDump;
-#if USE_CBDATA_DEBUG
-static OBJH cbdataDumpHistory;
-#endif
-
struct CBDataIndex {
Mem::Allocator *pool;
}
cbdata::~cbdata()
{
-#if USE_CBDATA_DEBUG
-
- while (!calls.empty()) {
- delete calls.back();
- calls.pop_back();
- }
-
-#endif
-
#if WITH_VALGRIND
void *p = data;
#else
#endif
}
-static void
-cbdataInternalInitType(cbdata_type type, const char *name, int size)
+cbdata_type
+cbdataInternalAddType(cbdata_type type, const char *name, int size)
{
+ if (type)
+ return type;
+
+ type = (cbdata_type)(cbdata_types + 1);
+
char *label;
assert (type == cbdata_types + 1);
#endif
cbdata_index[type].pool = memPoolCreate(label, size);
-}
-
-cbdata_type
-cbdataInternalAddType(cbdata_type type, const char *name, int size)
-{
- if (type)
- return type;
-
- type = (cbdata_type)(cbdata_types + 1);
-
- cbdataInternalInitType(type, name, size);
return type;
}
-void
-cbdataRegisterWithCacheManager(void)
-{
- Mgr::RegisterAction("cbdata",
- "Callback Data Registry Contents",
- cbdataDump, 0, 1);
-#if USE_CBDATA_DEBUG
-
- Mgr::RegisterAction("cbdatahistory",
- "Detailed call history for all current cbdata contents",
- cbdataDumpHistory, 0, 1);
-#endif
-}
-
void *
-cbdataInternalAlloc(cbdata_type type, const char *file, int line)
+cbdataInternalAlloc(cbdata_type type)
{
cbdata *c;
void *p;
c->locks = 0;
c->cookie = (long) c ^ cbdata::Cookie;
++cbdataCount;
-#if USE_CBDATA_DEBUG
-
- c->file = file;
- c->line = line;
- c->calls = std::vector<CBDataCall *> ();
- c->addHistory("Alloc", file, line);
- dlinkAdd(c, &c->link, &cbdataEntries);
- debugs(45, 3, "Allocating " << p << " " << file << ":" << line);
-#else
- (void)file;
- (void)line;
debugs(45, 9, "Allocating " << p);
-#endif
-
return p;
}
static void
-cbdataRealFree(cbdata *c, const char *file, const int line)
+cbdataRealFree(cbdata *c)
{
#if WITH_VALGRIND
void *p = c->data;
#endif
--cbdataCount;
-#if USE_CBDATA_DEBUG
- debugs(45, 3, "Freeing " << p << ' ' << file << ':' << line);
- dlinkDelete(&c->link, &cbdataEntries);
-#else
debugs(45, 9, "Freeing " << p);
- (void)file;
- (void)line;
-#endif
#if WITH_VALGRIND
cbdata_htable.erase(p);
}
void *
-cbdataInternalFree(void *p, const char *file, int line)
+cbdataInternalFree(void *p)
{
auto *c = cbdata::FromUserData(p);
-#if USE_CBDATA_DEBUG
- debugs(45, 3, p << " " << file << ":" << line);
-#else
- debugs(45, 9, p);
-#endif
c->check(__LINE__);
assert(c->valid);
c->valid = 0;
-#if USE_CBDATA_DEBUG
-
- c->addHistory("Free", file, line);
-#endif
if (c->locks) {
debugs(45, 9, p << " has " << c->locks << " locks, not freeing");
return nullptr;
}
- cbdataRealFree(c, file, line);
+ cbdataRealFree(c);
return nullptr;
}
void
-#if USE_CBDATA_DEBUG
-cbdataInternalLockDbg(const void *p, const char *file, int line)
-#else
cbdataInternalLock(const void *p)
-#endif
{
if (p == nullptr)
return;
auto *c = cbdata::FromUserData(p);
-#if USE_CBDATA_DEBUG
- debugs(45, 3, p << "=" << (c ? c->locks + 1 : -1) << " " << file << ":" << line);
- c->addHistory("Reference", file, line);
-#else
debugs(45, 9, p << "=" << (c ? c->locks + 1 : -1));
-#endif
c->check(__LINE__);
}
void
-#if USE_CBDATA_DEBUG
-cbdataInternalUnlockDbg(const void *p, const char *file, int line)
-#else
cbdataInternalUnlock(const void *p)
-#endif
{
if (p == nullptr)
return;
auto *c = cbdata::FromUserData(p);
-#if USE_CBDATA_DEBUG
- debugs(45, 3, p << "=" << (c ? c->locks - 1 : -1) << " " << file << ":" << line);
- c->addHistory("Dereference", file, line);
-#else
debugs(45, 9, p << "=" << (c ? c->locks - 1 : -1));
-#endif
c->check(__LINE__);
if (c->locks)
return;
- if (c->valid) {
-#if USE_CBDATA_DEBUG
- debugs(45, 3, "CBDATA valid with no references ... cbdata=" << p << " " << file << ":" << line);
-#endif
+ if (c->valid)
return;
- }
-#if USE_CBDATA_DEBUG
- cbdataRealFree(c, file, line);
-#else
- cbdataRealFree(c, NULL, 0);
-#endif
+ cbdataRealFree(c);
}
int
}
int
-#if USE_CBDATA_DEBUG
-cbdataInternalReferenceDoneValidDbg(void **pp, void **tp, const char *file, int line)
-#else
cbdataInternalReferenceDoneValid(void **pp, void **tp)
-#endif
{
void *p = (void *) *pp;
int valid = cbdataReferenceValid(p);
*pp = nullptr;
-#if USE_CBDATA_DEBUG
-
- cbdataInternalUnlockDbg(p, file, line);
-#else
cbdataInternalUnlock(p);
-#endif
if (valid) {
*tp = p;
}
}
-#if USE_CBDATA_DEBUG
-void
-cbdata::dump(StoreEntry *sentry) const
-{
-#if WITH_VALGRIND
- void *p = data;
-#else
- void *p = (void *)&data;
-#endif
- storeAppendPrintf(sentry, "%c%p\t%d\t%d\t%20s:%-5d\n", valid ? ' ' :
- '!', p, type, locks, file, line);
-}
-
-struct CBDataDumper : public unary_function<cbdata, void> {
- CBDataDumper(StoreEntry *anEntry):where(anEntry) {}
-
- void operator()(cbdata const &x) {
- x.dump(where);
- }
-
- StoreEntry *where;
-};
-
-#endif
-
-static void
-cbdataDump(StoreEntry * sentry)
-{
- storeAppendPrintf(sentry, "%d cbdata entries\n", cbdataCount);
-#if USE_CBDATA_DEBUG
-
- storeAppendPrintf(sentry, "Pointer\tType\tLocks\tAllocated by\n");
- CBDataDumper dumper(sentry);
- for_each (cbdataEntries, dumper);
- storeAppendPrintf(sentry, "\n");
- storeAppendPrintf(sentry, "types\tsize\tallocated\ttotal\n");
-
- for (int i = 1; i < cbdata_types; ++i) {
- if (const auto pool = cbdata_index[i].pool) {
-#if WITH_VALGRIND
- int obj_size = pool->objectSize();
-#else
- int obj_size = pool->objectSize() - offsetof(cbdata, data);
-#endif
- storeAppendPrintf(sentry, "%s\t%d\t%ld\t%ld\n", pool->objectType() + 7, obj_size, (long int)pool->getMeter().inuse.currentLevel(), (long int)obj_size * pool->getMeter().inuse.currentLevel());
- }
- }
-
-#else
- storeAppendPrintf(sentry, "detailed allocation information only available when compiled with --enable-debug-cbdata\n");
-
-#endif
-
- storeAppendPrintf(sentry, "\nsee also \"Memory utilization\" for detailed per type statistics\n");
-}
-
CallbackData &
CallbackData::operator =(const CallbackData &other)
{
CBDATA_CLASS_INIT(generic_cbdata);
-#if USE_CBDATA_DEBUG
-
-struct CBDataCallDumper : public unary_function<CBDataCall, void> {
- CBDataCallDumper (StoreEntry *anEntry):where(anEntry) {}
-
- void operator()(CBDataCall * const &x) {
- storeAppendPrintf(where, "%s\t%s\t%d\n", x->label, x->file, x->line);
- }
-
- StoreEntry *where;
-};
-
-struct CBDataHistoryDumper : public CBDataDumper {
- CBDataHistoryDumper(StoreEntry *anEntry):CBDataDumper(anEntry),where(anEntry), callDumper(anEntry) {}
-
- void operator()(cbdata const &x) {
- CBDataDumper::operator()(x);
- storeAppendPrintf(where, "\n");
- storeAppendPrintf(where, "Action\tFile\tLine\n");
- std::for_each (x.calls.begin(), x.calls.end(), callDumper);
- storeAppendPrintf(where, "\n");
- }
-
- StoreEntry *where;
- CBDataCallDumper callDumper;
-};
-
-void
-cbdataDumpHistory(StoreEntry *sentry)
-{
- storeAppendPrintf(sentry, "%d cbdata entries\n", cbdataCount);
- storeAppendPrintf(sentry, "Pointer\tType\tLocks\tAllocated by\n");
- CBDataHistoryDumper dumper(sentry);
- for_each (cbdataEntries, dumper);
-}
-
-#endif
-
typedef int cbdata_type;
static const cbdata_type CBDATA_UNKNOWN = 0;
-/**
- * Create a run-time registration of CBDATA component with
- * the Squid cachemgr
- */
-void cbdataRegisterWithCacheManager(void);
-
/**
* Allocates a new entry of a registered CBDATA type.
*
* \note For internal CBDATA use only.
*/
-void *cbdataInternalAlloc(cbdata_type type, const char *, int);
+void *cbdataInternalAlloc(cbdata_type type);
/**
* Frees a entry allocated by cbdataInternalAlloc().
*
* \note For internal CBDATA use only.
*/
-void *cbdataInternalFree(void *p, const char *, int);
-
-#if USE_CBDATA_DEBUG
-void cbdataInternalLockDbg(const void *p, const char *, int);
-#define cbdataInternalLock(a) cbdataInternalLockDbg(a,__FILE__,__LINE__)
+void *cbdataInternalFree(void *p);
-void cbdataInternalUnlockDbg(const void *p, const char *, int);
-#define cbdataInternalUnlock(a) cbdataInternalUnlockDbg(a,__FILE__,__LINE__)
-
-int cbdataInternalReferenceDoneValidDbg(void **p, void **tp, const char *, int);
-#define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValidDbg((void **)&(var), (ptr), __FILE__,__LINE__)
-
-#else
void cbdataInternalLock(const void *p);
void cbdataInternalUnlock(const void *p);
int cbdataInternalReferenceDoneValid(void **p, void **tp);
#define cbdataReferenceValidDone(var, ptr) cbdataInternalReferenceDoneValid((void **)&(var), (ptr))
-#endif /* !CBDATA_DEBUG */
-
/**
* \param p A cbdata entry reference pointer.
*
void *operator new(size_t size) { \
assert(size == sizeof(type)); \
if (!CBDATA_##type) CBDATA_##type = cbdataInternalAddType(CBDATA_##type, #type, sizeof(type)); \
- return (type *)cbdataInternalAlloc(CBDATA_##type,__FILE__,__LINE__); \
+ return (type *)cbdataInternalAlloc(CBDATA_##type); \
} \
void operator delete (void *address) { \
- if (address) cbdataInternalFree(address,__FILE__,__LINE__); \
+ if (address) cbdataInternalFree(address); \
} \
void *toCbdata() methodSpecifiers { return this; } \
private: \