summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
Diffstat (limited to 'linux')
-rw-r--r--linux/six.c12
-rw-r--r--linux/workqueue.c54
2 files changed, 47 insertions, 19 deletions
diff --git a/linux/six.c b/linux/six.c
index c7781235..3d863a9b 100644
--- a/linux/six.c
+++ b/linux/six.c
@@ -108,7 +108,8 @@ static bool __six_trylock_type(struct six_lock *lock, enum six_lock_type type)
if (!do_six_trylock_type(lock, type))
return false;
- six_acquire(&lock->dep_map, 1);
+ if (type != SIX_LOCK_write)
+ six_acquire(&lock->dep_map, 1);
return true;
}
@@ -130,7 +131,8 @@ static bool __six_relock_type(struct six_lock *lock, enum six_lock_type type,
old.v + l[type].lock_val)) != old.v);
six_set_owner(lock, type, old);
- six_acquire(&lock->dep_map, 1);
+ if (type != SIX_LOCK_write)
+ six_acquire(&lock->dep_map, 1);
return true;
}
@@ -323,7 +325,8 @@ static void __six_lock_type_slowpath(struct six_lock *lock, enum six_lock_type t
__always_inline
static void __six_lock_type(struct six_lock *lock, enum six_lock_type type)
{
- six_acquire(&lock->dep_map, 0);
+ if (type != SIX_LOCK_write)
+ six_acquire(&lock->dep_map, 0);
if (!do_six_trylock_type(lock, type))
__six_lock_type_slowpath(lock, type);
@@ -382,7 +385,8 @@ static void __six_unlock_type(struct six_lock *lock, enum six_lock_type type)
EBUG_ON(type == SIX_LOCK_write &&
!(lock->state.v & __SIX_LOCK_HELD_intent));
- six_release(&lock->dep_map);
+ if (type != SIX_LOCK_write)
+ six_release(&lock->dep_map);
if (type == SIX_LOCK_intent) {
EBUG_ON(lock->owner != current);
diff --git a/linux/workqueue.c b/linux/workqueue.c
index 550cfd3b..0d5af3fb 100644
--- a/linux/workqueue.c
+++ b/linux/workqueue.c
@@ -5,6 +5,7 @@
#include <linux/workqueue.h>
static pthread_mutex_t wq_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t work_finished = PTHREAD_COND_INITIALIZER;
static LIST_HEAD(wq_list);
struct workqueue_struct {
@@ -13,8 +14,6 @@ struct workqueue_struct {
struct work_struct *current_work;
struct list_head pending_work;
- pthread_cond_t work_finished;
-
struct task_struct *worker;
char name[24];
};
@@ -23,6 +22,11 @@ enum {
WORK_PENDING_BIT,
};
+static bool work_pending(struct work_struct *work)
+{
+ return test_bit(WORK_PENDING_BIT, work_data_bits(work));
+}
+
static void clear_work_pending(struct work_struct *work)
{
clear_bit(WORK_PENDING_BIT, work_data_bits(work));
@@ -36,7 +40,7 @@ static bool set_work_pending(struct work_struct *work)
static void __queue_work(struct workqueue_struct *wq,
struct work_struct *work)
{
- BUG_ON(!test_bit(WORK_PENDING_BIT, work_data_bits(work)));
+ BUG_ON(!work_pending(work));
BUG_ON(!list_empty(&work->entry));
list_add_tail(&work->entry, &wq->pending_work);
@@ -130,17 +134,39 @@ retry:
goto retry;
}
-static bool __flush_work(struct work_struct *work)
+static bool work_running(struct work_struct *work)
{
struct workqueue_struct *wq;
- bool ret = false;
-retry:
+
list_for_each_entry(wq, &wq_list, list)
- if (wq->current_work == work) {
- pthread_cond_wait(&wq->work_finished, &wq_lock);
- ret = true;
- goto retry;
- }
+ if (wq->current_work == work)
+ return true;
+
+ return false;
+}
+
+bool flush_work(struct work_struct *work)
+{
+ bool ret = false;
+
+ pthread_mutex_lock(&wq_lock);
+ while (work_pending(work) || work_running(work)) {
+ pthread_cond_wait(&work_finished, &wq_lock);
+ ret = true;
+ }
+ pthread_mutex_unlock(&wq_lock);
+
+ return ret;
+}
+
+static bool __flush_work(struct work_struct *work)
+{
+ bool ret = false;
+
+ while (work_running(work)) {
+ pthread_cond_wait(&work_finished, &wq_lock);
+ ret = true;
+ }
return ret;
}
@@ -228,7 +254,7 @@ static int worker_thread(void *arg)
continue;
}
- BUG_ON(!test_bit(WORK_PENDING_BIT, work_data_bits(work)));
+ BUG_ON(!work_pending(work));
list_del_init(&work->entry);
clear_work_pending(work);
@@ -236,7 +262,7 @@ static int worker_thread(void *arg)
work->func(work);
pthread_mutex_lock(&wq_lock);
- pthread_cond_broadcast(&wq->work_finished);
+ pthread_cond_broadcast(&work_finished);
}
pthread_mutex_unlock(&wq_lock);
@@ -269,8 +295,6 @@ struct workqueue_struct *alloc_workqueue(const char *fmt,
INIT_LIST_HEAD(&wq->list);
INIT_LIST_HEAD(&wq->pending_work);
- pthread_cond_init(&wq->work_finished, NULL);
-
va_start(args, max_active);
vsnprintf(wq->name, sizeof(wq->name), fmt, args);
va_end(args);