mirror of https://gitee.com/openkylin/linux.git
Merge branch 'freezer'
* freezer: af_unix: use freezable blocking calls in read sigtimedwait: use freezable blocking call nanosleep: use freezable blocking call futex: use freezable blocking call select: use freezable blocking call epoll: use freezable blocking call binder: use freezable blocking calls freezer: add new freezable helpers using freezer_do_not_count() freezer: convert freezable helpers to static inline where possible freezer: convert freezable helpers to freezer_do_not_count() freezer: skip waking up tasks with PF_FREEZER_SKIP set freezer: shorten freezer sleep time using exponential backoff lockdep: check that no locks held at freeze time lockdep: remove task argument from debug_check_no_locks_held freezer: add unsafe versions of freezable helpers for CIFS freezer: add unsafe versions of freezable helpers for NFS
This commit is contained in:
commit
207bc1181b
|
@ -20,6 +20,7 @@
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <linux/fdtable.h>
|
#include <linux/fdtable.h>
|
||||||
#include <linux/file.h>
|
#include <linux/file.h>
|
||||||
|
#include <linux/freezer.h>
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/miscdevice.h>
|
#include <linux/miscdevice.h>
|
||||||
|
@ -2140,13 +2141,13 @@ static int binder_thread_read(struct binder_proc *proc,
|
||||||
if (!binder_has_proc_work(proc, thread))
|
if (!binder_has_proc_work(proc, thread))
|
||||||
ret = -EAGAIN;
|
ret = -EAGAIN;
|
||||||
} else
|
} else
|
||||||
ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread));
|
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
|
||||||
} else {
|
} else {
|
||||||
if (non_block) {
|
if (non_block) {
|
||||||
if (!binder_has_thread_work(thread))
|
if (!binder_has_thread_work(thread))
|
||||||
ret = -EAGAIN;
|
ret = -EAGAIN;
|
||||||
} else
|
} else
|
||||||
ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));
|
ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
|
||||||
}
|
}
|
||||||
|
|
||||||
binder_lock(__func__);
|
binder_lock(__func__);
|
||||||
|
|
|
@ -447,7 +447,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = wait_event_freezekillable(server->response_q,
|
error = wait_event_freezekillable_unsafe(server->response_q,
|
||||||
midQ->mid_state != MID_REQUEST_SUBMITTED);
|
midQ->mid_state != MID_REQUEST_SUBMITTED);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/anon_inodes.h>
|
#include <linux/anon_inodes.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/freezer.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/mman.h>
|
#include <asm/mman.h>
|
||||||
|
@ -1602,7 +1603,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&ep->lock, flags);
|
spin_unlock_irqrestore(&ep->lock, flags);
|
||||||
if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
|
if (!freezable_schedule_hrtimeout_range(to, slack,
|
||||||
|
HRTIMER_MODE_ABS))
|
||||||
timed_out = 1;
|
timed_out = 1;
|
||||||
|
|
||||||
spin_lock_irqsave(&ep->lock, flags);
|
spin_lock_irqsave(&ep->lock, flags);
|
||||||
|
|
|
@ -79,7 +79,7 @@ int nfs_wait_bit_killable(void *word)
|
||||||
{
|
{
|
||||||
if (fatal_signal_pending(current))
|
if (fatal_signal_pending(current))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
freezable_schedule();
|
freezable_schedule_unsafe();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
|
EXPORT_SYMBOL_GPL(nfs_wait_bit_killable);
|
||||||
|
|
|
@ -33,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
|
||||||
res = rpc_call_sync(clnt, msg, flags);
|
res = rpc_call_sync(clnt, msg, flags);
|
||||||
if (res != -EJUKEBOX)
|
if (res != -EJUKEBOX)
|
||||||
break;
|
break;
|
||||||
freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
|
freezable_schedule_timeout_killable_unsafe(NFS_JUKEBOX_RETRY_TIME);
|
||||||
res = -ERESTARTSYS;
|
res = -ERESTARTSYS;
|
||||||
} while (!fatal_signal_pending(current));
|
} while (!fatal_signal_pending(current));
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -268,7 +268,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout)
|
||||||
*timeout = NFS4_POLL_RETRY_MIN;
|
*timeout = NFS4_POLL_RETRY_MIN;
|
||||||
if (*timeout > NFS4_POLL_RETRY_MAX)
|
if (*timeout > NFS4_POLL_RETRY_MAX)
|
||||||
*timeout = NFS4_POLL_RETRY_MAX;
|
*timeout = NFS4_POLL_RETRY_MAX;
|
||||||
freezable_schedule_timeout_killable(*timeout);
|
freezable_schedule_timeout_killable_unsafe(*timeout);
|
||||||
if (fatal_signal_pending(current))
|
if (fatal_signal_pending(current))
|
||||||
res = -ERESTARTSYS;
|
res = -ERESTARTSYS;
|
||||||
*timeout <<= 1;
|
*timeout <<= 1;
|
||||||
|
@ -4528,7 +4528,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4
|
||||||
static unsigned long
|
static unsigned long
|
||||||
nfs4_set_lock_task_retry(unsigned long timeout)
|
nfs4_set_lock_task_retry(unsigned long timeout)
|
||||||
{
|
{
|
||||||
freezable_schedule_timeout_killable(timeout);
|
freezable_schedule_timeout_killable_unsafe(timeout);
|
||||||
timeout <<= 1;
|
timeout <<= 1;
|
||||||
if (timeout > NFS4_LOCK_MAXTIMEOUT)
|
if (timeout > NFS4_LOCK_MAXTIMEOUT)
|
||||||
return NFS4_LOCK_MAXTIMEOUT;
|
return NFS4_LOCK_MAXTIMEOUT;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/rcupdate.h>
|
#include <linux/rcupdate.h>
|
||||||
#include <linux/hrtimer.h>
|
#include <linux/hrtimer.h>
|
||||||
#include <linux/sched/rt.h>
|
#include <linux/sched/rt.h>
|
||||||
|
#include <linux/freezer.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
|
@ -236,7 +237,8 @@ int poll_schedule_timeout(struct poll_wqueues *pwq, int state,
|
||||||
|
|
||||||
set_current_state(state);
|
set_current_state(state);
|
||||||
if (!pwq->triggered)
|
if (!pwq->triggered)
|
||||||
rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS);
|
rc = freezable_schedule_hrtimeout_range(expires, slack,
|
||||||
|
HRTIMER_MODE_ABS);
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -51,7 +51,7 @@ struct task_struct;
|
||||||
extern void debug_show_all_locks(void);
|
extern void debug_show_all_locks(void);
|
||||||
extern void debug_show_held_locks(struct task_struct *task);
|
extern void debug_show_held_locks(struct task_struct *task);
|
||||||
extern void debug_check_no_locks_freed(const void *from, unsigned long len);
|
extern void debug_check_no_locks_freed(const void *from, unsigned long len);
|
||||||
extern void debug_check_no_locks_held(struct task_struct *task);
|
extern void debug_check_no_locks_held(void);
|
||||||
#else
|
#else
|
||||||
static inline void debug_show_all_locks(void)
|
static inline void debug_show_all_locks(void)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ debug_check_no_locks_freed(const void *from, unsigned long len)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
debug_check_no_locks_held(struct task_struct *task)
|
debug_check_no_locks_held(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#ifndef FREEZER_H_INCLUDED
|
#ifndef FREEZER_H_INCLUDED
|
||||||
#define FREEZER_H_INCLUDED
|
#define FREEZER_H_INCLUDED
|
||||||
|
|
||||||
|
#include <linux/debug_locks.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/atomic.h>
|
#include <linux/atomic.h>
|
||||||
|
@ -46,7 +47,11 @@ extern int freeze_kernel_threads(void);
|
||||||
extern void thaw_processes(void);
|
extern void thaw_processes(void);
|
||||||
extern void thaw_kernel_threads(void);
|
extern void thaw_kernel_threads(void);
|
||||||
|
|
||||||
static inline bool try_to_freeze(void)
|
/*
|
||||||
|
* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION
|
||||||
|
* If try_to_freeze causes a lockdep warning it means the caller may deadlock
|
||||||
|
*/
|
||||||
|
static inline bool try_to_freeze_unsafe(void)
|
||||||
{
|
{
|
||||||
might_sleep();
|
might_sleep();
|
||||||
if (likely(!freezing(current)))
|
if (likely(!freezing(current)))
|
||||||
|
@ -54,6 +59,13 @@ static inline bool try_to_freeze(void)
|
||||||
return __refrigerator(false);
|
return __refrigerator(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool try_to_freeze(void)
|
||||||
|
{
|
||||||
|
if (!(current->flags & PF_NOFREEZE))
|
||||||
|
debug_check_no_locks_held();
|
||||||
|
return try_to_freeze_unsafe();
|
||||||
|
}
|
||||||
|
|
||||||
extern bool freeze_task(struct task_struct *p);
|
extern bool freeze_task(struct task_struct *p);
|
||||||
extern bool set_freezable(void);
|
extern bool set_freezable(void);
|
||||||
|
|
||||||
|
@ -115,6 +127,14 @@ static inline void freezer_count(void)
|
||||||
try_to_freeze();
|
try_to_freeze();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
|
||||||
|
static inline void freezer_count_unsafe(void)
|
||||||
|
{
|
||||||
|
current->flags &= ~PF_FREEZER_SKIP;
|
||||||
|
smp_mb();
|
||||||
|
try_to_freeze_unsafe();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* freezer_should_skip - whether to skip a task when determining frozen
|
* freezer_should_skip - whether to skip a task when determining frozen
|
||||||
* state is reached
|
* state is reached
|
||||||
|
@ -139,28 +159,86 @@ static inline bool freezer_should_skip(struct task_struct *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These macros are intended to be used whenever you want allow a sleeping
|
* These functions are intended to be used whenever you want allow a sleeping
|
||||||
* task to be frozen. Note that neither return any clear indication of
|
* task to be frozen. Note that neither return any clear indication of
|
||||||
* whether a freeze event happened while in this function.
|
* whether a freeze event happened while in this function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Like schedule(), but should not block the freezer. */
|
/* Like schedule(), but should not block the freezer. */
|
||||||
#define freezable_schedule() \
|
static inline void freezable_schedule(void)
|
||||||
({ \
|
{
|
||||||
freezer_do_not_count(); \
|
freezer_do_not_count();
|
||||||
schedule(); \
|
schedule();
|
||||||
freezer_count(); \
|
freezer_count();
|
||||||
})
|
}
|
||||||
|
|
||||||
|
/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
|
||||||
|
static inline void freezable_schedule_unsafe(void)
|
||||||
|
{
|
||||||
|
freezer_do_not_count();
|
||||||
|
schedule();
|
||||||
|
freezer_count_unsafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like freezable_schedule_timeout(), but should not block the freezer. Do not
|
||||||
|
* call this with locks held.
|
||||||
|
*/
|
||||||
|
static inline long freezable_schedule_timeout(long timeout)
|
||||||
|
{
|
||||||
|
long __retval;
|
||||||
|
freezer_do_not_count();
|
||||||
|
__retval = schedule_timeout(timeout);
|
||||||
|
freezer_count();
|
||||||
|
return __retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like schedule_timeout_interruptible(), but should not block the freezer. Do not
|
||||||
|
* call this with locks held.
|
||||||
|
*/
|
||||||
|
static inline long freezable_schedule_timeout_interruptible(long timeout)
|
||||||
|
{
|
||||||
|
long __retval;
|
||||||
|
freezer_do_not_count();
|
||||||
|
__retval = schedule_timeout_interruptible(timeout);
|
||||||
|
freezer_count();
|
||||||
|
return __retval;
|
||||||
|
}
|
||||||
|
|
||||||
/* Like schedule_timeout_killable(), but should not block the freezer. */
|
/* Like schedule_timeout_killable(), but should not block the freezer. */
|
||||||
#define freezable_schedule_timeout_killable(timeout) \
|
static inline long freezable_schedule_timeout_killable(long timeout)
|
||||||
({ \
|
{
|
||||||
long __retval; \
|
long __retval;
|
||||||
freezer_do_not_count(); \
|
freezer_do_not_count();
|
||||||
__retval = schedule_timeout_killable(timeout); \
|
__retval = schedule_timeout_killable(timeout);
|
||||||
freezer_count(); \
|
freezer_count();
|
||||||
__retval; \
|
return __retval;
|
||||||
})
|
}
|
||||||
|
|
||||||
|
/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
|
||||||
|
static inline long freezable_schedule_timeout_killable_unsafe(long timeout)
|
||||||
|
{
|
||||||
|
long __retval;
|
||||||
|
freezer_do_not_count();
|
||||||
|
__retval = schedule_timeout_killable(timeout);
|
||||||
|
freezer_count_unsafe();
|
||||||
|
return __retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like schedule_hrtimeout_range(), but should not block the freezer. Do not
|
||||||
|
* call this with locks held.
|
||||||
|
*/
|
||||||
|
static inline int freezable_schedule_hrtimeout_range(ktime_t *expires,
|
||||||
|
unsigned long delta, const enum hrtimer_mode mode)
|
||||||
|
{
|
||||||
|
int __retval;
|
||||||
|
freezer_do_not_count();
|
||||||
|
__retval = schedule_hrtimeout_range(expires, delta, mode);
|
||||||
|
freezer_count();
|
||||||
|
return __retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Freezer-friendly wrappers around wait_event_interruptible(),
|
* Freezer-friendly wrappers around wait_event_interruptible(),
|
||||||
|
@ -177,33 +255,45 @@ static inline bool freezer_should_skip(struct task_struct *p)
|
||||||
__retval; \
|
__retval; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */
|
||||||
|
#define wait_event_freezekillable_unsafe(wq, condition) \
|
||||||
|
({ \
|
||||||
|
int __retval; \
|
||||||
|
freezer_do_not_count(); \
|
||||||
|
__retval = wait_event_killable(wq, (condition)); \
|
||||||
|
freezer_count_unsafe(); \
|
||||||
|
__retval; \
|
||||||
|
})
|
||||||
|
|
||||||
#define wait_event_freezable(wq, condition) \
|
#define wait_event_freezable(wq, condition) \
|
||||||
({ \
|
({ \
|
||||||
int __retval; \
|
int __retval; \
|
||||||
for (;;) { \
|
freezer_do_not_count(); \
|
||||||
__retval = wait_event_interruptible(wq, \
|
__retval = wait_event_interruptible(wq, (condition)); \
|
||||||
(condition) || freezing(current)); \
|
freezer_count(); \
|
||||||
if (__retval || (condition)) \
|
|
||||||
break; \
|
|
||||||
try_to_freeze(); \
|
|
||||||
} \
|
|
||||||
__retval; \
|
__retval; \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define wait_event_freezable_timeout(wq, condition, timeout) \
|
#define wait_event_freezable_timeout(wq, condition, timeout) \
|
||||||
({ \
|
({ \
|
||||||
long __retval = timeout; \
|
long __retval = timeout; \
|
||||||
for (;;) { \
|
freezer_do_not_count(); \
|
||||||
__retval = wait_event_interruptible_timeout(wq, \
|
__retval = wait_event_interruptible_timeout(wq, (condition), \
|
||||||
(condition) || freezing(current), \
|
__retval); \
|
||||||
__retval); \
|
freezer_count(); \
|
||||||
if (__retval <= 0 || (condition)) \
|
|
||||||
break; \
|
|
||||||
try_to_freeze(); \
|
|
||||||
} \
|
|
||||||
__retval; \
|
__retval; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define wait_event_freezable_exclusive(wq, condition) \
|
||||||
|
({ \
|
||||||
|
int __retval; \
|
||||||
|
freezer_do_not_count(); \
|
||||||
|
__retval = wait_event_interruptible_exclusive(wq, condition); \
|
||||||
|
freezer_count(); \
|
||||||
|
__retval; \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
#else /* !CONFIG_FREEZER */
|
#else /* !CONFIG_FREEZER */
|
||||||
static inline bool frozen(struct task_struct *p) { return false; }
|
static inline bool frozen(struct task_struct *p) { return false; }
|
||||||
static inline bool freezing(struct task_struct *p) { return false; }
|
static inline bool freezing(struct task_struct *p) { return false; }
|
||||||
|
@ -225,18 +315,37 @@ static inline void set_freezable(void) {}
|
||||||
|
|
||||||
#define freezable_schedule() schedule()
|
#define freezable_schedule() schedule()
|
||||||
|
|
||||||
|
#define freezable_schedule_unsafe() schedule()
|
||||||
|
|
||||||
|
#define freezable_schedule_timeout(timeout) schedule_timeout(timeout)
|
||||||
|
|
||||||
|
#define freezable_schedule_timeout_interruptible(timeout) \
|
||||||
|
schedule_timeout_interruptible(timeout)
|
||||||
|
|
||||||
#define freezable_schedule_timeout_killable(timeout) \
|
#define freezable_schedule_timeout_killable(timeout) \
|
||||||
schedule_timeout_killable(timeout)
|
schedule_timeout_killable(timeout)
|
||||||
|
|
||||||
|
#define freezable_schedule_timeout_killable_unsafe(timeout) \
|
||||||
|
schedule_timeout_killable(timeout)
|
||||||
|
|
||||||
|
#define freezable_schedule_hrtimeout_range(expires, delta, mode) \
|
||||||
|
schedule_hrtimeout_range(expires, delta, mode)
|
||||||
|
|
||||||
#define wait_event_freezable(wq, condition) \
|
#define wait_event_freezable(wq, condition) \
|
||||||
wait_event_interruptible(wq, condition)
|
wait_event_interruptible(wq, condition)
|
||||||
|
|
||||||
#define wait_event_freezable_timeout(wq, condition, timeout) \
|
#define wait_event_freezable_timeout(wq, condition, timeout) \
|
||||||
wait_event_interruptible_timeout(wq, condition, timeout)
|
wait_event_interruptible_timeout(wq, condition, timeout)
|
||||||
|
|
||||||
|
#define wait_event_freezable_exclusive(wq, condition) \
|
||||||
|
wait_event_interruptible_exclusive(wq, condition)
|
||||||
|
|
||||||
#define wait_event_freezekillable(wq, condition) \
|
#define wait_event_freezekillable(wq, condition) \
|
||||||
wait_event_killable(wq, condition)
|
wait_event_killable(wq, condition)
|
||||||
|
|
||||||
|
#define wait_event_freezekillable_unsafe(wq, condition) \
|
||||||
|
wait_event_killable(wq, condition)
|
||||||
|
|
||||||
#endif /* !CONFIG_FREEZER */
|
#endif /* !CONFIG_FREEZER */
|
||||||
|
|
||||||
#endif /* FREEZER_H_INCLUDED */
|
#endif /* FREEZER_H_INCLUDED */
|
||||||
|
|
|
@ -835,7 +835,7 @@ void do_exit(long code)
|
||||||
/*
|
/*
|
||||||
* Make sure we are holding no locks:
|
* Make sure we are holding no locks:
|
||||||
*/
|
*/
|
||||||
debug_check_no_locks_held(tsk);
|
debug_check_no_locks_held();
|
||||||
/*
|
/*
|
||||||
* We can do this unlocked here. The futex code uses this flag
|
* We can do this unlocked here. The futex code uses this flag
|
||||||
* just to verify whether the pi state cleanup has been done
|
* just to verify whether the pi state cleanup has been done
|
||||||
|
|
|
@ -110,6 +110,18 @@ bool freeze_task(struct task_struct *p)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This check can race with freezer_do_not_count, but worst case that
|
||||||
|
* will result in an extra wakeup being sent to the task. It does not
|
||||||
|
* race with freezer_count(), the barriers in freezer_count() and
|
||||||
|
* freezer_should_skip() ensure that either freezer_count() sees
|
||||||
|
* freezing == true in try_to_freeze() and freezes, or
|
||||||
|
* freezer_should_skip() sees !PF_FREEZE_SKIP and freezes the task
|
||||||
|
* normally.
|
||||||
|
*/
|
||||||
|
if (freezer_should_skip(p))
|
||||||
|
return false;
|
||||||
|
|
||||||
spin_lock_irqsave(&freezer_lock, flags);
|
spin_lock_irqsave(&freezer_lock, flags);
|
||||||
if (!freezing(p) || frozen(p)) {
|
if (!freezing(p) || frozen(p)) {
|
||||||
spin_unlock_irqrestore(&freezer_lock, flags);
|
spin_unlock_irqrestore(&freezer_lock, flags);
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include <linux/nsproxy.h>
|
#include <linux/nsproxy.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/sched/rt.h>
|
#include <linux/sched/rt.h>
|
||||||
|
#include <linux/freezer.h>
|
||||||
|
|
||||||
#include <asm/futex.h>
|
#include <asm/futex.h>
|
||||||
|
|
||||||
|
@ -1807,7 +1808,7 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
|
||||||
* is no timeout, or if it has yet to expire.
|
* is no timeout, or if it has yet to expire.
|
||||||
*/
|
*/
|
||||||
if (!timeout || timeout->task)
|
if (!timeout || timeout->task)
|
||||||
schedule();
|
freezable_schedule();
|
||||||
}
|
}
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include <linux/sched/sysctl.h>
|
#include <linux/sched/sysctl.h>
|
||||||
#include <linux/sched/rt.h>
|
#include <linux/sched/rt.h>
|
||||||
#include <linux/timer.h>
|
#include <linux/timer.h>
|
||||||
|
#include <linux/freezer.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
|
@ -1545,7 +1546,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod
|
||||||
t->task = NULL;
|
t->task = NULL;
|
||||||
|
|
||||||
if (likely(t->task))
|
if (likely(t->task))
|
||||||
schedule();
|
freezable_schedule();
|
||||||
|
|
||||||
hrtimer_cancel(&t->timer);
|
hrtimer_cancel(&t->timer);
|
||||||
mode = HRTIMER_MODE_ABS;
|
mode = HRTIMER_MODE_ABS;
|
||||||
|
|
|
@ -4090,7 +4090,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
|
EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
|
||||||
|
|
||||||
static void print_held_locks_bug(struct task_struct *curr)
|
static void print_held_locks_bug(void)
|
||||||
{
|
{
|
||||||
if (!debug_locks_off())
|
if (!debug_locks_off())
|
||||||
return;
|
return;
|
||||||
|
@ -4099,22 +4099,21 @@ static void print_held_locks_bug(struct task_struct *curr)
|
||||||
|
|
||||||
printk("\n");
|
printk("\n");
|
||||||
printk("=====================================\n");
|
printk("=====================================\n");
|
||||||
printk("[ BUG: lock held at task exit time! ]\n");
|
printk("[ BUG: %s/%d still has locks held! ]\n",
|
||||||
|
current->comm, task_pid_nr(current));
|
||||||
print_kernel_ident();
|
print_kernel_ident();
|
||||||
printk("-------------------------------------\n");
|
printk("-------------------------------------\n");
|
||||||
printk("%s/%d is exiting with locks still held!\n",
|
lockdep_print_held_locks(current);
|
||||||
curr->comm, task_pid_nr(curr));
|
|
||||||
lockdep_print_held_locks(curr);
|
|
||||||
|
|
||||||
printk("\nstack backtrace:\n");
|
printk("\nstack backtrace:\n");
|
||||||
dump_stack();
|
dump_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug_check_no_locks_held(struct task_struct *task)
|
void debug_check_no_locks_held(void)
|
||||||
{
|
{
|
||||||
if (unlikely(task->lockdep_depth > 0))
|
if (unlikely(current->lockdep_depth > 0))
|
||||||
print_held_locks_bug(task);
|
print_held_locks_bug();
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(debug_check_no_locks_held);
|
||||||
|
|
||||||
void debug_show_all_locks(void)
|
void debug_show_all_locks(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,9 +30,10 @@ static int try_to_freeze_tasks(bool user_only)
|
||||||
unsigned int todo;
|
unsigned int todo;
|
||||||
bool wq_busy = false;
|
bool wq_busy = false;
|
||||||
struct timeval start, end;
|
struct timeval start, end;
|
||||||
u64 elapsed_csecs64;
|
u64 elapsed_msecs64;
|
||||||
unsigned int elapsed_csecs;
|
unsigned int elapsed_msecs;
|
||||||
bool wakeup = false;
|
bool wakeup = false;
|
||||||
|
int sleep_usecs = USEC_PER_MSEC;
|
||||||
|
|
||||||
do_gettimeofday(&start);
|
do_gettimeofday(&start);
|
||||||
|
|
||||||
|
@ -68,22 +69,25 @@ static int try_to_freeze_tasks(bool user_only)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to retry, but first give the freezing tasks some
|
* We need to retry, but first give the freezing tasks some
|
||||||
* time to enter the refrigerator.
|
* time to enter the refrigerator. Start with an initial
|
||||||
|
* 1 ms sleep followed by exponential backoff until 8 ms.
|
||||||
*/
|
*/
|
||||||
msleep(10);
|
usleep_range(sleep_usecs / 2, sleep_usecs);
|
||||||
|
if (sleep_usecs < 8 * USEC_PER_MSEC)
|
||||||
|
sleep_usecs *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
do_gettimeofday(&end);
|
do_gettimeofday(&end);
|
||||||
elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
|
elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start);
|
||||||
do_div(elapsed_csecs64, NSEC_PER_SEC / 100);
|
do_div(elapsed_msecs64, NSEC_PER_MSEC);
|
||||||
elapsed_csecs = elapsed_csecs64;
|
elapsed_msecs = elapsed_msecs64;
|
||||||
|
|
||||||
if (todo) {
|
if (todo) {
|
||||||
printk("\n");
|
printk("\n");
|
||||||
printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds "
|
printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds "
|
||||||
"(%d tasks refusing to freeze, wq_busy=%d):\n",
|
"(%d tasks refusing to freeze, wq_busy=%d):\n",
|
||||||
wakeup ? "aborted" : "failed",
|
wakeup ? "aborted" : "failed",
|
||||||
elapsed_csecs / 100, elapsed_csecs % 100,
|
elapsed_msecs / 1000, elapsed_msecs % 1000,
|
||||||
todo - wq_busy, wq_busy);
|
todo - wq_busy, wq_busy);
|
||||||
|
|
||||||
if (!wakeup) {
|
if (!wakeup) {
|
||||||
|
@ -96,8 +100,8 @@ static int try_to_freeze_tasks(bool user_only)
|
||||||
read_unlock(&tasklist_lock);
|
read_unlock(&tasklist_lock);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100,
|
printk("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000,
|
||||||
elapsed_csecs % 100);
|
elapsed_msecs % 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return todo ? -EBUSY : 0;
|
return todo ? -EBUSY : 0;
|
||||||
|
|
|
@ -2848,7 +2848,7 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
|
||||||
recalc_sigpending();
|
recalc_sigpending();
|
||||||
spin_unlock_irq(&tsk->sighand->siglock);
|
spin_unlock_irq(&tsk->sighand->siglock);
|
||||||
|
|
||||||
timeout = schedule_timeout_interruptible(timeout);
|
timeout = freezable_schedule_timeout_interruptible(timeout);
|
||||||
|
|
||||||
spin_lock_irq(&tsk->sighand->siglock);
|
spin_lock_irq(&tsk->sighand->siglock);
|
||||||
__set_task_blocked(tsk, &tsk->real_blocked);
|
__set_task_blocked(tsk, &tsk->real_blocked);
|
||||||
|
|
|
@ -254,7 +254,7 @@ static int rpc_wait_bit_killable(void *word)
|
||||||
{
|
{
|
||||||
if (fatal_signal_pending(current))
|
if (fatal_signal_pending(current))
|
||||||
return -ERESTARTSYS;
|
return -ERESTARTSYS;
|
||||||
freezable_schedule();
|
freezable_schedule_unsafe();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@
|
||||||
#include <linux/mount.h>
|
#include <linux/mount.h>
|
||||||
#include <net/checksum.h>
|
#include <net/checksum.h>
|
||||||
#include <linux/security.h>
|
#include <linux/security.h>
|
||||||
|
#include <linux/freezer.h>
|
||||||
|
|
||||||
struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
|
struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE];
|
||||||
EXPORT_SYMBOL_GPL(unix_socket_table);
|
EXPORT_SYMBOL_GPL(unix_socket_table);
|
||||||
|
@ -1879,7 +1880,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo,
|
||||||
|
|
||||||
set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
|
set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
|
||||||
unix_state_unlock(sk);
|
unix_state_unlock(sk);
|
||||||
timeo = schedule_timeout(timeo);
|
timeo = freezable_schedule_timeout(timeo);
|
||||||
unix_state_lock(sk);
|
unix_state_lock(sk);
|
||||||
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
|
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue