Coverage Report

Created: 2017-10-25 09:10

/root/src/xen/xen/common/smp.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * xen/common/smp.c
3
 *
4
 * Generic SMP function
5
 *
6
 * Copyright (c) 2013 Citrix Systems.
7
 *
8
 * This program is free software; you can redistribute it and/or modify
9
 * it under the terms of the GNU General Public License as published by
10
 * the Free Software Foundation; either version 2 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 */
18
19
#include <asm/hardirq.h>
20
#include <asm/processor.h>
21
#include <xen/spinlock.h>
22
#include <xen/smp.h>
23
24
/*
25
 * Structure and data for smp_call_function()/on_selected_cpus().
26
 */
27
static DEFINE_SPINLOCK(call_lock);
28
static struct call_data_struct {
29
    void (*func) (void *info);
30
    void *info;
31
    int wait;
32
    cpumask_t selected;
33
} call_data;
34
35
void smp_call_function(
36
    void (*func) (void *info),
37
    void *info,
38
    int wait)
39
1
{
40
1
    cpumask_t allbutself;
41
1
42
1
    cpumask_andnot(&allbutself, &cpu_online_map,
43
1
                   cpumask_of(smp_processor_id()));
44
1
    on_selected_cpus(&allbutself, func, info, wait);
45
1
}
46
47
void on_selected_cpus(
48
    const cpumask_t *selected,
49
    void (*func) (void *info),
50
    void *info,
51
    int wait)
52
222k
{
53
222k
    unsigned int nr_cpus;
54
222k
55
222k
    ASSERT(local_irq_is_enabled());
56
222k
    ASSERT(cpumask_subset(selected, &cpu_online_map));
57
222k
58
222k
    spin_lock(&call_lock);
59
222k
60
222k
    cpumask_copy(&call_data.selected, selected);
61
222k
62
222k
    nr_cpus = cpumask_weight(&call_data.selected);
63
222k
    if ( nr_cpus == 0 )
64
149
        goto out;
65
222k
66
222k
    call_data.func = func;
67
222k
    call_data.info = info;
68
222k
    call_data.wait = wait;
69
222k
70
222k
    smp_send_call_function_mask(&call_data.selected);
71
222k
72
33.4M
    while ( !cpumask_empty(&call_data.selected) )
73
33.2M
        cpu_relax();
74
222k
75
222k
out:
76
222k
    spin_unlock(&call_lock);
77
222k
}
78
79
void smp_call_function_interrupt(void)
80
2.12M
{
81
2.12M
    void (*func)(void *info) = call_data.func;
82
2.12M
    void *info = call_data.info;
83
2.12M
    unsigned int cpu = smp_processor_id();
84
2.12M
85
2.12M
    if ( !cpumask_test_cpu(cpu, &call_data.selected) )
86
0
        return;
87
2.12M
88
2.12M
    irq_enter();
89
2.12M
90
2.12M
    if ( call_data.wait )
91
1.97M
    {
92
1.97M
        (*func)(info);
93
1.97M
        smp_mb();
94
1.97M
        cpumask_clear_cpu(cpu, &call_data.selected);
95
1.97M
    }
96
2.12M
    else
97
151k
    {
98
151k
        smp_mb();
99
151k
        cpumask_clear_cpu(cpu, &call_data.selected);
100
151k
        (*func)(info);
101
151k
    }
102
2.12M
103
2.12M
    irq_exit();
104
2.12M
}
105
106
/*
107
 * Local variables:
108
 * mode: C
109
 * c-file-style: "BSD"
110
 * c-basic-offset: 4
111
 * indent-tabs-mode: nil
112
 * End:
113
 */