LCOV - code coverage report
Current view: top level - kernel/sched - swait.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 14 63 22.2 %
Date: 2023-04-06 08:38:28 Functions: 2 10 20.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * <linux/swait.h> (simple wait queues ) implementation:
       4             :  */
       5             : 
       6        1270 : void __init_swait_queue_head(struct swait_queue_head *q, const char *name,
       7             :                              struct lock_class_key *key)
       8             : {
       9             :         raw_spin_lock_init(&q->lock);
      10             :         lockdep_set_class_and_name(&q->lock, key, name);
      11        2540 :         INIT_LIST_HEAD(&q->task_list);
      12        1270 : }
      13             : EXPORT_SYMBOL(__init_swait_queue_head);
      14             : 
      15             : /*
      16             :  * The thing about the wake_up_state() return value; I think we can ignore it.
      17             :  *
      18             :  * If for some reason it would return 0, that means the previously waiting
      19             :  * task is already running, so it will observe condition true (or has already).
      20             :  */
      21        1016 : void swake_up_locked(struct swait_queue_head *q)
      22             : {
      23             :         struct swait_queue *curr;
      24             : 
      25        2032 :         if (list_empty(&q->task_list))
      26             :                 return;
      27             : 
      28         683 :         curr = list_first_entry(&q->task_list, typeof(*curr), task_list);
      29         683 :         wake_up_process(curr->task);
      30         683 :         list_del_init(&curr->task_list);
      31             : }
      32             : EXPORT_SYMBOL(swake_up_locked);
      33             : 
      34             : /*
      35             :  * Wake up all waiters. This is an interface which is solely exposed for
      36             :  * completions and not for general usage.
      37             :  *
      38             :  * It is intentionally different from swake_up_all() to allow usage from
      39             :  * hard interrupt context and interrupt disabled regions.
      40             :  */
      41           0 : void swake_up_all_locked(struct swait_queue_head *q)
      42             : {
      43        1176 :         while (!list_empty(&q->task_list))
      44           0 :                 swake_up_locked(q);
      45           0 : }
      46             : 
      47           0 : void swake_up_one(struct swait_queue_head *q)
      48             : {
      49             :         unsigned long flags;
      50             : 
      51           0 :         raw_spin_lock_irqsave(&q->lock, flags);
      52           0 :         swake_up_locked(q);
      53           0 :         raw_spin_unlock_irqrestore(&q->lock, flags);
      54           0 : }
      55             : EXPORT_SYMBOL(swake_up_one);
      56             : 
      57             : /*
      58             :  * Does not allow usage from IRQ disabled, since we must be able to
      59             :  * release IRQs to guarantee bounded hold time.
      60             :  */
      61           0 : void swake_up_all(struct swait_queue_head *q)
      62             : {
      63             :         struct swait_queue *curr;
      64           0 :         LIST_HEAD(tmp);
      65             : 
      66           0 :         raw_spin_lock_irq(&q->lock);
      67           0 :         list_splice_init(&q->task_list, &tmp);
      68           0 :         while (!list_empty(&tmp)) {
      69           0 :                 curr = list_first_entry(&tmp, typeof(*curr), task_list);
      70             : 
      71           0 :                 wake_up_state(curr->task, TASK_NORMAL);
      72           0 :                 list_del_init(&curr->task_list);
      73             : 
      74           0 :                 if (list_empty(&tmp))
      75             :                         break;
      76             : 
      77           0 :                 raw_spin_unlock_irq(&q->lock);
      78           0 :                 raw_spin_lock_irq(&q->lock);
      79             :         }
      80           0 :         raw_spin_unlock_irq(&q->lock);
      81           0 : }
      82             : EXPORT_SYMBOL(swake_up_all);
      83             : 
      84           0 : void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)
      85             : {
      86         683 :         wait->task = current;
      87        1366 :         if (list_empty(&wait->task_list))
      88         683 :                 list_add_tail(&wait->task_list, &q->task_list);
      89           0 : }
      90             : 
      91           0 : void prepare_to_swait_exclusive(struct swait_queue_head *q, struct swait_queue *wait, int state)
      92             : {
      93             :         unsigned long flags;
      94             : 
      95           0 :         raw_spin_lock_irqsave(&q->lock, flags);
      96           0 :         __prepare_to_swait(q, wait);
      97           0 :         set_current_state(state);
      98           0 :         raw_spin_unlock_irqrestore(&q->lock, flags);
      99           0 : }
     100             : EXPORT_SYMBOL(prepare_to_swait_exclusive);
     101             : 
     102           0 : long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state)
     103             : {
     104             :         unsigned long flags;
     105           0 :         long ret = 0;
     106             : 
     107           0 :         raw_spin_lock_irqsave(&q->lock, flags);
     108           0 :         if (signal_pending_state(state, current)) {
     109             :                 /*
     110             :                  * See prepare_to_wait_event(). TL;DR, subsequent swake_up_one()
     111             :                  * must not see us.
     112             :                  */
     113           0 :                 list_del_init(&wait->task_list);
     114           0 :                 ret = -ERESTARTSYS;
     115             :         } else {
     116           0 :                 __prepare_to_swait(q, wait);
     117           0 :                 set_current_state(state);
     118             :         }
     119           0 :         raw_spin_unlock_irqrestore(&q->lock, flags);
     120             : 
     121           0 :         return ret;
     122             : }
     123             : EXPORT_SYMBOL(prepare_to_swait_event);
     124             : 
     125           0 : void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait)
     126             : {
     127         683 :         __set_current_state(TASK_RUNNING);
     128        1366 :         if (!list_empty(&wait->task_list))
     129           0 :                 list_del_init(&wait->task_list);
     130           0 : }
     131             : 
     132           0 : void finish_swait(struct swait_queue_head *q, struct swait_queue *wait)
     133             : {
     134             :         unsigned long flags;
     135             : 
     136           0 :         __set_current_state(TASK_RUNNING);
     137             : 
     138           0 :         if (!list_empty_careful(&wait->task_list)) {
     139           0 :                 raw_spin_lock_irqsave(&q->lock, flags);
     140           0 :                 list_del_init(&wait->task_list);
     141           0 :                 raw_spin_unlock_irqrestore(&q->lock, flags);
     142             :         }
     143           0 : }
     144             : EXPORT_SYMBOL(finish_swait);

Generated by: LCOV version 1.14