Changed logging system to "cache" gettid() values, to avoid system calls at
runtime (ie, when logging). The implementation is cludgy. This is because we create threads before main, as a result of global thread objects (as opposed to pointers to thread objects that get new'ed and started in main). A view of the system through strace indicates one or two calls to gettid() per thread (usually 1, occasionally 2). Changing the read lock in Log() to a write lock deadlocks.
This commit is contained in:
parent
73ef35474f
commit
6129dbfbc2
|
@ -48,6 +48,8 @@ void addAlarm(const std::string&);
|
|||
//@}
|
||||
|
||||
pid_t gPid = 0;
|
||||
PthreadPidMap gPthreadTidMap;
|
||||
RWLock gPthreadTidLock;
|
||||
|
||||
|
||||
// (pat) If Log messages are printed before the classes in this module are inited
|
||||
|
|
20
Logger.h
20
Logger.h
|
@ -46,6 +46,7 @@
|
|||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/unistd.h>
|
||||
#include "Threads.h"
|
||||
|
||||
// We cannot include Utils.h because it includes Logger.h, so just declare timestr() here.
|
||||
// If timestr decl is changed G++ will whine when Utils.h is included.
|
||||
|
@ -56,9 +57,17 @@ namespace Utils { const std::string timestr(); };
|
|||
#endif // !defined(gettid)
|
||||
|
||||
extern pid_t gPid;
|
||||
typedef std::map<pthread_t,pid_t> PthreadPidMap;
|
||||
extern PthreadPidMap gPthreadTidMap;
|
||||
extern RWLock gPthreadTidLock;
|
||||
|
||||
#define _LOG(level) \
|
||||
Log(LOG_##level).get() << "pid(" << gPid << "), tid(" << gettid() << ") " \
|
||||
Log(LOG_##level).get() << "pid(" << gPid << "), " \
|
||||
<< "tid(" \
|
||||
<< gPthreadTidLock.rlock() \
|
||||
<< gPthreadTidMap[pthread_self()] \
|
||||
<< gPthreadTidLock.unlock() \
|
||||
<< ") " \
|
||||
<< Utils::timestr() << " " __FILE__ ":" << __LINE__ << ":" << __FUNCTION__ << ": "
|
||||
|
||||
// (pat) If you '#define LOG_GROUP groupname' before including Logger.h, then you can set Log.Level.groupname as well as Log.Level.filename.
|
||||
|
@ -139,7 +148,14 @@ class Log {
|
|||
|
||||
Log(int wPriority)
|
||||
:mPriority(wPriority), mDummyInit(false)
|
||||
{ }
|
||||
{
|
||||
gPthreadTidLock.rlock();
|
||||
if (gPthreadTidMap[pthread_self()] == 0)
|
||||
{
|
||||
gPthreadTidMap[pthread_self()] = gettid();
|
||||
}
|
||||
gPthreadTidLock.unlock();
|
||||
}
|
||||
|
||||
// (pat) This constructor is not used to construct a Log record, it is called once per application
|
||||
// to init the syslog facility. This is a very poor use of C++.
|
||||
|
|
20
Threads.cpp
20
Threads.cpp
|
@ -225,6 +225,21 @@ void Signal::wait(Mutex& wMutex, long timeout) const
|
|||
pthread_cond_timedwait(&mSignal,&wMutex.mMutex,&waitTime);
|
||||
}
|
||||
|
||||
struct wrapArgs
|
||||
{
|
||||
void *(*task)(void *);
|
||||
void *arg;
|
||||
};
|
||||
|
||||
static void *
|
||||
thread_main(void *arg)
|
||||
{
|
||||
struct wrapArgs *p = (struct wrapArgs *)arg;
|
||||
void *(*task)(void *) = p->task;
|
||||
void *param = p->arg;
|
||||
delete p;
|
||||
return (*task)(param);
|
||||
}
|
||||
|
||||
void Thread::start(void *(*task)(void*), void *arg)
|
||||
{
|
||||
|
@ -235,7 +250,10 @@ void Thread::start(void *(*task)(void*), void *arg)
|
|||
//assert(!res);
|
||||
res = pthread_attr_setstacksize(&mAttrib, mStackSize);
|
||||
assert(!res);
|
||||
res = pthread_create(&mThread, &mAttrib, task, arg);
|
||||
struct wrapArgs *p = new wrapArgs;
|
||||
p->task = task;
|
||||
p->arg = arg;
|
||||
res = pthread_create(&mThread, &mAttrib, &thread_main, p);
|
||||
assert(!res);
|
||||
}
|
||||
|
||||
|
|
|
@ -127,13 +127,13 @@ class RWLock {
|
|||
|
||||
~RWLock();
|
||||
|
||||
void wlock() { pthread_rwlock_wrlock(&mRWLock); }
|
||||
void rlock() { pthread_rwlock_rdlock(&mRWLock); }
|
||||
const char * wlock() { pthread_rwlock_wrlock(&mRWLock); return ""; }
|
||||
const char * rlock() { pthread_rwlock_rdlock(&mRWLock); return ""; }
|
||||
|
||||
bool trywlock() { return pthread_rwlock_trywrlock(&mRWLock)==0; }
|
||||
bool tryrlock() { return pthread_rwlock_tryrdlock(&mRWLock)==0; }
|
||||
|
||||
void unlock() { pthread_rwlock_unlock(&mRWLock); }
|
||||
const char * unlock() { pthread_rwlock_unlock(&mRWLock); return ""; }
|
||||
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue