1 /*
2 * Copyright (C) 2009 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <dirent.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <limits.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 #include <sys/wait.h>
38 #include <unistd.h>
39 #include "sysutil.h"
40
41 namespace {
42 const int kError = -1;
43 // Max number of retries on EAGAIN and EINTR. Totally arbitrary.
44 const int kMaxAttempts = 8;
45
46 // How long to wait after a cache purge. A few seconds (arbitrary).
47 const int kCachePurgeSleepDuration = 2; // seconds
48
49 const bool kSilentIfMissing = false;
50
51 const char *kKernelVersion = "/proc/version";
52 const char *kScalingGovernorFormat = "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor";
53 const char *kDropCaches = "/proc/sys/vm/drop_caches";
54 const char *kSchedFeatures = "/sys/kernel/debug/sched_features";
55 const char *kNewFairSleepers = "NEW_FAIR_SLEEPERS";
56 const char *kNoNewFairSleepers = "NO_NEW_FAIR_SLEEPERS";
57 const char *kNormalizedSleepers = "NORMALIZED_SLEEPER"; // no 's' at the end
58 const char *kNoNormalizedSleepers = "NO_NORMALIZED_SLEEPER";
59
60 const char *kDebugfsWarningMsg = "Did you 'adb root; adb shell mount -t debugfs none /sys/kernel/debug' ?";
61
62 // TODO: Surely these file utility functions must exist already. A
63 // quick grep did not turn up anything. Look harder later.
64
printErrno(const char * msg,const char * filename)65 void printErrno(const char *msg, const char *filename)
66 {
67 fprintf(stderr, "# %s %s %d %s\n", msg, filename, errno, strerror(errno));
68 }
69
70 // Read a C-string from a file. If the buffer is too short, an error
71 // message will be printed on stderr.
72 // @param filename Of the file to read.
73 // @param start Buffer where the data should be written to.
74 // @param size The size of the buffer pointed by str. Must be >= 1.
75 // @return The number of characters read (not including the trailing'\0' used
76 // to end the string) or -1 if there was an error.
readStringFromFile(const char * filename,char * const start,size_t size,bool must_exist=true)77 int readStringFromFile(const char *filename, char *const start, size_t size, bool must_exist=true)
78 {
79 if (NULL == start || size == 0)
80 {
81 return 0;
82 }
83 char *end = start;
84 int fd = open(filename, O_RDONLY);
85
86 if (fd < 0)
87 {
88 if (ENOENT != errno || must_exist)
89 {
90 printErrno("Failed to open", filename);
91 }
92 return kError;
93 }
94
95 bool eof = false;
96 bool error = false;
97 int attempts = 0;
98
99 --size; // reserve space for trailing '\0'
100
101 while (size > 0 && !error && !eof && attempts < kMaxAttempts)
102 {
103 ssize_t s;
104
105 s = read(fd, end, size);
106
107 if (s < 0)
108 {
109 error = EAGAIN != errno && EINTR != errno;
110 if (error)
111 {
112 printErrno("Failed to read", filename);
113 }
114 }
115 else if (0 == s)
116 {
117 eof = true;
118 }
119 else
120 {
121 end += s;
122 size -= s;
123 }
124 ++attempts;
125 }
126
127 close(fd);
128
129 if (error)
130 {
131 return kError;
132 }
133 else
134 {
135 *end = '\0';
136 if (!eof)
137 {
138 fprintf(stderr, "Buffer too small for %s\n", filename);
139 }
140 return end - start;
141 }
142 }
143
144 // Write a C string ('\0' terminated) to a file.
145 //
writeStringToFile(const char * filename,const char * start,bool must_exist=true)146 int writeStringToFile(const char *filename, const char *start, bool must_exist=true)
147 {
148 int fd = open(filename, O_WRONLY);
149
150
151 if (fd < 0)
152 {
153 if (ENOENT != errno || must_exist)
154 {
155 printErrno("Failed to open", filename);
156 }
157 return kError;
158 }
159
160 const size_t len = strlen(start);
161 size_t size = len;
162 bool error = false;
163 int attempts = 0;
164
165 while (size > 0 && !error && attempts < kMaxAttempts)
166 {
167 ssize_t s = write(fd, start, size);
168
169 if (s < 0)
170 {
171 error = EAGAIN != errno && EINTR != errno;
172 if (error)
173 {
174 printErrno("Failed to write", filename);
175 }
176 }
177 else
178 {
179 start += s;
180 size -= s;
181 }
182 ++attempts;
183 }
184 close(fd);
185
186 if (error)
187 {
188 return kError;
189 }
190 else
191 {
192 if (size > 0)
193 {
194 fprintf(stderr, "Partial write to %s (%d out of %d)\n",
195 filename, size, len);
196 }
197 return len - size;
198 }
199 }
200
writeIntToFile(const char * filename,long value)201 int writeIntToFile(const char *filename, long value)
202 {
203 char buffer[16] = {0,};
204 sprintf(buffer, "%ld", value);
205 return writeStringToFile(filename, buffer);
206 }
207
208 // @return a message describing the reason why the child exited. The
209 // message is in a shared buffer, not thread safe, erased by
210 // subsequent calls.
reasonChildExited(int status)211 const char *reasonChildExited(int status)
212 {
213 static char buffer[80];
214
215 if (WIFEXITED(status))
216 {
217 snprintf(buffer, sizeof(buffer), "ok (%d)", WEXITSTATUS(status));
218 }
219 else if (WIFSIGNALED(status))
220 {
221 snprintf(buffer, sizeof(buffer), "signaled (%d %s)", WTERMSIG(status), strsignal(WTERMSIG(status)));
222 }
223 else
224 {
225 snprintf(buffer, sizeof(buffer), "stopped?");
226 }
227 return buffer;
228 }
229
230
231 } // anonymous namespace
232
233 namespace android {
234
kernelVersion(char * str,size_t size)235 int kernelVersion(char *str, size_t size)
236 {
237 return readStringFromFile(kKernelVersion, str, size);
238 }
239
pidOutOfMemoryAdj()240 int pidOutOfMemoryAdj()
241 {
242 char filename[FILENAME_MAX];
243
244 snprintf(filename, sizeof(filename), "/proc/%d/oom_adj", getpid());
245
246 char value[16];
247 if (readStringFromFile(filename, value, sizeof(value)) == -1)
248 {
249 return -127;
250 }
251 else
252 {
253 return atoi(value);
254 }
255 }
256
setPidOutOfMemoryAdj(int level)257 void setPidOutOfMemoryAdj(int level)
258 {
259 char filename[FILENAME_MAX];
260
261 snprintf(filename, sizeof(filename), "/proc/%d/oom_adj", getpid());
262 writeIntToFile(filename, level);
263 }
264
disableCpuScaling()265 void disableCpuScaling()
266 {
267 for (int cpu = 0; cpu < 16; ++cpu) // 16 cores mobile phones, abestos pockets recommended.
268 {
269 char governor[FILENAME_MAX];
270 sprintf(governor, kScalingGovernorFormat, cpu);
271
272 if (writeStringToFile(governor, "performance", kSilentIfMissing) < 0)
273 {
274 if (cpu > 0 && errno == ENOENT)
275 {
276 break; // cpu1 or above not found, ok since we have cpu0.
277 }
278 fprintf(stderr, "Failed to write to scaling governor file for cpu %d: %d %s",
279 cpu, errno, strerror(errno));
280 break;
281 }
282 }
283 }
284
schedFeatures(char * str,size_t size)285 int schedFeatures(char *str, size_t size)
286 {
287 return readStringFromFile(kSchedFeatures, str, size);
288 }
289
newFairSleepers()290 bool newFairSleepers()
291 {
292 char value[256] = {0,};
293
294 if (readStringFromFile(kSchedFeatures, value, sizeof(value)) == -1)
295 {
296 printErrno(kDebugfsWarningMsg, kSchedFeatures);
297 return false;
298 }
299 return strstr(value, "NO_NEW_FAIR_SLEEPERS") == NULL;
300 }
301
setNewFairSleepers(bool on)302 void setNewFairSleepers(bool on)
303 {
304 int retcode;
305
306 if (on)
307 {
308 retcode = writeStringToFile(kSchedFeatures, kNewFairSleepers);
309 }
310 else
311 {
312 retcode = writeStringToFile(kSchedFeatures, kNoNewFairSleepers);
313 }
314 if (retcode < 0)
315 {
316 fprintf(stderr, "# %s\n", kDebugfsWarningMsg);
317 }
318 }
319
normalizedSleepers()320 bool normalizedSleepers()
321 {
322 char value[256] = {0,};
323
324 if (readStringFromFile(kSchedFeatures, value, sizeof(value)) == -1)
325 {
326 printErrno(kDebugfsWarningMsg, kSchedFeatures);
327 return false;
328 }
329 return strstr(value, "NO_NEW_FAIR_SLEEPERS") == NULL;
330 }
331
setNormalizedSleepers(bool on)332 void setNormalizedSleepers(bool on)
333 {
334 int retcode;
335
336 if (on)
337 {
338 retcode = writeStringToFile(kSchedFeatures, kNormalizedSleepers);
339 }
340 else
341 {
342 retcode = writeStringToFile(kSchedFeatures, kNoNormalizedSleepers);
343 }
344 if (retcode < 0)
345 {
346 fprintf(stderr, "# %s\n", kDebugfsWarningMsg);
347 }
348 }
349
forkOrExit()350 pid_t forkOrExit()
351 {
352 pid_t childpid = fork();
353
354 if (-1 == childpid)
355 {
356 fprintf(stderr, "Fork failed: %d %s", errno, strerror(errno));
357 exit(EXIT_FAILURE);
358 }
359 return childpid;
360 }
361
waitForChildrenOrExit(int num)362 void waitForChildrenOrExit(int num)
363 {
364 while (num > 0)
365 {
366 int status;
367 pid_t pid = wait(&status);
368 if (-1 == pid)
369 {
370 fprintf(stderr, "Wait failed\n");
371 }
372 else
373 {
374 if (!WIFEXITED(status))
375 {
376 fprintf(stderr, "Child pid %d did not exit cleanly %s\n",
377 pid, reasonChildExited(status));
378 exit(EXIT_FAILURE);
379 }
380 }
381 --num;
382 }
383 }
384
385 // Sync and cache cleaning functions. In the old hpux days I was told
386 // to always call *sync twice. The same advice seems to be still true
387 // today so *sync is called twice.
388 // Also we wait 'a little' to give a chance to background threads to
389 // purge their caches.
syncAndDropCaches(int code)390 void syncAndDropCaches(int code)
391 {
392 sync();
393 sync();
394 writeIntToFile(kDropCaches, code);
395 sleep(kCachePurgeSleepDuration);
396 }
397
398
fsyncAndDropCaches(int fd,int code)399 void fsyncAndDropCaches(int fd, int code)
400 {
401 fsync(fd);
402 fsync(fd);
403 writeIntToFile(kDropCaches, code);
404 sleep(kCachePurgeSleepDuration);
405 }
406
407
resetDirectory(const char * directory)408 void resetDirectory(const char *directory)
409 {
410 DIR *dir = opendir(directory);
411
412 if (NULL != dir)
413 {
414 struct dirent *entry;
415 char name_buffer[PATH_MAX];
416
417 while((entry = readdir(dir)))
418 {
419 if (0 == strcmp(entry->d_name, ".")
420 || 0 == strcmp(entry->d_name, "..")
421 || 0 == strcmp(entry->d_name, "lost+found"))
422 {
423 continue;
424 }
425 strcpy(name_buffer, directory);
426 strcat(name_buffer, "/");
427 strcat(name_buffer, entry->d_name);
428 unlink(name_buffer);
429 }
430 closedir(dir);
431 } else {
432 mkdir(directory, S_IRWXU);
433 }
434 }
435
436
437 // IPC
writePidAndWaitForReply(int writefd,int readfd)438 bool writePidAndWaitForReply(int writefd, int readfd)
439 {
440 if (writefd > readfd)
441 {
442 fprintf(stderr, "Called with args in wrong order!!\n");
443 return false;
444 }
445 pid_t pid = getpid();
446 char *start = reinterpret_cast<char *>(&pid);
447 size_t size = sizeof(pid);
448 bool error = false;
449 int attempts = 0;
450
451 while (size > 0 && !error && attempts < kMaxAttempts)
452 {
453 ssize_t s = write(writefd, start, size);
454
455 if (s < 0)
456 {
457 error = EAGAIN != errno && EINTR != errno;
458 if (error)
459 {
460 printErrno("Failed to write", "parent");
461 }
462 }
463 else
464 {
465 start += s;
466 size -= s;
467 }
468 ++attempts;
469 }
470
471 if (error || 0 != size)
472 {
473 return false;
474 }
475
476 bool eof = false;
477 char dummy;
478 size = sizeof(dummy);
479 error = false;
480 attempts = 0;
481
482 while (size > 0 && !error && !eof && attempts < kMaxAttempts)
483 {
484 ssize_t s;
485
486 s = read(readfd, &dummy, size);
487
488 if (s < 0)
489 {
490 error = EAGAIN != errno && EINTR != errno;
491 if (error)
492 {
493 printErrno("Failed to read", "parent");
494 }
495 }
496 else if (0 == s)
497 {
498 eof = true;
499 }
500 else
501 {
502 size -= s;
503 }
504 ++attempts;
505 }
506 if (error || 0 != size)
507 {
508 return false;
509 }
510 return true;
511 }
512
513
514
waitForChildrenAndSignal(int mProcessNb,int readfd,int writefd)515 bool waitForChildrenAndSignal(int mProcessNb, int readfd, int writefd)
516 {
517 if (readfd > writefd)
518 {
519 fprintf(stderr, "Called with args in wrong order!!\n");
520 return false;
521 }
522
523 bool error;
524 int attempts;
525 size_t size;
526
527 for (int p = 0; p < mProcessNb; ++p)
528 {
529 bool eof = false;
530 pid_t pid;
531 char *end = reinterpret_cast<char *>(&pid);
532
533 error = false;
534 attempts = 0;
535 size = sizeof(pid);
536
537 while (size > 0 && !error && !eof && attempts < kMaxAttempts)
538 {
539 ssize_t s;
540
541 s = read(readfd, end, size);
542
543 if (s < 0)
544 {
545 error = EAGAIN != errno && EINTR != errno;
546 if (error)
547 {
548 printErrno("Failed to read", "child");
549 }
550 }
551 else if (0 == s)
552 {
553 eof = true;
554 }
555 else
556 {
557 end += s;
558 size -= s;
559 }
560 ++attempts;
561 }
562
563 if (error || 0 != size)
564 {
565 return false;
566 }
567 }
568
569 for (int p = 0; p < mProcessNb; ++p)
570 {
571 char dummy;
572
573 error = false;
574 attempts = 0;
575 size = sizeof(dummy);
576
577 while (size > 0 && !error && attempts < kMaxAttempts)
578 {
579 ssize_t s = write(writefd, &dummy, size);
580
581 if (s < 0)
582 {
583 error = EAGAIN != errno && EINTR != errno;
584 if (error)
585 {
586 printErrno("Failed to write", "child");
587 }
588 }
589 else
590 {
591 size -= s;
592 }
593 ++attempts;
594 }
595
596 if (error || 0 != size)
597 {
598 return false;
599 }
600 }
601 return true;
602 }
603
604 } // namespace android
605