aboutsummaryrefslogtreecommitdiff
path: root/utils/src/workqueue.cpp
diff options
context:
space:
mode:
authorHo-Eun Ryu <ho-eun.ryu@windriver.com>2009-09-25 14:33:02 +0900
committerPatrick Tjin <pattjin@google.com>2014-07-21 22:03:24 -0700
commit27553108e3ec272ee7f4ec9a4da2f2c22dafb36f (patch)
treed0bee4036114cd16c3ef6bb5b17bc39344e5a791 /utils/src/workqueue.cpp
parentba4014339471126ca90af5a5ec7a1ee10ad6c15b (diff)
downloadwrs_omxil_core-27553108e3ec272ee7f4ec9a4da2f2c22dafb36f.tar.gz
utils:workqueue: fix bug in lock works list
it had a race condition against list manipulation while processing Work() this patch prevents race condition while processing Work()
Diffstat (limited to 'utils/src/workqueue.cpp')
-rw-r--r--utils/src/workqueue.cpp29
1 files changed, 17 insertions, 12 deletions
diff --git a/utils/src/workqueue.cpp b/utils/src/workqueue.cpp
index ca101e0..6e281e1 100644
--- a/utils/src/workqueue.cpp
+++ b/utils/src/workqueue.cpp
@@ -3,7 +3,7 @@
WorkQueue::WorkQueue()
{
stop = false;
- __list_init(&works); /* head, works->data is always NULL */
+ works = NULL;
pthread_mutex_init(&wlock, NULL);
pthread_cond_init(&wcond, NULL);
@@ -13,6 +13,11 @@ WorkQueue::~WorkQueue()
{
StopWork();
+ pthread_mutex_lock(&wlock);
+ while (works)
+ works = __list_delete(works, works);
+ pthread_mutex_unlock(&wlock);
+
pthread_cond_destroy(&wcond);
pthread_mutex_destroy(&wlock);
}
@@ -37,21 +42,20 @@ void WorkQueue::StopWork(void)
void WorkQueue::Run(void)
{
while (!stop) {
- struct list *entry, *temp;
-
pthread_mutex_lock(&wlock);
/*
* sleeps until works're available.
* wokeup by ScheduleWork() or FlushWork() or ~WorkQueue()
*/
- if (!works.next)
+ if (works)
pthread_cond_wait(&wcond, &wlock);
- list_foreach_safe(works.next, entry, temp) {
+ while (works) {
+ struct list *entry = works;
WorkableInterface *wi =
static_cast<WorkableInterface *>(entry->data);
- __list_delete(works.next, entry);
+ works = __list_delete(works, entry);
pthread_mutex_unlock(&wlock);
DoWork(wi);
pthread_mutex_lock(&wlock);
@@ -62,7 +66,8 @@ void WorkQueue::Run(void)
void WorkQueue::DoWork(WorkableInterface *wi)
{
- wi->Work();
+ if (wi)
+ wi->Work();
}
void WorkQueue::Work(void)
@@ -73,7 +78,7 @@ void WorkQueue::Work(void)
void WorkQueue::ScheduleWork(void)
{
pthread_mutex_lock(&wlock);
- list_add_tail(&works, static_cast<WorkableInterface *>(this));
+ works = list_add_tail(works, static_cast<WorkableInterface *>(this));
pthread_cond_signal(&wcond); /* wakeup Run() if it's sleeping */
pthread_mutex_unlock(&wlock);
}
@@ -82,9 +87,9 @@ void WorkQueue::ScheduleWork(WorkableInterface *wi)
{
pthread_mutex_lock(&wlock);
if (wi)
- list_add_tail(&works, wi);
+ works = list_add_tail(works, wi);
else
- list_add_tail(&works, static_cast<WorkableInterface *>(this));
+ works = list_add_tail(works, static_cast<WorkableInterface *>(this));
pthread_cond_signal(&wcond); /* wakeup Run() if it's sleeping */
pthread_mutex_unlock(&wlock);
}
@@ -95,8 +100,8 @@ void WorkQueue::FlushWork(void)
bool needtowait = false;
pthread_mutex_lock(&wlock);
- if (works.next) {
- list_add_tail(&works, &fb);
+ if (works) {
+ list_add_tail(works, &fb);
pthread_cond_signal(&wcond); /* wakeup Run() if it's sleeping */
needtowait = true;