]> Git Repo - qemu.git/blob - osdep.c
Merge branch 'pci' into for_anthony
[qemu.git] / osdep.c
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
32 /* Needed early for CONFIG_BSD etc. */
33 #include "config-host.h"
34
35 #if defined(CONFIG_MADVISE) || defined(CONFIG_POSIX_MADVISE)
36 #include <sys/mman.h>
37 #endif
38
39 #ifdef CONFIG_SOLARIS
40 #include <sys/types.h>
41 #include <sys/statvfs.h>
42 /* See MySQL bug #7156 (http://bugs.mysql.com/bug.php?id=7156) for
43    discussion about Solaris header problems */
44 extern int madvise(caddr_t, size_t, int);
45 #endif
46
47 #ifdef CONFIG_EVENTFD
48 #include <sys/eventfd.h>
49 #endif
50
51 #ifdef _WIN32
52 #include <windows.h>
53 #elif defined(CONFIG_BSD)
54 #include <stdlib.h>
55 #else
56 #include <malloc.h>
57 #endif
58
59 #include "qemu-common.h"
60 #include "trace.h"
61 #include "sysemu.h"
62 #include "qemu_socket.h"
63
64 #if !defined(_POSIX_C_SOURCE) || defined(_WIN32) || defined(__sun__)
65 static void *oom_check(void *ptr)
66 {
67     if (ptr == NULL) {
68 #if defined(_WIN32)
69         fprintf(stderr, "Failed to allocate memory: %lu\n", GetLastError());
70 #else
71         fprintf(stderr, "Failed to allocate memory: %s\n", strerror(errno));
72 #endif
73         abort();
74     }
75     return ptr;
76 }
77 #endif
78
79 #if defined(_WIN32)
80 void *qemu_memalign(size_t alignment, size_t size)
81 {
82     void *ptr;
83
84     if (!size) {
85         abort();
86     }
87     ptr = oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
88     trace_qemu_memalign(alignment, size, ptr);
89     return ptr;
90 }
91
92 void *qemu_vmalloc(size_t size)
93 {
94     void *ptr;
95
96     /* FIXME: this is not exactly optimal solution since VirtualAlloc
97        has 64Kb granularity, but at least it guarantees us that the
98        memory is page aligned. */
99     if (!size) {
100         abort();
101     }
102     ptr = oom_check(VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE));
103     trace_qemu_vmalloc(size, ptr);
104     return ptr;
105 }
106
107 void qemu_vfree(void *ptr)
108 {
109     trace_qemu_vfree(ptr);
110     VirtualFree(ptr, 0, MEM_RELEASE);
111 }
112
113 #else
114
115 void *qemu_memalign(size_t alignment, size_t size)
116 {
117     void *ptr;
118 #if defined(_POSIX_C_SOURCE) && !defined(__sun__)
119     int ret;
120     ret = posix_memalign(&ptr, alignment, size);
121     if (ret != 0) {
122         fprintf(stderr, "Failed to allocate %zu B: %s\n",
123                 size, strerror(ret));
124         abort();
125     }
126 #elif defined(CONFIG_BSD)
127     ptr = oom_check(valloc(size));
128 #else
129     ptr = oom_check(memalign(alignment, size));
130 #endif
131     trace_qemu_memalign(alignment, size, ptr);
132     return ptr;
133 }
134
135 /* alloc shared memory pages */
136 void *qemu_vmalloc(size_t size)
137 {
138     return qemu_memalign(getpagesize(), size);
139 }
140
141 void qemu_vfree(void *ptr)
142 {
143     trace_qemu_vfree(ptr);
144     free(ptr);
145 }
146
147 #endif
148
149 int qemu_madvise(void *addr, size_t len, int advice)
150 {
151     if (advice == QEMU_MADV_INVALID) {
152         errno = EINVAL;
153         return -1;
154     }
155 #if defined(CONFIG_MADVISE)
156     return madvise(addr, len, advice);
157 #elif defined(CONFIG_POSIX_MADVISE)
158     return posix_madvise(addr, len, advice);
159 #else
160     errno = EINVAL;
161     return -1;
162 #endif
163 }
164
165 int qemu_create_pidfile(const char *filename)
166 {
167     char buffer[128];
168     int len;
169 #ifndef _WIN32
170     int fd;
171
172     fd = qemu_open(filename, O_RDWR | O_CREAT, 0600);
173     if (fd == -1)
174         return -1;
175
176     if (lockf(fd, F_TLOCK, 0) == -1)
177         return -1;
178
179     len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
180     if (write(fd, buffer, len) != len)
181         return -1;
182 #else
183     HANDLE file;
184     OVERLAPPED overlap;
185     BOOL ret;
186     memset(&overlap, 0, sizeof(overlap));
187
188     file = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ, NULL,
189                       OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
190
191     if (file == INVALID_HANDLE_VALUE)
192       return -1;
193
194     len = snprintf(buffer, sizeof(buffer), "%ld\n", (long)getpid());
195     ret = WriteFileEx(file, (LPCVOID)buffer, (DWORD)len,
196                       &overlap, NULL);
197     if (ret == 0)
198       return -1;
199 #endif
200     return 0;
201 }
202
203 #ifdef _WIN32
204
205 /* mingw32 needs ffs for compilations without optimization. */
206 int ffs(int i)
207 {
208     /* Use gcc's builtin ffs. */
209     return __builtin_ffs(i);
210 }
211
212 /* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
213 #define _W32_FT_OFFSET (116444736000000000ULL)
214
215 int qemu_gettimeofday(qemu_timeval *tp)
216 {
217   union {
218     unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
219     FILETIME ft;
220   }  _now;
221
222   if(tp)
223     {
224       GetSystemTimeAsFileTime (&_now.ft);
225       tp->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL );
226       tp->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL);
227     }
228   /* Always return 0 as per Open Group Base Specifications Issue 6.
229      Do not set errno on error.  */
230   return 0;
231 }
232 #endif /* _WIN32 */
233
234
235 #ifdef _WIN32
236 void socket_set_nonblock(int fd)
237 {
238     unsigned long opt = 1;
239     ioctlsocket(fd, FIONBIO, &opt);
240 }
241
242 int inet_aton(const char *cp, struct in_addr *ia)
243 {
244     uint32_t addr = inet_addr(cp);
245     if (addr == 0xffffffff)
246         return 0;
247     ia->s_addr = addr;
248     return 1;
249 }
250
251 void qemu_set_cloexec(int fd)
252 {
253 }
254
255 #else
256
257 void socket_set_nonblock(int fd)
258 {
259     int f;
260     f = fcntl(fd, F_GETFL);
261     fcntl(fd, F_SETFL, f | O_NONBLOCK);
262 }
263
264 void qemu_set_cloexec(int fd)
265 {
266     int f;
267     f = fcntl(fd, F_GETFD);
268     fcntl(fd, F_SETFD, f | FD_CLOEXEC);
269 }
270
271 #endif
272
273 /*
274  * Opens a file with FD_CLOEXEC set
275  */
276 int qemu_open(const char *name, int flags, ...)
277 {
278     int ret;
279     int mode = 0;
280
281     if (flags & O_CREAT) {
282         va_list ap;
283
284         va_start(ap, flags);
285         mode = va_arg(ap, int);
286         va_end(ap);
287     }
288
289 #ifdef O_CLOEXEC
290     ret = open(name, flags | O_CLOEXEC, mode);
291 #else
292     ret = open(name, flags, mode);
293     if (ret >= 0) {
294         qemu_set_cloexec(ret);
295     }
296 #endif
297
298     return ret;
299 }
300
301 /*
302  * A variant of write(2) which handles partial write.
303  *
304  * Return the number of bytes transferred.
305  * Set errno if fewer than `count' bytes are written.
306  *
307  * This function don't work with non-blocking fd's.
308  * Any of the possibilities with non-bloking fd's is bad:
309  *   - return a short write (then name is wrong)
310  *   - busy wait adding (errno == EAGAIN) to the loop
311  */
312 ssize_t qemu_write_full(int fd, const void *buf, size_t count)
313 {
314     ssize_t ret = 0;
315     ssize_t total = 0;
316
317     while (count) {
318         ret = write(fd, buf, count);
319         if (ret < 0) {
320             if (errno == EINTR)
321                 continue;
322             break;
323         }
324
325         count -= ret;
326         buf += ret;
327         total += ret;
328     }
329
330     return total;
331 }
332
333 #ifndef _WIN32
334 /*
335  * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set.
336  */
337 int qemu_eventfd(int fds[2])
338 {
339 #ifdef CONFIG_EVENTFD
340     int ret;
341
342     ret = eventfd(0, 0);
343     if (ret >= 0) {
344         fds[0] = ret;
345         qemu_set_cloexec(ret);
346         if ((fds[1] = dup(ret)) == -1) {
347             close(ret);
348             return -1;
349         }
350         qemu_set_cloexec(fds[1]);
351         return 0;
352     }
353
354     if (errno != ENOSYS) {
355         return -1;
356     }
357 #endif
358
359     return qemu_pipe(fds);
360 }
361
362 /*
363  * Creates a pipe with FD_CLOEXEC set on both file descriptors
364  */
365 int qemu_pipe(int pipefd[2])
366 {
367     int ret;
368
369 #ifdef CONFIG_PIPE2
370     ret = pipe2(pipefd, O_CLOEXEC);
371     if (ret != -1 || errno != ENOSYS) {
372         return ret;
373     }
374 #endif
375     ret = pipe(pipefd);
376     if (ret == 0) {
377         qemu_set_cloexec(pipefd[0]);
378         qemu_set_cloexec(pipefd[1]);
379     }
380
381     return ret;
382 }
383 #endif
384
385 /*
386  * Opens a socket with FD_CLOEXEC set
387  */
388 int qemu_socket(int domain, int type, int protocol)
389 {
390     int ret;
391
392 #ifdef SOCK_CLOEXEC
393     ret = socket(domain, type | SOCK_CLOEXEC, protocol);
394     if (ret != -1 || errno != EINVAL) {
395         return ret;
396     }
397 #endif
398     ret = socket(domain, type, protocol);
399     if (ret >= 0) {
400         qemu_set_cloexec(ret);
401     }
402
403     return ret;
404 }
405
406 /*
407  * Accept a connection and set FD_CLOEXEC
408  */
409 int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen)
410 {
411     int ret;
412
413 #ifdef CONFIG_ACCEPT4
414     ret = accept4(s, addr, addrlen, SOCK_CLOEXEC);
415     if (ret != -1 || errno != ENOSYS) {
416         return ret;
417     }
418 #endif
419     ret = accept(s, addr, addrlen);
420     if (ret >= 0) {
421         qemu_set_cloexec(ret);
422     }
423
424     return ret;
425 }
This page took 0.044988 seconds and 4 git commands to generate.