Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0dbc3be authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "workqueue: fix subtle pool management issue which can stall whole worker_pool"

parents 8e22f218 ede8177f
Loading
Loading
Loading
Loading
+11 −18
Original line number Original line Diff line number Diff line
@@ -1935,17 +1935,11 @@ static void pool_mayday_timeout(unsigned long __pool)
 * spin_lock_irq(pool->lock) which may be released and regrabbed
 * spin_lock_irq(pool->lock) which may be released and regrabbed
 * multiple times.  Does GFP_KERNEL allocations.  Called only from
 * multiple times.  Does GFP_KERNEL allocations.  Called only from
 * manager.
 * manager.
 *
 * RETURNS:
 * %false if no action was taken and pool->lock stayed locked, %true
 * otherwise.
 */
 */
static bool maybe_create_worker(struct worker_pool *pool)
static void maybe_create_worker(struct worker_pool *pool)
__releases(&pool->lock)
__releases(&pool->lock)
__acquires(&pool->lock)
__acquires(&pool->lock)
{
{
	if (!need_to_create_worker(pool))
		return false;
restart:
restart:
	spin_unlock_irq(&pool->lock);
	spin_unlock_irq(&pool->lock);


@@ -1962,7 +1956,7 @@ restart:
			start_worker(worker);
			start_worker(worker);
			if (WARN_ON_ONCE(need_to_create_worker(pool)))
			if (WARN_ON_ONCE(need_to_create_worker(pool)))
				goto restart;
				goto restart;
			return true;
			return;
		}
		}


		if (!need_to_create_worker(pool))
		if (!need_to_create_worker(pool))
@@ -1979,7 +1973,6 @@ restart:
	spin_lock_irq(&pool->lock);
	spin_lock_irq(&pool->lock);
	if (need_to_create_worker(pool))
	if (need_to_create_worker(pool))
		goto restart;
		goto restart;
	return true;
}
}


/**
/**
@@ -2036,14 +2029,15 @@ static bool maybe_destroy_workers(struct worker_pool *pool)
 * spin_lock_irq(pool->lock) which may be released and regrabbed
 * spin_lock_irq(pool->lock) which may be released and regrabbed
 * multiple times.  Does GFP_KERNEL allocations.
 * multiple times.  Does GFP_KERNEL allocations.
 *
 *
 * RETURNS:
 * Return:
 * spin_lock_irq(pool->lock) which may be released and regrabbed
 * %false if the pool doesn't need management and the caller can safely
 * multiple times.  Does GFP_KERNEL allocations.
 * start processing works, %true if management function was performed and
 * the conditions that the caller verified before calling the function may
 * no longer be true.
 */
 */
static bool manage_workers(struct worker *worker)
static bool manage_workers(struct worker *worker)
{
{
	struct worker_pool *pool = worker->pool;
	struct worker_pool *pool = worker->pool;
	bool ret = false;


	/*
	/*
	 * Managership is governed by two mutexes - manager_arb and
	 * Managership is governed by two mutexes - manager_arb and
@@ -2067,7 +2061,7 @@ static bool manage_workers(struct worker *worker)
	 * manager_mutex.
	 * manager_mutex.
	 */
	 */
	if (!mutex_trylock(&pool->manager_arb))
	if (!mutex_trylock(&pool->manager_arb))
		return ret;
		return false;


	/*
	/*
	 * With manager arbitration won, manager_mutex would be free in
	 * With manager arbitration won, manager_mutex would be free in
@@ -2077,7 +2071,6 @@ static bool manage_workers(struct worker *worker)
		spin_unlock_irq(&pool->lock);
		spin_unlock_irq(&pool->lock);
		mutex_lock(&pool->manager_mutex);
		mutex_lock(&pool->manager_mutex);
		spin_lock_irq(&pool->lock);
		spin_lock_irq(&pool->lock);
		ret = true;
	}
	}


	pool->flags &= ~POOL_MANAGE_WORKERS;
	pool->flags &= ~POOL_MANAGE_WORKERS;
@@ -2086,12 +2079,12 @@ static bool manage_workers(struct worker *worker)
	 * Destroy and then create so that may_start_working() is true
	 * Destroy and then create so that may_start_working() is true
	 * on return.
	 * on return.
	 */
	 */
	ret |= maybe_destroy_workers(pool);
	maybe_destroy_workers(pool);
	ret |= maybe_create_worker(pool);
	maybe_create_worker(pool);


	mutex_unlock(&pool->manager_mutex);
	mutex_unlock(&pool->manager_mutex);
	mutex_unlock(&pool->manager_arb);
	mutex_unlock(&pool->manager_arb);
	return ret;
	return true;
}
}


/**
/**