Home | History | Annotate | Download | only in util
      1 /*
      2  * os-posix-lib.c
      3  *
      4  * Copyright (c) 2003-2008 Fabrice Bellard
      5  * Copyright (c) 2010 Red Hat, Inc.
      6  *
      7  * QEMU library functions on POSIX which are shared between QEMU and
      8  * the QEMU tools.
      9  *
     10  * Permission is hereby granted, free of charge, to any person obtaining a copy
     11  * of this software and associated documentation files (the "Software"), to deal
     12  * in the Software without restriction, including without limitation the rights
     13  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     14  * copies of the Software, and to permit persons to whom the Software is
     15  * furnished to do so, subject to the following conditions:
     16  *
     17  * The above copyright notice and this permission notice shall be included in
     18  * all copies or substantial portions of the Software.
     19  *
     20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     25  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     26  * THE SOFTWARE.
     27  */
     28 
     29 /* The following block of code temporarily renames the daemon() function so the
     30    compiler does not see the warning associated with it in stdlib.h on OSX */
     31 #ifdef __APPLE__
     32 #define daemon qemu_fake_daemon_function
     33 #include <stdlib.h>
     34 #undef daemon
     35 extern int daemon(int, int);
     36 #endif
     37 
     38 #if defined(__linux__) && (defined(__x86_64__) || defined(__arm__))
     39    /* Use 2 MiB alignment so transparent hugepages can be used by KVM.
     40       Valgrind does not support alignments larger than 1 MiB,
     41       therefore we need special code which handles running on Valgrind. */
     42 #  define QEMU_VMALLOC_ALIGN (512 * 4096)
     43 #elif defined(__linux__) && defined(__s390x__)
     44    /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */
     45 #  define QEMU_VMALLOC_ALIGN (256 * 4096)
     46 #else
     47 #  define QEMU_VMALLOC_ALIGN getpagesize()
     48 #endif
     49 
     50 #include "config-host.h"
     51 #ifndef CONFIG_ANDROID
     52 #include <glib/gprintf.h>
     53 #endif
     54 
     55 #include "config-host.h"
     56 #include "sysemu/sysemu.h"
     57 #include "trace.h"
     58 #include "qemu/sockets.h"
     59 #include <sys/mman.h>
     60 
     61 #ifdef CONFIG_LINUX
     62 #include <sys/syscall.h>
     63 #endif
     64 
     65 int qemu_get_thread_id(void)
     66 {
     67 #if defined(__linux__)
     68     return syscall(SYS_gettid);
     69 #else
     70     return getpid();
     71 #endif
     72 }
     73 
     74 int qemu_daemon(int nochdir, int noclose)
     75 {
     76     return daemon(nochdir, noclose);
     77 }
     78 
     79 void *qemu_oom_check(void *ptr)
     80 {
     81     if (ptr == NULL) {
     82         fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
     83         abort();
     84     }
     85     return ptr;
     86 }
     87 
     88 void *qemu_memalign(size_t alignment, size_t size)
     89 {
     90     void *ptr;
     91 #if defined(_POSIX_C_SOURCE) && !defined(__sun__)
     92     int ret;
     93     ret = posix_memalign(&ptr, alignment, size);
     94     if (ret != 0) {
     95         fprintf(stderr, "Failed to allocate %zu B: %s\n",
     96                 size, strerror(ret));
     97         abort();
     98     }
     99 #elif defined(CONFIG_BSD)
    100     ptr = qemu_oom_check(valloc(size));
    101 #else
    102     ptr = qemu_oom_check(memalign(alignment, size));
    103 #endif
    104     //trace_qemu_memalign(alignment, size, ptr);
    105     return ptr;
    106 }
    107 
    108 /* alloc shared memory pages */
    109 void *qemu_vmalloc(size_t size)
    110 {
    111     return qemu_memalign(getpagesize(), size);
    112 }
    113 
    114 /* alloc shared memory pages */
    115 void *qemu_anon_ram_alloc(size_t size)
    116 {
    117     size_t align = QEMU_VMALLOC_ALIGN;
    118     size_t total = size + align - getpagesize();
    119     void *ptr = mmap(0, total, PROT_READ | PROT_WRITE,
    120                      MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    121     size_t offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr;
    122 
    123     if (ptr == MAP_FAILED) {
    124         return NULL;
    125     }
    126 
    127     ptr += offset;
    128     total -= offset;
    129 
    130     if (offset > 0) {
    131         munmap(ptr - offset, offset);
    132     }
    133     if (total > size) {
    134         munmap(ptr + size, total - size);
    135     }
    136 
    137     //trace_qemu_anon_ram_alloc(size, ptr);
    138     return ptr;
    139 }
    140 
    141 void qemu_vfree(void *ptr)
    142 {
    143     //trace_qemu_vfree(ptr);
    144     free(ptr);
    145 }
    146 
    147 void qemu_anon_ram_free(void *ptr, size_t size)
    148 {
    149     //trace_qemu_anon_ram_free(ptr, size);
    150     if (ptr) {
    151         munmap(ptr, size);
    152     }
    153 }
    154 
    155 void qemu_set_block(int fd)
    156 {
    157     int f;
    158     f = fcntl(fd, F_GETFL);
    159     fcntl(fd, F_SETFL, f & ~O_NONBLOCK);
    160 }
    161 
    162 void qemu_set_nonblock(int fd)
    163 {
    164     int f;
    165     f = fcntl(fd, F_GETFL);
    166     fcntl(fd, F_SETFL, f | O_NONBLOCK);
    167 }
    168 
    169 int socket_set_fast_reuse(int fd)
    170 {
    171 #ifdef CONFIG_ANDROID
    172     return socket_set_xreuseaddr(fd);
    173 #else
    174     int val = 1, ret;
    175 
    176     ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
    177                      (const char *)&val, sizeof(val));
    178 
    179     assert(ret == 0);
    180 
    181     return ret;
    182 #endif
    183 }
    184 
    185 void qemu_set_cloexec(int fd)
    186 {
    187     int f;
    188     f = fcntl(fd, F_GETFD);
    189     fcntl(fd, F_SETFD, f | FD_CLOEXEC);
    190 }
    191 
    192 /*
    193  * Creates a pipe with FD_CLOEXEC set on both file descriptors
    194  */
    195 int qemu_pipe(int pipefd[2])
    196 {
    197     int ret;
    198 
    199 #ifdef CONFIG_PIPE2
    200     ret = pipe2(pipefd, O_CLOEXEC);
    201     if (ret != -1 || errno != ENOSYS) {
    202         return ret;
    203     }
    204 #endif
    205     ret = pipe(pipefd);
    206     if (ret == 0) {
    207         qemu_set_cloexec(pipefd[0]);
    208         qemu_set_cloexec(pipefd[1]);
    209     }
    210 
    211     return ret;
    212 }
    213 
    214 int qemu_utimens(const char *path, const struct timespec *times)
    215 {
    216     struct timeval tv[2], tv_now;
    217     struct stat st;
    218     int i;
    219 #ifdef CONFIG_UTIMENSAT
    220     int ret;
    221 
    222     ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
    223     if (ret != -1 || errno != ENOSYS) {
    224         return ret;
    225     }
    226 #endif
    227     /* Fallback: use utimes() instead of utimensat() */
    228 
    229     /* happy if special cases */
    230     if (times[0].tv_nsec == UTIME_OMIT && times[1].tv_nsec == UTIME_OMIT) {
    231         return 0;
    232     }
    233     if (times[0].tv_nsec == UTIME_NOW && times[1].tv_nsec == UTIME_NOW) {
    234         return utimes(path, NULL);
    235     }
    236 
    237     /* prepare for hard cases */
    238     if (times[0].tv_nsec == UTIME_NOW || times[1].tv_nsec == UTIME_NOW) {
    239         gettimeofday(&tv_now, NULL);
    240     }
    241     if (times[0].tv_nsec == UTIME_OMIT || times[1].tv_nsec == UTIME_OMIT) {
    242         stat(path, &st);
    243     }
    244 
    245     for (i = 0; i < 2; i++) {
    246         if (times[i].tv_nsec == UTIME_NOW) {
    247             tv[i].tv_sec = tv_now.tv_sec;
    248             tv[i].tv_usec = tv_now.tv_usec;
    249         } else if (times[i].tv_nsec == UTIME_OMIT) {
    250             tv[i].tv_sec = (i == 0) ? st.st_atime : st.st_mtime;
    251             tv[i].tv_usec = 0;
    252         } else {
    253             tv[i].tv_sec = times[i].tv_sec;
    254             tv[i].tv_usec = times[i].tv_nsec / 1000;
    255         }
    256     }
    257 
    258     return utimes(path, &tv[0]);
    259 }
    260 
    261 char *
    262 qemu_get_local_state_pathname(const char *relative_pathname)
    263 {
    264 #ifdef CONFIG_ANDROID
    265     return NULL;
    266 #else
    267     return g_strdup_printf("%s/%s", CONFIG_QEMU_LOCALSTATEDIR,
    268                            relative_pathname);
    269 #endif
    270 }
    271