Statistics
| Branch: | Revision:

root / osdep.c @ d644f8be

History | View | Annotate | Download (8.7 kB)

1
/*
2
 * QEMU low level functions
3
 *
4
 * Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <errno.h>
29
#include <unistd.h>
30
#include <fcntl.h>
31
#ifdef HOST_SOLARIS
32
#include <sys/types.h>
33
#include <sys/statvfs.h>
34
#endif
35

    
36
/* FIXME: This file should be target independent. However it has kqemu
37
   hacks, so must be built for every target.  */
38

    
39
/* Needed early for HOST_BSD etc. */
40
#include "config-host.h"
41

    
42
#ifdef _WIN32
43
#include <windows.h>
44
#elif defined(HOST_BSD)
45
#include <stdlib.h>
46
#else
47
#include <malloc.h>
48
#endif
49

    
50
#include "qemu-common.h"
51
#include "sysemu.h"
52
#include "qemu_socket.h"
53

    
54
#if !defined(_POSIX_C_SOURCE) || defined(_WIN32)
55
static void *oom_check(void *ptr)
56
{
57
    if (ptr == NULL) {
58
        abort();
59
    }
60
    return ptr;
61
}
62
#endif
63

    
64
#if defined(_WIN32)
65
void *qemu_memalign(size_t alignment, size_t size)
66
{
67
    if (!size) {
68
        abort();
69
    }
70
    return oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
71
}
72

    
73
void *qemu_vmalloc(size_t size)
74
{
75
    /* FIXME: this is not exactly optimal solution since VirtualAlloc
76
       has 64Kb granularity, but at least it guarantees us that the
77
       memory is page aligned. */
78
    if (!size) {
79
        abort();
80
    }
81
    return oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
82
}
83

    
84
void qemu_vfree(void *ptr)
85
{
86
    VirtualFree(ptr, 0, MEM_RELEASE);
87
}
88

    
89
#else
90

    
91
#if defined(CONFIG_KQEMU)
92

    
93
#ifdef __OpenBSD__
94
#include <sys/param.h>
95
#include <sys/types.h>
96
#include <sys/mount.h>
97
#else
98
#ifndef __FreeBSD__
99
#include <sys/vfs.h>
100
#endif
101
#endif
102

    
103
#include <sys/mman.h>
104
#include <fcntl.h>
105

    
106
static void *kqemu_vmalloc(size_t size)
107
{
108
    static int phys_ram_fd = -1;
109
    static int phys_ram_size = 0;
110
    void *ptr;
111

    
112
/* no need (?) for a dummy file on OpenBSD/FreeBSD */
113
#if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
114
    int map_anon = MAP_ANON;
115
#else
116
    int map_anon = 0;
117
    const char *tmpdir;
118
    char phys_ram_file[1024];
119
#ifdef HOST_SOLARIS
120
    struct statvfs stfs;
121
#else
122
    struct statfs stfs;
123
#endif
124

    
125
    if (!size) {
126
        abort ();
127
    }
128

    
129
    if (phys_ram_fd < 0) {
130
        tmpdir = getenv("QEMU_TMPDIR");
131
        if (!tmpdir)
132
#ifdef HOST_SOLARIS
133
            tmpdir = "/tmp";
134
        if (statvfs(tmpdir, &stfs) == 0) {
135
#else
136
            tmpdir = "/dev/shm";
137
        if (statfs(tmpdir, &stfs) == 0) {
138
#endif
139
            int64_t free_space;
140
            int ram_mb;
141

    
142
            free_space = (int64_t)stfs.f_bavail * stfs.f_bsize;
143
            if ((ram_size + 8192 * 1024) >= free_space) {
144
                ram_mb = (ram_size / (1024 * 1024));
145
                fprintf(stderr,
146
                        "You do not have enough space in '%s' for the %d MB of QEMU virtual RAM.\n",
147
                        tmpdir, ram_mb);
148
                if (strcmp(tmpdir, "/dev/shm") == 0) {
149
                    fprintf(stderr, "To have more space available provided you have enough RAM and swap, do as root:\n"
150
                            "mount -o remount,size=%dm /dev/shm\n",
151
                            ram_mb + 16);
152
                } else {
153
                    fprintf(stderr,
154
                            "Use the '-m' option of QEMU to diminish the amount of virtual RAM or use the\n"
155
                            "QEMU_TMPDIR environment variable to set another directory where the QEMU\n"
156
                            "temporary RAM file will be opened.\n");
157
                }
158
                fprintf(stderr, "Or disable the accelerator module with -no-kqemu\n");
159
                exit(1);
160
            }
161
        }
162
        snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX",
163
                 tmpdir);
164
        phys_ram_fd = mkstemp(phys_ram_file);
165
        if (phys_ram_fd < 0) {
166
            fprintf(stderr,
167
                    "warning: could not create temporary file in '%s'.\n"
168
                    "Use QEMU_TMPDIR to select a directory in a tmpfs filesystem.\n"
169
                    "Using '/tmp' as fallback.\n",
170
                    tmpdir);
171
            snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/qemuXXXXXX",
172
                     "/tmp");
173
            phys_ram_fd = mkstemp(phys_ram_file);
174
            if (phys_ram_fd < 0) {
175
                fprintf(stderr, "Could not create temporary memory file '%s'\n",
176
                        phys_ram_file);
177
                exit(1);
178
            }
179
        }
180
        unlink(phys_ram_file);
181
    }
182
    size = (size + 4095) & ~4095;
183
    ftruncate(phys_ram_fd, phys_ram_size + size);
184
#endif /* !(__OpenBSD__ || __FreeBSD__ || __DragonFly__) */
185
    ptr = mmap(NULL,
186
               size,
187
               PROT_WRITE | PROT_READ, map_anon | MAP_SHARED,
188
               phys_ram_fd, phys_ram_size);
189
    if (ptr == MAP_FAILED) {
190
        fprintf(stderr, "Could not map physical memory\n");
191
        exit(1);
192
    }
193
    phys_ram_size += size;
194
    return ptr;
195
}
196

    
197
static void kqemu_vfree(void *ptr)
198
{
199
    /* may be useful some day, but currently we do not need to free */
200
}
201

    
202
#endif
203

    
204
void *qemu_memalign(size_t alignment, size_t size)
205
{
206
#if defined(_POSIX_C_SOURCE)
207
    int ret;
208
    void *ptr;
209
    ret = posix_memalign(&ptr, alignment, size);
210
    if (ret != 0)
211
        abort();
212
    return ptr;
213
#elif defined(HOST_BSD)
214
    return oom_check(valloc(size));
215
#else
216
    return oom_check(memalign(alignment, size));
217
#endif
218
}
219

    
220
/* alloc shared memory pages */
221
void *qemu_vmalloc(size_t size)
222
{
223
#if defined(CONFIG_KQEMU)
224
    if (kqemu_allowed)
225
        return kqemu_vmalloc(size);
226
#endif
227
    return qemu_memalign(getpagesize(), size);
228
}
229

    
230
void qemu_vfree(void *ptr)
231
{
232
#if defined(CONFIG_KQEMU)
233
    if (kqemu_allowed)
234
        kqemu_vfree(ptr);
235
#endif
236
    free(ptr);
237
}
238

    
239
#endif
240

    
241
int qemu_create_pidfile(const char *filename)
242
{
243
    char buffer[128];
244
    int len;
245
#ifndef _WIN32
246
    int fd;
247

    
248
    fd = open(filename, O_RDWR | O_CREAT, 0600);
249
    if (fd == -1)
250
        return -1;
251

    
252
    if (lockf(fd, F_TLOCK, 0) == -1)
253
        return -1;
254

    
255
    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
256
    if (write(fd, buffer, len) != len)
257
        return -1;
258
#else
259
    HANDLE file;
260
    DWORD flags;
261
    OVERLAPPED overlap;
262
    BOOL ret;
263

    
264
    /* Open for writing with no sharing. */
265
    file = CreateFile(filename, GENERIC_WRITE, 0, NULL,
266
                      OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
267

    
268
    if (file == INVALID_HANDLE_VALUE)
269
      return -1;
270

    
271
    flags = LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY;
272
    overlap.hEvent = 0;
273
    /* Lock 1 byte. */
274
    ret = LockFileEx(file, flags, 0, 0, 1, &overlap);
275
    if (ret == 0)
276
      return -1;
277

    
278
    /* Write PID to file. */
279
    len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
280
    ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len,
281
                      &overlap, NULL);
282
    if (ret == 0)
283
      return -1;
284
#endif
285
    return 0;
286
}
287

    
288
#ifdef _WIN32
289

    
290
/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
291
#define _W32_FT_OFFSET (116444736000000000ULL)
292

    
293
int qemu_gettimeofday(qemu_timeval *tp)
294
{
295
  union {
296
    unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
297
    FILETIME ft;
298
  }  _now;
299

    
300
  if(tp)
301
    {
302
      GetSystemTimeAsFileTime (&_now.ft);
303
      tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
304
      tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
305
    }
306
  /* Always return 0 as per Open Group Base Specifications Issue 6.
307
     Do not set errno on error.  */
308
  return 0;
309
}
310
#endif /* _WIN32 */
311

    
312

    
313
#ifdef _WIN32
314
void socket_set_nonblock(int fd)
315
{
316
    unsigned long opt = 1;
317
    ioctlsocket(fd, FIONBIO, &opt);
318
}
319

    
320
int inet_aton(const char *cp, struct in_addr *ia)
321
{
322
    uint32_t addr = inet_addr(cp);
323
    if (addr == 0xffffffff)
324
        return 0;
325
    ia->s_addr = addr;
326
    return 1;
327
}
328
#else
329
void socket_set_nonblock(int fd)
330
{
331
    int f;
332
    f = fcntl(fd, F_GETFL);
333
    fcntl(fd, F_SETFL, f | O_NONBLOCK);
334
}
335
#endif