Crash fix with MsgTask API change

Removed tCreate and tAssociate from MsgTask. LocThread
now can optionally take a tCreate method. Associator is
replaced with *firstMsg* option to MsgTask, which is a
more generic option, that can associate or do other set
up job at the create of a MsgTask.

The current MsgTask doesn't use tCreate, which exposes
a slight time window for Location HAL when its MsgTask
is NOT associated to DVM heap but a message delivery to
DVM could be attempted during this time.

Change-Id: Iafd5b91b693baacb9b7064463f8c44f74026f54c
CRs-Fixed: 902350
This commit is contained in:
Kevin Tang 2015-09-11 19:40:25 -07:00 committed by Vamana Murthi
parent f533181bd6
commit 2f74f91ac1
12 changed files with 151 additions and 168 deletions

View file

@ -63,34 +63,28 @@ const char* LocDualContext::mLBSLibName = "liblbs_core.so";
pthread_mutex_t LocDualContext::mGetLocContextMutex = PTHREAD_MUTEX_INITIALIZER;
const MsgTask* LocDualContext::getMsgTask(MsgTask::tCreate tCreator,
const char* name)
const MsgTask* LocDualContext::getMsgTask(LocThread::tCreate tCreator,
const char* name, bool joinable)
{
if (NULL == mMsgTask) {
mMsgTask = new MsgTask(tCreator, name);
mMsgTask = new MsgTask(tCreator, name, joinable);
}
return mMsgTask;
}
const MsgTask* LocDualContext::getMsgTask(MsgTask::tAssociate tAssociate,
const char* name)
{
if (NULL == mMsgTask) {
mMsgTask = new MsgTask(tAssociate, name);
} else if (tAssociate) {
mMsgTask->associate(tAssociate);
}
return mMsgTask;
inline
const MsgTask* LocDualContext::getMsgTask(const char* name, bool joinable) {
return getMsgTask((LocThread::tCreate)NULL, name, joinable);
}
ContextBase* LocDualContext::getLocFgContext(MsgTask::tCreate tCreator,
const char* name)
ContextBase* LocDualContext::getLocFgContext(LocThread::tCreate tCreator,
LocMsg* firstMsg, const char* name, bool joinable)
{
pthread_mutex_lock(&LocDualContext::mGetLocContextMutex);
LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__);
if (NULL == mFgContext) {
LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__);
const MsgTask* msgTask = getMsgTask(tCreator, name);
const MsgTask* msgTask = getMsgTask(tCreator, name, joinable);
mFgContext = new LocDualContext(msgTask,
mFgExclMask);
}
@ -100,37 +94,22 @@ ContextBase* LocDualContext::getLocFgContext(MsgTask::tCreate tCreator,
injectFeatureConfig(mInjectContext);
}
pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex);
if (firstMsg) {
mFgContext->sendMsg(firstMsg);
}
return mFgContext;
}
ContextBase* LocDualContext::getLocFgContext(MsgTask::tAssociate tAssociate,
const char* name)
{
pthread_mutex_lock(&LocDualContext::mGetLocContextMutex);
LOC_LOGD("%s:%d]: querying ContextBase with tAssociate", __func__, __LINE__);
if (NULL == mFgContext) {
LOC_LOGD("%s:%d]: creating msgTask with tAssociate", __func__, __LINE__);
const MsgTask* msgTask = getMsgTask(tAssociate, name);
mFgContext = new LocDualContext(msgTask,
mFgExclMask);
}
if(NULL == mInjectContext) {
LOC_LOGD("%s:%d]: mInjectContext is FgContext", __func__, __LINE__);
mInjectContext = mFgContext;
injectFeatureConfig(mInjectContext);
}
pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex);
return mFgContext;
}
ContextBase* LocDualContext::getLocBgContext(MsgTask::tCreate tCreator,
const char* name)
ContextBase* LocDualContext::getLocBgContext(LocThread::tCreate tCreator,
LocMsg* firstMsg, const char* name, bool joinable)
{
pthread_mutex_lock(&LocDualContext::mGetLocContextMutex);
LOC_LOGD("%s:%d]: querying ContextBase with tCreator", __func__, __LINE__);
if (NULL == mBgContext) {
LOC_LOGD("%s:%d]: creating msgTask with tCreator", __func__, __LINE__);
const MsgTask* msgTask = getMsgTask(tCreator, name);
const MsgTask* msgTask = getMsgTask(tCreator, name, joinable);
mBgContext = new LocDualContext(msgTask,
mBgExclMask);
}
@ -140,26 +119,11 @@ ContextBase* LocDualContext::getLocBgContext(MsgTask::tCreate tCreator,
injectFeatureConfig(mInjectContext);
}
pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex);
return mBgContext;
if (firstMsg) {
mBgContext->sendMsg(firstMsg);
}
ContextBase* LocDualContext::getLocBgContext(MsgTask::tAssociate tAssociate,
const char* name)
{
pthread_mutex_lock(&LocDualContext::mGetLocContextMutex);
LOC_LOGD("%s:%d]: querying ContextBase with tAssociate", __func__, __LINE__);
if (NULL == mBgContext) {
LOC_LOGD("%s:%d]: creating msgTask with tAssociate", __func__, __LINE__);
const MsgTask* msgTask = getMsgTask(tAssociate, name);
mBgContext = new LocDualContext(msgTask,
mBgExclMask);
}
if(NULL == mInjectContext) {
LOC_LOGD("%s:%d]: mInjectContext is BgContext", __func__, __LINE__);
mInjectContext = mBgContext;
injectFeatureConfig(mInjectContext);
}
pthread_mutex_unlock(&LocDualContext::mGetLocContextMutex);
return mBgContext;
}

View file

@ -41,10 +41,9 @@ class LocDualContext : public ContextBase {
static ContextBase* mFgContext;
static ContextBase* mBgContext;
static ContextBase* mInjectContext;
static const MsgTask* getMsgTask(MsgTask::tCreate tCreator,
const char* name);
static const MsgTask* getMsgTask(MsgTask::tAssociate tAssociate,
const char* name);
static const MsgTask* getMsgTask(LocThread::tCreate tCreator,
const char* name, bool joinable = true);
static const MsgTask* getMsgTask(const char* name, bool joinable = true);
static pthread_mutex_t mGetLocContextMutex;
protected:
@ -58,14 +57,17 @@ public:
static const LOC_API_ADAPTER_EVENT_MASK_T mBgExclMask;
static const char* mLocationHalName;
static ContextBase* getLocFgContext(MsgTask::tCreate tCreator,
const char* name);
static ContextBase* getLocFgContext(MsgTask::tAssociate tAssociate,
const char* name);
static ContextBase* getLocBgContext(MsgTask::tCreate tCreator,
const char* name);
static ContextBase* getLocBgContext(MsgTask::tAssociate tAssociate,
const char* name);
static ContextBase* getLocFgContext(LocThread::tCreate tCreator, LocMsg* firstMsg,
const char* name, bool joinable = true);
inline static ContextBase* getLocFgContext(const char* name, bool joinable = true) {
return getLocFgContext(NULL, NULL, name, joinable);
}
static ContextBase* getLocBgContext(LocThread::tCreate tCreator, LocMsg* firstMsg,
const char* name, bool joinable = true);
inline static ContextBase* getLocBgContext(const char* name, bool joinable = true) {
return getLocBgContext(NULL, NULL, name, joinable);
}
static void injectFeatureConfig(ContextBase *context);
};

View file

@ -55,13 +55,15 @@ void LocInternalAdapter::getZppInt() {
LocEngAdapter::LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask,
void* owner, ContextBase* context,
MsgTask::tCreate tCreator) :
LocThread::tCreate tCreator) :
LocAdapterBase(mask,
//Get the AFW context if VzW context has not already been intialized in
//loc_ext
context == NULL?
LocDualContext::getLocFgContext(tCreator,
LocDualContext::mLocationHalName)
NULL,
LocDualContext::mLocationHalName,
false)
:context),
mOwner(owner), mInternalAdapter(new LocInternalAdapter(this)),
mUlp(new UlpProxyBase()), mNavigating(false),

View file

@ -88,7 +88,7 @@ public:
LocEngAdapter(LOC_API_ADAPTER_EVENT_MASK_T mask,
void* owner, ContextBase* context,
MsgTask::tCreate tCreator);
LocThread::tCreate tCreator);
virtual ~LocEngAdapter();
virtual void setUlpProxy(UlpProxyBase* ulp);

View file

@ -223,7 +223,6 @@ static void* noProc(void* data)
return NULL;
}
/*********************************************************************
* definitions of the static messages used in the file
*********************************************************************/
@ -1768,7 +1767,7 @@ int loc_eng_init(loc_eng_data_s_type &loc_eng_data, LocCallbacks* callbacks,
loc_eng_data.adapter =
new LocEngAdapter(event, &loc_eng_data, context,
(MsgTask::tCreate)callbacks->create_thread_cb);
(LocThread::tCreate)callbacks->create_thread_cb);
LOC_LOGD("loc_eng_init created client, id = %p\n",
loc_eng_data.adapter);

58
utils/LocSharedLock.h Normal file
View file

@ -0,0 +1,58 @@
/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation, nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __LOC_SHARED_LOCK__
#define __LOC_SHARED_LOCK__
#include <stddef.h>
#include <pthread.h>
// This is a utility created for use cases such that there are more than
// one client who need to share the same lock, but it is not predictable
// which of these clients is to last to go away. This shared lock deletes
// itself when the last client calls its drop() method. To add a cient,
// this share lock's share() method has to be called, so that the obj
// can maintain an accurate client count.
class LocSharedLock {
uint32_t mRef;
pthread_mutex_t mMutex;
inline ~LocSharedLock() { pthread_mutex_destroy(&mMutex); }
public:
// first client to create this LockSharedLock
inline LocSharedLock() : mRef(1) { pthread_mutex_init(&mMutex, NULL); }
// following client(s) are to *share()* this lock created by the first client
inline LocSharedLock* share() { mRef++; return this; }
// whe a client no longer needs this shared lock, drop() shall be called.
inline void drop() { if (0 == --mRef) delete this; }
// locking the lock to enter critical section
inline void lock() { pthread_mutex_lock(&mMutex); }
// unlocking the lock to leave the critical section
inline void unlock() { pthread_mutex_unlock(&mMutex); }
};
#endif //__LOC_SHARED_LOCK__

View file

@ -37,12 +37,12 @@ class LocThreadDelegate {
pthread_mutex_t mMutex;
int mRefCount;
~LocThreadDelegate();
LocThreadDelegate(const char* threadName,
LocThreadDelegate(LocThread::tCreate creator, const char* threadName,
LocRunnable* runnable, bool joinable);
void destroy();
public:
static LocThreadDelegate* create(const char* threadName,
LocRunnable* runnable, bool joinable);
static LocThreadDelegate* create(LocThread::tCreate creator,
const char* threadName, LocRunnable* runnable, bool joinable);
void stop();
// bye() is for the parent thread to go away. if joinable,
// parent must stop the spawned thread, join, and then
@ -62,19 +62,28 @@ public:
// However, upon pthread_create failure, the data members
// must be set to indicate failure, e.g. mRunnable, and
// threashold approprietly for destroy(), e.g. mRefCount.
LocThreadDelegate::LocThreadDelegate(const char* threadName,
LocRunnable* runnable, bool joinable) :
mRunnable(runnable), mJoinable(joinable),
LocThreadDelegate::LocThreadDelegate(LocThread::tCreate creator,
const char* threadName, LocRunnable* runnable, bool joinable) :
mRunnable(runnable), mJoinable(joinable), mThandle(NULL),
mMutex(PTHREAD_MUTEX_INITIALIZER), mRefCount(2) {
// set up thread name, if nothing is passed in
if (!threadName) {
threadName = "LocThread";
}
// create the thread here, then if successful
// and a name is given, we set the thread name
if (!pthread_create(&mThandle, NULL, threadMain, this)) {
if (creator) {
mThandle = creator(threadName, threadMain, this);
} else if (pthread_create(&mThandle, NULL, threadMain, this)) {
// pthread_create() failed
mThandle = NULL;
}
if (mThandle) {
// set thread name
char lname[16];
const char* defaultName = "LocThread";
if (!threadName) {
threadName = defaultName;
}
int len = sizeof(lname) - 1;
memcpy(lname, threadName, len);
lname[len] = 0;
@ -99,11 +108,11 @@ LocThreadDelegate::~LocThreadDelegate() {
}
// factory method so that we could return NULL upon failure
LocThreadDelegate* LocThreadDelegate::create(const char* threadName,
LocRunnable* runnable, bool joinable) {
LocThreadDelegate* LocThreadDelegate::create(LocThread::tCreate creator,
const char* threadName, LocRunnable* runnable, bool joinable) {
LocThreadDelegate* thread = NULL;
if (runnable) {
thread = new LocThreadDelegate(threadName, runnable, joinable);
thread = new LocThreadDelegate(creator, threadName, runnable, joinable);
if (thread && !thread->isRunning()) {
thread->destroy();
thread = NULL;
@ -199,11 +208,14 @@ LocThread::~LocThread() {
}
}
bool LocThread::start(const char* threadName, LocRunnable* runnable, bool joinable) {
mThread = LocThreadDelegate::create(threadName, runnable, joinable);
bool LocThread::start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable) {
bool success = false;
if (!mThread) {
mThread = LocThreadDelegate::create(creator, threadName, runnable, joinable);
// true only if thread is created successfully
return (NULL != mThread);
success = (NULL != mThread);
}
return success;
}
void LocThread::stop() {

View file

@ -30,6 +30,7 @@
#define __LOC_THREAD__
#include <stddef.h>
#include <pthread.h>
// abstract class to be implemented by client to provide a runnable class
// which gets scheduled by LocThread
@ -64,6 +65,7 @@ public:
inline LocThread() : mThread(NULL) {}
virtual ~LocThread();
typedef pthread_t (*tCreate)(const char* name, void* (*start)(void*), void* arg);
// client starts thread with a runnable, which implements
// the logics to fun in the created thread context.
// The thread could be either joinable or detached.
@ -74,7 +76,10 @@ public:
// returns true. Else it is client's responsibility
// to delete the object
// Returns 0 if success; false if failure.
bool start(const char* threadName, LocRunnable* runnable, bool joinable = true);
bool start(tCreate creator, const char* threadName, LocRunnable* runnable, bool joinable = true);
inline bool start(const char* threadName, LocRunnable* runnable, bool joinable = true) {
return start(NULL, threadName, runnable, joinable);
}
// NOTE: if this is a joinable thread, this stop may block
// for a while until the thread is joined.

View file

@ -37,7 +37,7 @@
#include <LocTimer.h>
#include <LocHeap.h>
#include <LocThread.h>
#include <pthread.h>
#include <LocSharedLock.h>
#include <MsgTask.h>
#ifdef __HOST_UNIT_TEST__
@ -46,22 +46,6 @@
#define CLOCK_BOOTTIME_ALARM CLOCK_MONOTONIC
#endif
using namespace loc_core;
// a shared lock until, place it here for now.
class LocUtilSharedLock {
uint32_t mRef;
pthread_mutex_t mMutex;
inline ~LocUtilSharedLock() { pthread_mutex_destroy(&mMutex); }
public:
inline LocUtilSharedLock() : mRef(1) { pthread_mutex_init(&mMutex, NULL); }
inline LocUtilSharedLock* share() { mRef++; return this; }
inline void drop() { if (0 == --mRef) delete this; }
inline void lock() { pthread_mutex_lock(&mMutex); }
inline void unlock() { pthread_mutex_unlock(&mMutex); }
};
/*
There are implementations of 5 classes in this file:
LocTimer, LocTimerDelegate, LocTimerContainer, LocTimerPollTask, LocTimerWrapper
@ -191,7 +175,7 @@ class LocTimerDelegate : public LocRankable {
friend class LocTimerContainer;
friend class LocTimer;
LocTimer* mClient;
LocUtilSharedLock* mLock;
LocSharedLock* mLock;
struct timespec mFutureTime;
LocTimerContainer* mContainer;
// not a complete obj, just ctor for LocRankable comparisons
@ -548,7 +532,7 @@ void LocTimerDelegate::expire() {
/***************************LocTimer methods***************************/
LocTimer::LocTimer() : mTimer(NULL), mLock(new LocUtilSharedLock()) {
LocTimer::LocTimer() : mTimer(NULL), mLock(new LocSharedLock()) {
}
LocTimer::~LocTimer() {

View file

@ -35,14 +35,14 @@
// opaque class to provide service implementation.
class LocTimerDelegate;
class LocUtilSharedLock;
class LocSharedLock;
// LocTimer client must extend this class and implementthe callback.
// start() / stop() methods are to arm / disarm timer.
class LocTimer
{
LocTimerDelegate* mTimer;
LocUtilSharedLock* mLock;
LocSharedLock* mLock;
// don't really want mLock to be manipulated by clients, yet LocTimer
// has to have a reference to the lock so that the delete of LocTimer
// and LocTimerDelegate can work together on their share resources.

View file

@ -36,12 +36,19 @@
#include <log_util.h>
#include <loc_log.h>
namespace loc_core {
static void LocMsgDestroy(void* msg) {
delete (LocMsg*)msg;
}
MsgTask::MsgTask(LocThread::tCreate tCreator,
const char* threadName, bool joinable) :
mQ(msg_q_init2()), mThread(new LocThread()) {
if (!mThread->start(tCreator, threadName, this, joinable)) {
delete mThread;
mThread = NULL;
}
}
MsgTask::MsgTask(const char* threadName, bool joinable) :
mQ(msg_q_init2()), mThread(new LocThread()) {
if (!mThread->start(threadName, this, joinable)) {
@ -93,40 +100,3 @@ bool MsgTask::run() {
return true;
}
// TODO: remove the below in the next patch
void MsgTask::associate(tAssociate tAssociator) const {
struct LocAssociateMsg : public LocMsg {
tAssociate mAssociator;
LocAssociateMsg(tAssociate associator) :
mAssociator(associator) {}
inline virtual void proc() const {
static bool sAssociated = false;
if (!sAssociated) {
sAssociated = true;
mAssociator();
}
}
};
sendMsg(new LocAssociateMsg(tAssociator));
}
MsgTask::MsgTask(tCreate tCreator, const char* threadName) :
mQ(msg_q_init2()), mThread(new LocThread()) {
if (!mThread->start(threadName, this, false)) {
delete mThread;
mThread = NULL;
}
}
MsgTask::MsgTask(tAssociate tAssociator, const char* threadName) :
mQ(msg_q_init2()), mThread(new LocThread()) {
if (!mThread->start(threadName, this, false)) {
delete mThread;
mThread = NULL;
} else {
associate(tAssociator);
}
}
} // namespace loc_core

View file

@ -30,10 +30,6 @@
#define __MSG_TASK__
#include <LocThread.h>
// TODO: remove this include in the next patch
#include <pthread.h>
namespace loc_core {
struct LocMsg {
inline LocMsg() {}
@ -49,6 +45,7 @@ class MsgTask : public LocRunnable{
protected:
virtual ~MsgTask();
public:
MsgTask(LocThread::tCreate tCreator, const char* threadName = NULL, bool joinable = true);
MsgTask(const char* threadName = NULL, bool joinable = true);
// this obj will be deleted once thread is deleted
void destroy();
@ -65,16 +62,6 @@ public:
// The method to be run after thread loop (conditionally repeatedly)
// calls run()
inline virtual void postrun() {}
// TODO: remove the below in the next patch
typedef void* (*tStart)(void*);
typedef pthread_t (*tCreate)(const char* name, tStart start, void* arg);
typedef int (*tAssociate)();
MsgTask(tCreate tCreator, const char* threadName);
MsgTask(tAssociate tAssociator, const char* threadName);
void associate(tAssociate tAssociator) const;
};
} // namespace loc_core
#endif //__MSG_TASK__