diff options
Diffstat (limited to 'include/linux/wait_bit.h')
| -rw-r--r-- | include/linux/wait_bit.h | 95 |
1 files changed, 69 insertions, 26 deletions
diff --git a/include/linux/wait_bit.h b/include/linux/wait_bit.h index 61b39eaf7cad..9318b2166439 100644 --- a/include/linux/wait_bit.h +++ b/include/linux/wait_bit.h | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | struct wait_bit_key { | 10 | struct wait_bit_key { |
| 11 | void *flags; | 11 | void *flags; |
| 12 | int bit_nr; | 12 | int bit_nr; |
| 13 | #define WAIT_ATOMIC_T_BIT_NR -1 | ||
| 14 | unsigned long timeout; | 13 | unsigned long timeout; |
| 15 | }; | 14 | }; |
| 16 | 15 | ||
| @@ -22,21 +21,15 @@ struct wait_bit_queue_entry { | |||
| 22 | #define __WAIT_BIT_KEY_INITIALIZER(word, bit) \ | 21 | #define __WAIT_BIT_KEY_INITIALIZER(word, bit) \ |
| 23 | { .flags = word, .bit_nr = bit, } | 22 | { .flags = word, .bit_nr = bit, } |
| 24 | 23 | ||
| 25 | #define __WAIT_ATOMIC_T_KEY_INITIALIZER(p) \ | ||
| 26 | { .flags = p, .bit_nr = WAIT_ATOMIC_T_BIT_NR, } | ||
| 27 | |||
| 28 | typedef int wait_bit_action_f(struct wait_bit_key *key, int mode); | 24 | typedef int wait_bit_action_f(struct wait_bit_key *key, int mode); |
| 29 | typedef int wait_atomic_t_action_f(atomic_t *counter, unsigned int mode); | ||
| 30 | 25 | ||
| 31 | void __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit); | 26 | void __wake_up_bit(struct wait_queue_head *wq_head, void *word, int bit); |
| 32 | int __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); | 27 | int __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); |
| 33 | int __wait_on_bit_lock(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); | 28 | int __wait_on_bit_lock(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_entry, wait_bit_action_f *action, unsigned int mode); |
| 34 | void wake_up_bit(void *word, int bit); | 29 | void wake_up_bit(void *word, int bit); |
| 35 | void wake_up_atomic_t(atomic_t *p); | ||
| 36 | int out_of_line_wait_on_bit(void *word, int, wait_bit_action_f *action, unsigned int mode); | 30 | int out_of_line_wait_on_bit(void *word, int, wait_bit_action_f *action, unsigned int mode); |
| 37 | int out_of_line_wait_on_bit_timeout(void *word, int, wait_bit_action_f *action, unsigned int mode, unsigned long timeout); | 31 | int out_of_line_wait_on_bit_timeout(void *word, int, wait_bit_action_f *action, unsigned int mode, unsigned long timeout); |
| 38 | int out_of_line_wait_on_bit_lock(void *word, int, wait_bit_action_f *action, unsigned int mode); | 32 | int out_of_line_wait_on_bit_lock(void *word, int, wait_bit_action_f *action, unsigned int mode); |
| 39 | int out_of_line_wait_on_atomic_t(atomic_t *p, wait_atomic_t_action_f action, unsigned int mode); | ||
| 40 | struct wait_queue_head *bit_waitqueue(void *word, int bit); | 33 | struct wait_queue_head *bit_waitqueue(void *word, int bit); |
| 41 | extern void __init wait_bit_init(void); | 34 | extern void __init wait_bit_init(void); |
| 42 | 35 | ||
| @@ -57,7 +50,6 @@ extern int bit_wait(struct wait_bit_key *key, int mode); | |||
| 57 | extern int bit_wait_io(struct wait_bit_key *key, int mode); | 50 | extern int bit_wait_io(struct wait_bit_key *key, int mode); |
| 58 | extern int bit_wait_timeout(struct wait_bit_key *key, int mode); | 51 | extern int bit_wait_timeout(struct wait_bit_key *key, int mode); |
| 59 | extern int bit_wait_io_timeout(struct wait_bit_key *key, int mode); | 52 | extern int bit_wait_io_timeout(struct wait_bit_key *key, int mode); |
| 60 | extern int atomic_t_wait(atomic_t *counter, unsigned int mode); | ||
| 61 | 53 | ||
| 62 | /** | 54 | /** |
| 63 | * wait_on_bit - wait for a bit to be cleared | 55 | * wait_on_bit - wait for a bit to be cleared |
| @@ -243,23 +235,74 @@ wait_on_bit_lock_action(unsigned long *word, int bit, wait_bit_action_f *action, | |||
| 243 | return out_of_line_wait_on_bit_lock(word, bit, action, mode); | 235 | return out_of_line_wait_on_bit_lock(word, bit, action, mode); |
| 244 | } | 236 | } |
| 245 | 237 | ||
| 246 | /** | 238 | extern void init_wait_var_entry(struct wait_bit_queue_entry *wbq_entry, void *var, int flags); |
| 247 | * wait_on_atomic_t - Wait for an atomic_t to become 0 | 239 | extern void wake_up_var(void *var); |
| 248 | * @val: The atomic value being waited on, a kernel virtual address | 240 | extern wait_queue_head_t *__var_waitqueue(void *p); |
| 249 | * @action: the function used to sleep, which may take special actions | 241 | |
| 250 | * @mode: the task state to sleep in | 242 | #define ___wait_var_event(var, condition, state, exclusive, ret, cmd) \ |
| 251 | * | 243 | ({ \ |
| 252 | * Wait for an atomic_t to become 0. We abuse the bit-wait waitqueue table for | 244 | __label__ __out; \ |
| 253 | * the purpose of getting a waitqueue, but we set the key to a bit number | 245 | struct wait_queue_head *__wq_head = __var_waitqueue(var); \ |
| 254 | * outside of the target 'word'. | 246 | struct wait_bit_queue_entry __wbq_entry; \ |
| 255 | */ | 247 | long __ret = ret; /* explicit shadow */ \ |
| 256 | static inline | 248 | \ |
| 257 | int wait_on_atomic_t(atomic_t *val, wait_atomic_t_action_f action, unsigned mode) | 249 | init_wait_var_entry(&__wbq_entry, var, \ |
| 258 | { | 250 | exclusive ? WQ_FLAG_EXCLUSIVE : 0); \ |
| 259 | might_sleep(); | 251 | for (;;) { \ |
| 260 | if (atomic_read(val) == 0) | 252 | long __int = prepare_to_wait_event(__wq_head, \ |
| 261 | return 0; | 253 | &__wbq_entry.wq_entry, \ |
| 262 | return out_of_line_wait_on_atomic_t(val, action, mode); | 254 | state); \ |
| 263 | } | 255 | if (condition) \ |
| 256 | break; \ | ||
| 257 | \ | ||
| 258 | if (___wait_is_interruptible(state) && __int) { \ | ||
| 259 | __ret = __int; \ | ||
| 260 | goto __out; \ | ||
| 261 | } \ | ||
| 262 | \ | ||
| 263 | cmd; \ | ||
| 264 | } \ | ||
| 265 | finish_wait(__wq_head, &__wbq_entry.wq_entry); \ | ||
| 266 | __out: __ret; \ | ||
| 267 | }) | ||
| 268 | |||
| 269 | #define __wait_var_event(var, condition) \ | ||
| 270 | ___wait_var_event(var, condition, TASK_UNINTERRUPTIBLE, 0, 0, \ | ||
| 271 | schedule()) | ||
| 272 | |||
| 273 | #define wait_var_event(var, condition) \ | ||
| 274 | do { \ | ||
| 275 | might_sleep(); \ | ||
| 276 | if (condition) \ | ||
| 277 | break; \ | ||
| 278 | __wait_var_event(var, condition); \ | ||
| 279 | } while (0) | ||
| 280 | |||
| 281 | #define __wait_var_event_killable(var, condition) \ | ||
| 282 | ___wait_var_event(var, condition, TASK_KILLABLE, 0, 0, \ | ||
| 283 | schedule()) | ||
| 284 | |||
| 285 | #define wait_var_event_killable(var, condition) \ | ||
| 286 | ({ \ | ||
| 287 | int __ret = 0; \ | ||
| 288 | might_sleep(); \ | ||
| 289 | if (!(condition)) \ | ||
| 290 | __ret = __wait_var_event_killable(var, condition); \ | ||
| 291 | __ret; \ | ||
| 292 | }) | ||
| 293 | |||
| 294 | #define __wait_var_event_timeout(var, condition, timeout) \ | ||
| 295 | ___wait_var_event(var, ___wait_cond_timeout(condition), \ | ||
| 296 | TASK_UNINTERRUPTIBLE, 0, timeout, \ | ||
| 297 | __ret = schedule_timeout(__ret)) | ||
| 298 | |||
| 299 | #define wait_var_event_timeout(var, condition, timeout) \ | ||
| 300 | ({ \ | ||
| 301 | long __ret = timeout; \ | ||
| 302 | might_sleep(); \ | ||
| 303 | if (!___wait_cond_timeout(condition)) \ | ||
| 304 | __ret = __wait_var_event_timeout(var, condition, timeout); \ | ||
| 305 | __ret; \ | ||
| 306 | }) | ||
| 264 | 307 | ||
| 265 | #endif /* _LINUX_WAIT_BIT_H */ | 308 | #endif /* _LINUX_WAIT_BIT_H */ |
