Home | History | Annotate | Download | only in sdcard
      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 
     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.
     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 //
    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 
    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.
    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 
    235 int kernelVersion(char *str, size_t size)
    236 {
    237     return readStringFromFile(kKernelVersion, str, size);
    238 }
    239 
    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 
    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 
    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 
    285 int schedFeatures(char *str, size_t size)
    286 {
    287     return readStringFromFile(kSchedFeatures, str, size);
    288 }
    289 
    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 
    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 
    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 
    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 
    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 
    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.
    390 void syncAndDropCaches(int code)
    391 {
    392     sync();
    393     sync();
    394     writeIntToFile(kDropCaches, code);
    395     sleep(kCachePurgeSleepDuration);
    396 }
    397 
    398 
    399 void fsyncAndDropCaches(int fd, int code)
    400 {
    401     fsync(fd);
    402     fsync(fd);
    403     writeIntToFile(kDropCaches, code);
    404     sleep(kCachePurgeSleepDuration);
    405 }
    406 
    407 
    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
    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 
    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