LCOV - code coverage report
Current view: top level - kernel/bpf - percpu_freelist.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 0 50 0.0 %
Date: 2020-09-30 20:25:40 Functions: 0 8 0.0 %
Branches: 0 22 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /* Copyright (c) 2016 Facebook
       3                 :            :  */
       4                 :            : #include "percpu_freelist.h"
       5                 :            : 
       6                 :          0 : int pcpu_freelist_init(struct pcpu_freelist *s)
       7                 :            : {
       8                 :            :         int cpu;
       9                 :            : 
      10                 :          0 :         s->freelist = alloc_percpu(struct pcpu_freelist_head);
      11         [ #  # ]:          0 :         if (!s->freelist)
      12                 :            :                 return -ENOMEM;
      13                 :            : 
      14         [ #  # ]:          0 :         for_each_possible_cpu(cpu) {
      15                 :          0 :                 struct pcpu_freelist_head *head = per_cpu_ptr(s->freelist, cpu);
      16                 :            : 
      17                 :          0 :                 raw_spin_lock_init(&head->lock);
      18                 :          0 :                 head->first = NULL;
      19                 :            :         }
      20                 :            :         return 0;
      21                 :            : }
      22                 :            : 
      23                 :          0 : void pcpu_freelist_destroy(struct pcpu_freelist *s)
      24                 :            : {
      25                 :          0 :         free_percpu(s->freelist);
      26                 :          0 : }
      27                 :            : 
      28                 :          0 : static inline void ___pcpu_freelist_push(struct pcpu_freelist_head *head,
      29                 :            :                                          struct pcpu_freelist_node *node)
      30                 :            : {
      31                 :          0 :         raw_spin_lock(&head->lock);
      32                 :          0 :         node->next = head->first;
      33                 :          0 :         head->first = node;
      34                 :            :         raw_spin_unlock(&head->lock);
      35                 :          0 : }
      36                 :            : 
      37                 :          0 : void __pcpu_freelist_push(struct pcpu_freelist *s,
      38                 :            :                         struct pcpu_freelist_node *node)
      39                 :            : {
      40                 :          0 :         struct pcpu_freelist_head *head = this_cpu_ptr(s->freelist);
      41                 :            : 
      42                 :          0 :         ___pcpu_freelist_push(head, node);
      43                 :          0 : }
      44                 :            : 
      45                 :          0 : void pcpu_freelist_push(struct pcpu_freelist *s,
      46                 :            :                         struct pcpu_freelist_node *node)
      47                 :            : {
      48                 :            :         unsigned long flags;
      49                 :            : 
      50                 :          0 :         local_irq_save(flags);
      51                 :            :         __pcpu_freelist_push(s, node);
      52         [ #  # ]:          0 :         local_irq_restore(flags);
      53                 :          0 : }
      54                 :            : 
      55                 :          0 : void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
      56                 :            :                             u32 nr_elems)
      57                 :            : {
      58                 :            :         struct pcpu_freelist_head *head;
      59                 :            :         unsigned long flags;
      60                 :            :         int i, cpu, pcpu_entries;
      61                 :            : 
      62                 :          0 :         pcpu_entries = nr_elems / num_possible_cpus() + 1;
      63                 :            :         i = 0;
      64                 :            : 
      65                 :            :         /* disable irq to workaround lockdep false positive
      66                 :            :          * in bpf usage pcpu_freelist_populate() will never race
      67                 :            :          * with pcpu_freelist_push()
      68                 :            :          */
      69                 :          0 :         local_irq_save(flags);
      70         [ #  # ]:          0 :         for_each_possible_cpu(cpu) {
      71                 :            : again:
      72                 :          0 :                 head = per_cpu_ptr(s->freelist, cpu);
      73                 :          0 :                 ___pcpu_freelist_push(head, buf);
      74                 :          0 :                 i++;
      75                 :          0 :                 buf += elem_size;
      76         [ #  # ]:          0 :                 if (i == nr_elems)
      77                 :            :                         break;
      78         [ #  # ]:          0 :                 if (i % pcpu_entries)
      79                 :            :                         goto again;
      80                 :            :         }
      81         [ #  # ]:          0 :         local_irq_restore(flags);
      82                 :          0 : }
      83                 :            : 
      84                 :          0 : struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *s)
      85                 :            : {
      86                 :            :         struct pcpu_freelist_head *head;
      87                 :            :         struct pcpu_freelist_node *node;
      88                 :            :         int orig_cpu, cpu;
      89                 :            : 
      90                 :            :         orig_cpu = cpu = raw_smp_processor_id();
      91                 :            :         while (1) {
      92                 :          0 :                 head = per_cpu_ptr(s->freelist, cpu);
      93                 :          0 :                 raw_spin_lock(&head->lock);
      94                 :          0 :                 node = head->first;
      95         [ #  # ]:          0 :                 if (node) {
      96                 :          0 :                         head->first = node->next;
      97                 :            :                         raw_spin_unlock(&head->lock);
      98                 :          0 :                         return node;
      99                 :            :                 }
     100                 :            :                 raw_spin_unlock(&head->lock);
     101                 :          0 :                 cpu = cpumask_next(cpu, cpu_possible_mask);
     102         [ #  # ]:          0 :                 if (cpu >= nr_cpu_ids)
     103                 :            :                         cpu = 0;
     104         [ #  # ]:          0 :                 if (cpu == orig_cpu)
     105                 :            :                         return NULL;
     106                 :            :         }
     107                 :            : }
     108                 :            : 
     109                 :          0 : struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
     110                 :            : {
     111                 :            :         struct pcpu_freelist_node *ret;
     112                 :            :         unsigned long flags;
     113                 :            : 
     114                 :          0 :         local_irq_save(flags);
     115                 :          0 :         ret = __pcpu_freelist_pop(s);
     116         [ #  # ]:          0 :         local_irq_restore(flags);
     117                 :          0 :         return ret;
     118                 :            : }

Generated by: LCOV version 1.14