X-Git-Url: http://git.madism.org/?p=~madcoder%2Fpwqr.git;a=blobdiff_plain;f=kernel%2Fpwqr.c;h=e4e3f58a872b146af038b8cffc9a5c6f2ca5ab0a;hp=4d4c4cd10b5a8112c4e57c367287dcf89e2b1aa9;hb=b29ccbcc4ab80bc7e7b2131349459cc9e96d49ef;hpb=006df851760b087ea18222f4c417756cbf69b2ea;ds=sidebyside diff --git a/kernel/pwqr.c b/kernel/pwqr.c index 4d4c4cd..e4e3f58 100644 --- a/kernel/pwqr.c +++ b/kernel/pwqr.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,7 @@ #include "pwqr.h" +#define PWQR_UNPARK_DELAY (HZ / 10) #define PWQR_HASH_BITS 5 #define PWQR_HASH_SIZE (1 << PWQR_HASH_BITS) @@ -49,6 +51,7 @@ struct pwqr_task_bucket { struct pwqr_sb { struct kref kref; struct rcu_head rcu; + struct timer_list timer; wait_queue_head_t wqh; pid_t tgid; @@ -97,10 +100,9 @@ static inline void __pwqr_sb_update_state(struct pwqr_sb *sb, int running_delta) sb->running += running_delta; overcommit = sb->running + sb->waiting - sb->concurrency; - if (overcommit == 0) - return; - - if (overcommit > 0) { + if (overcommit == 0) { + /* do nothing */ + } else if (overcommit > 0) { if (overcommit > sb->waiting) { sb->quarantined += sb->waiting; sb->waiting = 0; @@ -118,9 +120,29 @@ static inline void __pwqr_sb_update_state(struct pwqr_sb *sb, int running_delta) sb->waiting += sb->quarantined; sb->quarantined = 0; } else if (sb->waiting == 0 && sb->parked) { - wake_up_locked(&sb->wqh); + if (!timer_pending(&sb->timer)) { + mod_timer(&sb->timer, jiffies + + PWQR_UNPARK_DELAY); + } + return; } } + + if (timer_pending(&sb->timer)) + del_timer(&sb->timer); +} + +static void pwqr_sb_timer_cb(unsigned long arg) +{ + struct pwqr_sb *sb = (struct pwqr_sb *)arg; + unsigned long flags; + + pwqr_sb_lock_irqsave(sb, flags); + if (sb->waiting == 0 && sb->parked && sb->running < sb->concurrency) { + if (sb->overcommit_wakes == 0) + wake_up_locked(&sb->wqh); + } + pwqr_sb_unlock_irqrestore(sb, flags); } static struct pwqr_sb *pwqr_sb_create(void) @@ -135,6 +157,9 @@ static struct pwqr_sb *pwqr_sb_create(void) init_waitqueue_head(&sb->wqh); sb->tgid = current->tgid; sb->concurrency = num_online_cpus(); + init_timer(&sb->timer); + sb->timer.function = pwqr_sb_timer_cb; + sb->timer.data = (unsigned long)sb; __module_get(THIS_MODULE); return sb; @@ -156,6 +181,7 @@ static void pwqr_sb_release(struct kref *kref) { struct pwqr_sb *sb = container_of(kref, struct pwqr_sb, kref); + del_timer_sync(&sb->timer); call_rcu(&sb->rcu, pwqr_sb_finalize); } static inline void pwqr_sb_put(struct pwqr_sb *sb)