1 : /*
2 : * This file is part of MIN Test Framework. Copyright © 2008 Nokia Corporation
3 : * and/or its subsidiary(-ies).
4 : * Contact: Robert Galkowski
5 : * Contact e-mail: DG.MIN-Support@nokia.com
6 : *
7 : * This program is free software: you can redistribute it and/or modify it
8 : * under the terms of the GNU General Public License as published by the Free
9 : * Software Foundation, version 2 of the License.
10 : *
11 : * This program is distributed in the hope that it will be useful, but WITHOUT
12 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 : * more details. You should have received a copy of the GNU General Public
15 : * License along with this program. If not, see
16 : * <http://www.gnu.org/licenses/>.
17 : */
18 :
19 :
20 : /**
21 : * @file min_test_interference.c
22 : * @version 0.1
23 : * @brief This file contains implementation of Event System for
24 : * Test Process
25 : */
26 :
27 : /* ------------------------------------------------------------------------- */
28 : /* INCLUDE FILES */
29 : #include <signal.h>
30 : #include <errno.h>
31 : #include <tmc.h>
32 : #include <tmc_ipc.h>
33 : #include <min_logger.h>
34 : #include <min_test_interference.h>
35 : #include <pthread.h>
36 :
37 : /* ------------------------------------------------------------------------- */
38 : /* EXTERNAL DATA STRUCTURES */
39 : /* None */
40 :
41 : /* ------------------------------------------------------------------------- */
42 : /* EXTERNAL FUNCTION PROTOTYPES */
43 : /* None */
44 :
45 : /* ------------------------------------------------------------------------- */
46 : /* CONSTANTS */
47 : /* None */
48 :
49 : /* ------------------------------------------------------------------------- */
50 : /* MACROS */
51 :
52 : /* ------------------------------------------------------------------------- */
53 : /* LOCAL CONSTANTS AND MACROS */
54 : /* None */
55 :
56 : /* ------------------------------------------------------------------------- */
57 : /* MODULE DATA STRUCTURES */
58 :
59 :
60 : /* ------------------------------------------------------------------------- */
61 : /* LOCAL FUNCTION PROTOTYPES */
62 : /**sleeping for number of miliseconds given in argument
63 : */
64 : inline void msleep(int period)
65 294 : {
66 294 : sleep ((int)(period/1000));
67 294 : usleep (1000*(period%1000));
68 294 : }
69 :
70 :
71 : LOCAL int check_package_avail ()
72 9 : {
73 9 : int retval = 0;
74 9 : if ((access ("/usr/bin/cpuload", X_OK) != 0) ||
75 : (access ("/usr/bin/memload", X_OK) != 0) ||
76 : (access ("/usr/bin/ioload", X_OK) != 0))
77 0 : retval = -1;
78 :
79 9 : return retval;
80 : }
81 :
82 : LOCAL void *ti_cpu_controller (void *Arg)
83 3 : {
84 3 : testInterference *Ainterference = (testInterference *) Arg;
85 3 : MIN_TRACE ("-->");
86 3 : if (Ainterference->idle_time_ != 0) {
87 3 : MIN_DEBUG ("enter IDLE/BUSY cycle (%d/%d)",
88 : Ainterference->idle_time_,
89 : Ainterference->busy_time_);
90 58 : while (Ainterference->terminated_ == ESFalse) {
91 52 : switch (Ainterference->instance_paused_) {
92 : case (ERunning):
93 52 : msleep(Ainterference->busy_time_);
94 52 : kill (Ainterference->instance_pid_, SIGSTOP);
95 52 : msleep(Ainterference->idle_time_);
96 52 : kill (Ainterference->instance_pid_, SIGCONT);
97 52 : break;
98 : case (EPausePending):
99 0 : kill (Ainterference->instance_pid_, SIGSTOP);
100 0 : Ainterference->instance_paused_ = EPaused;
101 0 : break;
102 : case (EResumePending):
103 0 : kill (Ainterference->instance_pid_, SIGCONT);
104 0 : break;
105 : case (EPaused):
106 0 : usleep (1000);
107 : }
108 : }
109 : } else {
110 0 : while (Ainterference->terminated_ == ESFalse) {
111 : /*no need to do anything */
112 0 : usleep (10000);
113 : }
114 : }
115 3 : kill (Ainterference->instance_pid_, SIGKILL);
116 3 : DELETE (Ainterference);
117 3 : MIN_TRACE ("<--");
118 3 : return NULL; //only to satisfy compiler
119 : }
120 :
121 : /* ------------------------------------------------------------------------- */
122 :
123 : LOCAL void *ti_mem_controller (void *Arg)
124 3 : {
125 3 : FILE *output = NULL;
126 3 : int num = 0;
127 : pid_t inst_pid;
128 3 : char **exec_args = NEW2 (char *, 3);
129 3 : testInterference *Ainterference = (testInterference *) Arg;
130 3 : MIN_TRACE ("-->");
131 3 : if (Ainterference->idle_time_ != 0) {
132 3 : MIN_DEBUG ("enter IDLE/BUSY cycle (%d/%d)",
133 : Ainterference->idle_time_,
134 : Ainterference->busy_time_);
135 49 : while (Ainterference->terminated_ == ESFalse) {
136 43 : switch (Ainterference->instance_paused_) {
137 : case (ERunning):
138 43 : MIN_DEBUG ("ERunning");
139 43 : inst_pid = fork ();
140 86 : if (inst_pid == 0) {
141 43 : output = fopen ("/dev/null", "w+");
142 43 : num = fileno (output);
143 43 : dup2 (num, STDOUT_FILENO);
144 43 : dup2 (num, STDERR_FILENO);
145 43 : exec_args[0] = "/usr/bin/memload";
146 43 : exec_args[1] = NEW2 (char, 3);
147 43 : sprintf (exec_args[1], "%d",
148 : Ainterference->memory_load_);
149 43 : exec_args[2] = NULL;
150 43 : execv (exec_args[0], exec_args);
151 : } else {
152 43 : Ainterference->instance_pid_ =
153 : inst_pid;
154 43 : msleep(Ainterference->busy_time_);
155 43 : kill (Ainterference->instance_pid_,
156 : SIGKILL);
157 43 : waitpid(Ainterference->instance_pid_,NULL,0);
158 43 : msleep(Ainterference->idle_time_);
159 : }
160 43 : break;
161 : case (EPausePending):
162 0 : MIN_DEBUG ("EPausePending");
163 0 : Ainterference->instance_paused_ = EPaused;
164 0 : break;
165 : case (EPaused):
166 0 : MIN_DEBUG ("EPaused");
167 0 : msleep(Ainterference->idle_time_);
168 0 : break;
169 : case (EResumePending):
170 0 : MIN_DEBUG ("EResumePending");
171 0 : Ainterference->instance_paused_ = ERunning;
172 0 : break;
173 : default:
174 0 : MIN_WARN ("fault in interference status");
175 : }
176 : }
177 : } else {
178 0 : inst_pid = fork ();
179 0 : if (inst_pid == 0) {
180 0 : MIN_DEBUG ("starting interference tool");
181 0 : output = fopen ("/dev/null", "w+");
182 0 : num = fileno (output);
183 0 : dup2 (num, STDOUT_FILENO);
184 0 : dup2 (num, STDERR_FILENO);
185 0 : exec_args[0] = "/usr/bin/memload";
186 0 : exec_args[1] = NEW2 (char, 3);
187 0 : sprintf (exec_args[1], "%d",
188 : Ainterference->memory_load_);
189 0 : exec_args[2] = NULL;
190 0 : execv (exec_args[0], exec_args);
191 : } else {
192 0 : Ainterference->instance_pid_ = inst_pid;
193 : }
194 0 : while (Ainterference->terminated_ == ESFalse) {
195 0 : usleep (1000);
196 : }
197 0 : kill (Ainterference->instance_pid_, SIGKILL);
198 : }
199 3 : DELETE (Ainterference);
200 3 : MIN_TRACE ("<--");
201 3 : return NULL; //only to satisfy compiler
202 : }
203 :
204 : /* ------------------------------------------------------------------------- */
205 :
206 : LOCAL void *ti_io_controller (void *Arg)
207 3 : {
208 3 : testInterference *Ainterference = (testInterference *) Arg;
209 3 : MIN_TRACE ("-->");
210 3 : if (Ainterference->idle_time_ != 0) {
211 3 : MIN_DEBUG ("enter IDLE/BUSY cycle (%d/%d)",
212 : Ainterference->idle_time_,
213 : Ainterference->busy_time_);
214 58 : while (Ainterference->terminated_ == ESFalse) {
215 52 : switch (Ainterference->instance_paused_) {
216 : case (ERunning):
217 52 : msleep(Ainterference->busy_time_);
218 52 : kill (Ainterference->instance_pid_, SIGSTOP);
219 52 : msleep(Ainterference->idle_time_);
220 52 : kill (Ainterference->instance_pid_, SIGCONT);
221 52 : break;
222 : case (EPausePending):
223 0 : kill (Ainterference->instance_pid_, SIGSTOP);
224 0 : Ainterference->instance_paused_ = EPaused;
225 0 : break;
226 : case (EResumePending):
227 0 : Ainterference->instance_paused_ = ERunning;
228 0 : kill (Ainterference->instance_pid_, SIGCONT);
229 0 : break;
230 : case (EPaused):
231 0 : usleep (1000);
232 : default:
233 0 : MIN_WARN ("fault in interference status");
234 : }
235 : }
236 : } else {
237 0 : while (Ainterference->terminated_ == ESFalse) {
238 : /*no need to do anything */
239 0 : usleep (10000);
240 : }
241 : }
242 3 : kill (Ainterference->instance_pid_, SIGKILL);
243 3 : DELETE (Ainterference);
244 3 : MIN_TRACE ("<--");
245 3 : return NULL; //only to satisfy compiler
246 : }
247 :
248 : /* ------------------------------------------------------------------------- */
249 :
250 : /* ================= OTHER EXPORTED FUNCTIONS ============================== */
251 : /* None */
252 : testInterference *ti_start_interference_timed (TInterferenceType aType,
253 : int aIdleTime,
254 : int aBusyTime, int aLoadValue)
255 9 : {
256 9 : testInterference *interf_controller = INITPTR;
257 9 : pid_t ins_pid = 0;
258 9 : FILE *output = NULL;
259 9 : int num = 0, ret;
260 9 : char **exec_args = NULL;
261 : pthread_t watcher;
262 9 : void *(*controller) (void *) = NULL;
263 9 : MIN_TRACE ("-->");
264 9 : interf_controller = NEW (testInterference);
265 9 : interf_controller->type_ = aType;
266 9 : interf_controller->idle_time_ = aIdleTime;
267 9 : interf_controller->busy_time_ = aBusyTime;
268 9 : if (check_package_avail () != 0) {
269 0 : DELETE (interf_controller);
270 0 : MIN_INFO
271 : ("Could not find interference tools. Check if sp-stress is available");
272 0 : return NULL;
273 : }
274 9 : switch (aType) {
275 : case (ECpuLoad):
276 3 : interf_controller->cpu_load_ = aLoadValue;
277 3 : interf_controller->memory_load_ = 0;
278 3 : interf_controller->io_fname_ = NULL;
279 3 : interf_controller->instance_paused_ = ESFalse;
280 3 : break;
281 : case (EMemLoad):
282 3 : interf_controller->cpu_load_ = 0;
283 3 : interf_controller->memory_load_ = aLoadValue;
284 3 : interf_controller->io_fname_ = NULL;
285 3 : interf_controller->instance_paused_ = ESFalse;
286 3 : break;
287 : case (EIOLoad):
288 3 : interf_controller->cpu_load_ = 0;
289 3 : interf_controller->memory_load_ = 0;
290 3 : interf_controller->io_fname_ = "/tmp/intworkf";
291 3 : interf_controller->instance_paused_ = ESFalse;
292 : break;
293 : }
294 : /*now fork disturbance process and controller proces if necessary */
295 9 : ins_pid = fork ();
296 :
297 18 : if (ins_pid != 0) {
298 9 : interf_controller->instance_pid_ = ins_pid;
299 : /*leave some time for sp-stress tool to start */
300 9 : sleep (3);
301 : /*now start the thread with controller/timer */
302 9 : switch (aType) {
303 : case (ECpuLoad):
304 3 : controller = ti_cpu_controller;
305 3 : break;
306 : case (EMemLoad):
307 3 : controller = ti_mem_controller;
308 3 : break;
309 : case (EIOLoad):
310 3 : controller = ti_io_controller;
311 : }
312 9 : interf_controller->terminated_ = ESFalse;
313 9 : interf_controller->instance_paused_ = ERunning;
314 9 : pthread_create (&watcher, NULL, controller,
315 : (void *)interf_controller);
316 9 : interf_controller->controller_handle_ = watcher;
317 : } else {
318 : /*change this process into proper
319 : sp-stress tool now. */
320 : /*first, redirect output to /dev/null , to
321 : prevent messing up of console ui. */
322 9 : output = fopen ("/dev/null", "w+");
323 9 : num = fileno (output);
324 9 : dup2 (num, STDOUT_FILENO);
325 9 : dup2 (num, STDERR_FILENO);
326 9 : exec_args = NEW2 (char *, 3);
327 9 : switch (interf_controller->type_) {
328 : case (ECpuLoad):
329 3 : exec_args[0] = "/usr/bin/cpuload";
330 3 : exec_args[1] = NEW2 (char, 3);
331 3 : sprintf (exec_args[1], "%d",
332 : interf_controller->cpu_load_);
333 3 : exec_args[2] = NULL;
334 3 : execv (exec_args[0], exec_args);
335 0 : break;
336 : case (EMemLoad):
337 : /*memload is treated differently, since pausing it
338 : doesn't stop the memory from being taken */
339 3 : exit (0);
340 : case (EIOLoad):
341 3 : ret = system
342 : ("dd if=/dev/zero of=/tmp/workfile count=128 bs=128");
343 3 : exec_args[0] = "/usr/bin/ioload";
344 3 : exec_args[1] = "/tmp/workfile";
345 3 : exec_args[2] = NULL;
346 3 : execv (exec_args[0], exec_args);
347 : break;
348 : }
349 : }
350 9 : MIN_TRACE ("<--");
351 :
352 :
353 9 : return interf_controller;
354 : }
355 :
356 : /* ------------------------------------------------------------------------- */
357 : testInterference *ti_start_interference (TInterferenceType aType,
358 : int aLoadValue)
359 0 : {
360 0 : return ti_start_interference_timed (aType, 0, 0, aLoadValue);
361 : }
362 :
363 : /* ------------------------------------------------------------------------- */
364 : void ti_stop_interference (testInterference * aInterference)
365 9 : {
366 9 : MIN_TRACE ("-->");
367 9 : aInterference->terminated_ = ESTrue;
368 9 : pthread_join (aInterference->controller_handle_, NULL);
369 9 : MIN_TRACE ("<--");
370 9 : }
371 :
372 : /* ------------------------------------------------------------------------- */
373 : void ti_pause_interference (testInterference * aInterference)
374 0 : {
375 0 : aInterference->instance_paused_ = EPausePending;
376 0 : }
377 :
378 : /* ------------------------------------------------------------------------- */
379 : void ti_resume_interference (testInterference * aInterference)
380 0 : {
381 0 : aInterference->instance_paused_ = EResumePending;
382 0 : }
383 :
384 : /* ================= TESTS FOR LOCAL FUNCTIONS ============================= */
385 :
386 : /* End of file */
|