root / util / qemu-progress.c @ 795ca114
History | View | Annotate | Download (4.3 kB)
1 | 6b837bc4 | Jes Sorensen | /*
|
---|---|---|---|
2 | 6b837bc4 | Jes Sorensen | * QEMU progress printing utility functions
|
3 | 6b837bc4 | Jes Sorensen | *
|
4 | 6b837bc4 | Jes Sorensen | * Copyright (C) 2011 Jes Sorensen <Jes.Sorensen@redhat.com>
|
5 | 6b837bc4 | Jes Sorensen | *
|
6 | 6b837bc4 | Jes Sorensen | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 6b837bc4 | Jes Sorensen | * of this software and associated documentation files (the "Software"), to deal
|
8 | 6b837bc4 | Jes Sorensen | * in the Software without restriction, including without limitation the rights
|
9 | 6b837bc4 | Jes Sorensen | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 6b837bc4 | Jes Sorensen | * copies of the Software, and to permit persons to whom the Software is
|
11 | 6b837bc4 | Jes Sorensen | * furnished to do so, subject to the following conditions:
|
12 | 6b837bc4 | Jes Sorensen | *
|
13 | 6b837bc4 | Jes Sorensen | * The above copyright notice and this permission notice shall be included in
|
14 | 6b837bc4 | Jes Sorensen | * all copies or substantial portions of the Software.
|
15 | 6b837bc4 | Jes Sorensen | *
|
16 | 6b837bc4 | Jes Sorensen | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 6b837bc4 | Jes Sorensen | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 6b837bc4 | Jes Sorensen | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 6b837bc4 | Jes Sorensen | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 6b837bc4 | Jes Sorensen | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 6b837bc4 | Jes Sorensen | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 6b837bc4 | Jes Sorensen | * THE SOFTWARE.
|
23 | 6b837bc4 | Jes Sorensen | */
|
24 | 6b837bc4 | Jes Sorensen | |
25 | 6b837bc4 | Jes Sorensen | #include "qemu-common.h" |
26 | 1de7afc9 | Paolo Bonzini | #include "qemu/osdep.h" |
27 | 6b837bc4 | Jes Sorensen | #include <stdio.h> |
28 | 6b837bc4 | Jes Sorensen | |
29 | 6b837bc4 | Jes Sorensen | struct progress_state {
|
30 | 6b837bc4 | Jes Sorensen | float current;
|
31 | 6b837bc4 | Jes Sorensen | float last_print;
|
32 | 6b837bc4 | Jes Sorensen | float min_skip;
|
33 | a55c73ba | Jes Sorensen | void (*print)(void); |
34 | a55c73ba | Jes Sorensen | void (*end)(void); |
35 | 6b837bc4 | Jes Sorensen | }; |
36 | 6b837bc4 | Jes Sorensen | |
37 | 6b837bc4 | Jes Sorensen | static struct progress_state state; |
38 | 2ab3cb8c | Jes Sorensen | static volatile sig_atomic_t print_pending; |
39 | 6b837bc4 | Jes Sorensen | |
40 | 6b837bc4 | Jes Sorensen | /*
|
41 | 6b837bc4 | Jes Sorensen | * Simple progress print function.
|
42 | 6b837bc4 | Jes Sorensen | * @percent relative percent of current operation
|
43 | 6b837bc4 | Jes Sorensen | * @max percent of total operation
|
44 | 6b837bc4 | Jes Sorensen | */
|
45 | 6b837bc4 | Jes Sorensen | static void progress_simple_print(void) |
46 | 6b837bc4 | Jes Sorensen | { |
47 | df6e008a | Jes Sorensen | printf(" (%3.2f/100%%)\r", state.current);
|
48 | df6e008a | Jes Sorensen | fflush(stdout); |
49 | 6b837bc4 | Jes Sorensen | } |
50 | 6b837bc4 | Jes Sorensen | |
51 | 6b837bc4 | Jes Sorensen | static void progress_simple_end(void) |
52 | 6b837bc4 | Jes Sorensen | { |
53 | a55c73ba | Jes Sorensen | printf("\n");
|
54 | a55c73ba | Jes Sorensen | } |
55 | a55c73ba | Jes Sorensen | |
56 | a55c73ba | Jes Sorensen | static void progress_simple_init(void) |
57 | a55c73ba | Jes Sorensen | { |
58 | a55c73ba | Jes Sorensen | state.print = progress_simple_print; |
59 | a55c73ba | Jes Sorensen | state.end = progress_simple_end; |
60 | a55c73ba | Jes Sorensen | } |
61 | a55c73ba | Jes Sorensen | |
62 | a55c73ba | Jes Sorensen | #ifdef CONFIG_POSIX
|
63 | a55c73ba | Jes Sorensen | static void sigusr_print(int signal) |
64 | a55c73ba | Jes Sorensen | { |
65 | 2ab3cb8c | Jes Sorensen | print_pending = 1;
|
66 | a55c73ba | Jes Sorensen | } |
67 | a55c73ba | Jes Sorensen | #endif
|
68 | a55c73ba | Jes Sorensen | |
69 | a55c73ba | Jes Sorensen | static void progress_dummy_print(void) |
70 | a55c73ba | Jes Sorensen | { |
71 | 2ab3cb8c | Jes Sorensen | if (print_pending) {
|
72 | 2ab3cb8c | Jes Sorensen | fprintf(stderr, " (%3.2f/100%%)\n", state.current);
|
73 | 2ab3cb8c | Jes Sorensen | print_pending = 0;
|
74 | 2ab3cb8c | Jes Sorensen | } |
75 | a55c73ba | Jes Sorensen | } |
76 | a55c73ba | Jes Sorensen | |
77 | a55c73ba | Jes Sorensen | static void progress_dummy_end(void) |
78 | a55c73ba | Jes Sorensen | { |
79 | a55c73ba | Jes Sorensen | } |
80 | a55c73ba | Jes Sorensen | |
81 | a55c73ba | Jes Sorensen | static void progress_dummy_init(void) |
82 | a55c73ba | Jes Sorensen | { |
83 | a55c73ba | Jes Sorensen | #ifdef CONFIG_POSIX
|
84 | a55c73ba | Jes Sorensen | struct sigaction action;
|
85 | 3c4b4e38 | Kevin Wolf | sigset_t set; |
86 | a55c73ba | Jes Sorensen | |
87 | a55c73ba | Jes Sorensen | memset(&action, 0, sizeof(action)); |
88 | a55c73ba | Jes Sorensen | sigfillset(&action.sa_mask); |
89 | a55c73ba | Jes Sorensen | action.sa_handler = sigusr_print; |
90 | a55c73ba | Jes Sorensen | action.sa_flags = 0;
|
91 | a55c73ba | Jes Sorensen | sigaction(SIGUSR1, &action, NULL);
|
92 | 3c4b4e38 | Kevin Wolf | |
93 | 3c4b4e38 | Kevin Wolf | /*
|
94 | 3c4b4e38 | Kevin Wolf | * SIGUSR1 is SIG_IPI and gets blocked in qemu_init_main_loop(). In the
|
95 | 3c4b4e38 | Kevin Wolf | * tools that use the progress report SIGUSR1 isn't used in this meaning
|
96 | 3c4b4e38 | Kevin Wolf | * and instead should print the progress, so reenable it.
|
97 | 3c4b4e38 | Kevin Wolf | */
|
98 | 3c4b4e38 | Kevin Wolf | sigemptyset(&set); |
99 | 3c4b4e38 | Kevin Wolf | sigaddset(&set, SIGUSR1); |
100 | 3c4b4e38 | Kevin Wolf | pthread_sigmask(SIG_UNBLOCK, &set, NULL);
|
101 | a55c73ba | Jes Sorensen | #endif
|
102 | a55c73ba | Jes Sorensen | |
103 | a55c73ba | Jes Sorensen | state.print = progress_dummy_print; |
104 | a55c73ba | Jes Sorensen | state.end = progress_dummy_end; |
105 | 6b837bc4 | Jes Sorensen | } |
106 | 6b837bc4 | Jes Sorensen | |
107 | 3bfe4dbf | Jes Sorensen | /*
|
108 | 3bfe4dbf | Jes Sorensen | * Initialize progress reporting.
|
109 | 3bfe4dbf | Jes Sorensen | * If @enabled is false, actual reporting is suppressed. The user can
|
110 | 3bfe4dbf | Jes Sorensen | * still trigger a report by sending a SIGUSR1.
|
111 | 3bfe4dbf | Jes Sorensen | * Reports are also suppressed unless we've had at least @min_skip
|
112 | 3bfe4dbf | Jes Sorensen | * percent progress since the last report.
|
113 | 3bfe4dbf | Jes Sorensen | */
|
114 | 6b837bc4 | Jes Sorensen | void qemu_progress_init(int enabled, float min_skip) |
115 | 6b837bc4 | Jes Sorensen | { |
116 | 6b837bc4 | Jes Sorensen | state.min_skip = min_skip; |
117 | a55c73ba | Jes Sorensen | if (enabled) {
|
118 | a55c73ba | Jes Sorensen | progress_simple_init(); |
119 | a55c73ba | Jes Sorensen | } else {
|
120 | a55c73ba | Jes Sorensen | progress_dummy_init(); |
121 | a55c73ba | Jes Sorensen | } |
122 | 6b837bc4 | Jes Sorensen | } |
123 | 6b837bc4 | Jes Sorensen | |
124 | 6b837bc4 | Jes Sorensen | void qemu_progress_end(void) |
125 | 6b837bc4 | Jes Sorensen | { |
126 | a55c73ba | Jes Sorensen | state.end(); |
127 | 6b837bc4 | Jes Sorensen | } |
128 | 6b837bc4 | Jes Sorensen | |
129 | 3bfe4dbf | Jes Sorensen | /*
|
130 | 3bfe4dbf | Jes Sorensen | * Report progress.
|
131 | 3bfe4dbf | Jes Sorensen | * @delta is how much progress we made.
|
132 | 3bfe4dbf | Jes Sorensen | * If @max is zero, @delta is an absolut value of the total job done.
|
133 | 3bfe4dbf | Jes Sorensen | * Else, @delta is a progress delta since the last call, as a fraction
|
134 | 3bfe4dbf | Jes Sorensen | * of @max. I.e. the delta is @delta * @max / 100. This allows
|
135 | 3bfe4dbf | Jes Sorensen | * relative accounting of functions which may be a different fraction of
|
136 | 3bfe4dbf | Jes Sorensen | * the full job, depending on the context they are called in. I.e.
|
137 | 3bfe4dbf | Jes Sorensen | * a function might be considered 40% of the full job if used from
|
138 | 3bfe4dbf | Jes Sorensen | * bdrv_img_create() but only 20% if called from img_convert().
|
139 | 3bfe4dbf | Jes Sorensen | */
|
140 | 3bfe4dbf | Jes Sorensen | void qemu_progress_print(float delta, int max) |
141 | 6b837bc4 | Jes Sorensen | { |
142 | 6b837bc4 | Jes Sorensen | float current;
|
143 | 6b837bc4 | Jes Sorensen | |
144 | 6b837bc4 | Jes Sorensen | if (max == 0) { |
145 | 3bfe4dbf | Jes Sorensen | current = delta; |
146 | 6b837bc4 | Jes Sorensen | } else {
|
147 | 3bfe4dbf | Jes Sorensen | current = state.current + delta / 100 * max;
|
148 | 6b837bc4 | Jes Sorensen | } |
149 | 6b837bc4 | Jes Sorensen | if (current > 100) { |
150 | 6b837bc4 | Jes Sorensen | current = 100;
|
151 | 6b837bc4 | Jes Sorensen | } |
152 | 6b837bc4 | Jes Sorensen | state.current = current; |
153 | 6b837bc4 | Jes Sorensen | |
154 | 6b837bc4 | Jes Sorensen | if (current > (state.last_print + state.min_skip) ||
|
155 | 6b837bc4 | Jes Sorensen | (current == 100) || (current == 0)) { |
156 | 6b837bc4 | Jes Sorensen | state.last_print = state.current; |
157 | a55c73ba | Jes Sorensen | state.print(); |
158 | 6b837bc4 | Jes Sorensen | } |
159 | 6b837bc4 | Jes Sorensen | } |