]> git.proxmox.com Git - ceph.git/blob - ceph/src/dpdk/examples/vm_power_manager/channel_monitor.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / dpdk / examples / vm_power_manager / channel_monitor.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <unistd.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdint.h>
38 #include <signal.h>
39 #include <errno.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/epoll.h>
43 #include <sys/queue.h>
44
45 #include <rte_log.h>
46 #include <rte_memory.h>
47 #include <rte_malloc.h>
48 #include <rte_atomic.h>
49
50
51 #include "channel_monitor.h"
52 #include "channel_commands.h"
53 #include "channel_manager.h"
54 #include "power_manager.h"
55
56 #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1
57
58 #define MAX_EVENTS 256
59
60
61 static volatile unsigned run_loop = 1;
62 static int global_event_fd;
63 static struct epoll_event *global_events_list;
64
65 void channel_monitor_exit(void)
66 {
67 run_loop = 0;
68 rte_free(global_events_list);
69 }
70
71 static int
72 process_request(struct channel_packet *pkt, struct channel_info *chan_info)
73 {
74 uint64_t core_mask;
75
76 if (chan_info == NULL)
77 return -1;
78
79 if (rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_CONNECTED,
80 CHANNEL_MGR_CHANNEL_PROCESSING) == 0)
81 return -1;
82
83 if (pkt->command == CPU_POWER) {
84 core_mask = get_pcpus_mask(chan_info, pkt->resource_id);
85 if (core_mask == 0) {
86 RTE_LOG(ERR, CHANNEL_MONITOR, "Error get physical CPU mask for "
87 "channel '%s' using vCPU(%u)\n", chan_info->channel_path,
88 (unsigned)pkt->unit);
89 return -1;
90 }
91 if (__builtin_popcountll(core_mask) == 1) {
92
93 unsigned core_num = __builtin_ffsll(core_mask) - 1;
94
95 switch (pkt->unit) {
96 case(CPU_POWER_SCALE_MIN):
97 power_manager_scale_core_min(core_num);
98 break;
99 case(CPU_POWER_SCALE_MAX):
100 power_manager_scale_core_max(core_num);
101 break;
102 case(CPU_POWER_SCALE_DOWN):
103 power_manager_scale_core_down(core_num);
104 break;
105 case(CPU_POWER_SCALE_UP):
106 power_manager_scale_core_up(core_num);
107 break;
108 default:
109 break;
110 }
111 } else {
112 switch (pkt->unit) {
113 case(CPU_POWER_SCALE_MIN):
114 power_manager_scale_mask_min(core_mask);
115 break;
116 case(CPU_POWER_SCALE_MAX):
117 power_manager_scale_mask_max(core_mask);
118 break;
119 case(CPU_POWER_SCALE_DOWN):
120 power_manager_scale_mask_down(core_mask);
121 break;
122 case(CPU_POWER_SCALE_UP):
123 power_manager_scale_mask_up(core_mask);
124 break;
125 default:
126 break;
127 }
128
129 }
130 }
131 /* Return is not checked as channel status may have been set to DISABLED
132 * from management thread
133 */
134 rte_atomic32_cmpset(&(chan_info->status), CHANNEL_MGR_CHANNEL_PROCESSING,
135 CHANNEL_MGR_CHANNEL_CONNECTED);
136 return 0;
137
138 }
139
140 int
141 add_channel_to_monitor(struct channel_info **chan_info)
142 {
143 struct channel_info *info = *chan_info;
144 struct epoll_event event;
145
146 event.events = EPOLLIN;
147 event.data.ptr = info;
148 if (epoll_ctl(global_event_fd, EPOLL_CTL_ADD, info->fd, &event) < 0) {
149 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to add channel '%s' "
150 "to epoll\n", info->channel_path);
151 return -1;
152 }
153 return 0;
154 }
155
156 int
157 remove_channel_from_monitor(struct channel_info *chan_info)
158 {
159 if (epoll_ctl(global_event_fd, EPOLL_CTL_DEL, chan_info->fd, NULL) < 0) {
160 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to remove channel '%s' "
161 "from epoll\n", chan_info->channel_path);
162 return -1;
163 }
164 return 0;
165 }
166
167 int
168 channel_monitor_init(void)
169 {
170 global_event_fd = epoll_create1(0);
171 if (global_event_fd == 0) {
172 RTE_LOG(ERR, CHANNEL_MONITOR, "Error creating epoll context with "
173 "error %s\n", strerror(errno));
174 return -1;
175 }
176 global_events_list = rte_malloc("epoll_events", sizeof(*global_events_list)
177 * MAX_EVENTS, RTE_CACHE_LINE_SIZE);
178 if (global_events_list == NULL) {
179 RTE_LOG(ERR, CHANNEL_MONITOR, "Unable to rte_malloc for "
180 "epoll events\n");
181 return -1;
182 }
183 return 0;
184 }
185
186 void
187 run_channel_monitor(void)
188 {
189 while (run_loop) {
190 int n_events, i;
191
192 n_events = epoll_wait(global_event_fd, global_events_list,
193 MAX_EVENTS, 1);
194 if (!run_loop)
195 break;
196 for (i = 0; i < n_events; i++) {
197 struct channel_info *chan_info = (struct channel_info *)
198 global_events_list[i].data.ptr;
199 if ((global_events_list[i].events & EPOLLERR) ||
200 (global_events_list[i].events & EPOLLHUP)) {
201 RTE_LOG(DEBUG, CHANNEL_MONITOR, "Remote closed connection for "
202 "channel '%s'\n", chan_info->channel_path);
203 remove_channel(&chan_info);
204 continue;
205 }
206 if (global_events_list[i].events & EPOLLIN) {
207
208 int n_bytes, err = 0;
209 struct channel_packet pkt;
210 void *buffer = &pkt;
211 int buffer_len = sizeof(pkt);
212
213 while (buffer_len > 0) {
214 n_bytes = read(chan_info->fd, buffer, buffer_len);
215 if (n_bytes == buffer_len)
216 break;
217 if (n_bytes == -1) {
218 err = errno;
219 RTE_LOG(DEBUG, CHANNEL_MONITOR, "Received error on "
220 "channel '%s' read: %s\n",
221 chan_info->channel_path, strerror(err));
222 remove_channel(&chan_info);
223 break;
224 }
225 buffer = (char *)buffer + n_bytes;
226 buffer_len -= n_bytes;
227 }
228 if (!err)
229 process_request(&pkt, chan_info);
230 }
231 }
232 }
233 }