gettime: Fix compilation on non-Linux with pthread_getaffinity_np()
[fio.git] / os / os-android.h
1 #ifndef FIO_OS_ANDROID_H
2 #define FIO_OS_ANDROID_H
3
4 #define FIO_OS  os_android
5
6 #include <sys/ioctl.h>
7 #include <sys/mman.h>
8 #include <sys/uio.h>
9 #include <sys/syscall.h>
10 #include <sys/sysmacros.h>
11 #include <sys/vfs.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <errno.h>
15 #include <sched.h>
16 #include <linux/unistd.h>
17 #include <linux/major.h>
18 #include <asm/byteorder.h>
19
20 #include "./os-linux-syscall.h"
21 #include "../file.h"
22
23 #ifndef __has_builtin         // Optional of course.
24   #define __has_builtin(x) 0  // Compatibility with non-clang compilers.
25 #endif
26
27 #define FIO_HAVE_DISK_UTIL
28 #define FIO_HAVE_IOSCHED_SWITCH
29 #define FIO_HAVE_IOPRIO
30 #define FIO_HAVE_IOPRIO_CLASS
31 #define FIO_HAVE_ODIRECT
32 #define FIO_HAVE_HUGETLB
33 #define FIO_HAVE_BLKTRACE
34 #define FIO_HAVE_CL_SIZE
35 #define FIO_HAVE_CGROUPS
36 #define FIO_HAVE_FS_STAT
37 #define FIO_HAVE_TRIM
38 #define FIO_HAVE_GETTID
39 #define FIO_USE_GENERIC_INIT_RANDOM_STATE
40 #define FIO_HAVE_E4_ENG
41 #define FIO_HAVE_BYTEORDER_FUNCS
42 #define FIO_HAVE_MMAP_HUGE
43 #define FIO_NO_HAVE_SHM_H
44
45 #define OS_MAP_ANON             MAP_ANONYMOUS
46
47 #ifndef POSIX_MADV_DONTNEED
48 #define posix_madvise   madvise
49 #define POSIX_MADV_DONTNEED MADV_DONTNEED
50 #define POSIX_MADV_SEQUENTIAL   MADV_SEQUENTIAL
51 #define POSIX_MADV_RANDOM       MADV_RANDOM
52 #endif
53
54 #ifdef MADV_REMOVE
55 #define FIO_MADV_FREE   MADV_REMOVE
56 #endif
57 #ifndef MAP_HUGETLB
58 #define MAP_HUGETLB 0x40000 /* arch specific */
59 #endif
60
61 #ifdef CONFIG_PTHREAD_GETAFFINITY
62 #define FIO_HAVE_GET_THREAD_AFFINITY
63 #define fio_get_thread_affinity(mask)   \
64         pthread_getaffinity_np(pthread_self(), sizeof(mask), &(mask))
65 #endif
66
67 #ifndef CONFIG_NO_SHM
68 /*
69  * Bionic doesn't support SysV shared memeory, so implement it using ashmem
70  */
71 #include <stdio.h>
72 #include <linux/ashmem.h>
73 #include <linux/shm.h>
74 #define shmid_ds shmid64_ds
75 #define SHM_HUGETLB    04000
76
77 #define ASHMEM_DEVICE   "/dev/ashmem"
78
79 static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf)
80 {
81         int ret=0;
82         if (__cmd == IPC_RMID)
83         {
84                 int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
85                 struct ashmem_pin pin = {0 , length};
86                 ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
87                 close(__shmid);
88         }
89         return ret;
90 }
91
92 static inline int shmget(key_t __key, size_t __size, int __shmflg)
93 {
94         int fd,ret;
95         char keybuf[11];
96
97         fd = open(ASHMEM_DEVICE, O_RDWR);
98         if (fd < 0)
99                 return fd;
100
101         sprintf(keybuf,"%d",__key);
102         ret = ioctl(fd, ASHMEM_SET_NAME, keybuf);
103         if (ret < 0)
104                 goto error;
105
106         /* Stores size in first 8 bytes, allocate extra space */
107         ret = ioctl(fd, ASHMEM_SET_SIZE, __size + sizeof(uint64_t));
108         if (ret < 0)
109                 goto error;
110
111         return fd;
112
113 error:
114         close(fd);
115         return ret;
116 }
117
118 static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg)
119 {
120         size_t size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
121         /* Needs to be 8-byte aligned to prevent SIGBUS on 32-bit ARM */
122         uint64_t *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0);
123         /* Save size at beginning of buffer, for use with munmap */
124         *ptr = size;
125         return ptr + 1;
126 }
127
128 static inline int shmdt (const void *__shmaddr)
129 {
130         /* Find mmap size which we stored at the beginning of the buffer */
131         uint64_t *ptr = (uint64_t *)__shmaddr - 1;
132         size_t size = *ptr;
133         return munmap(ptr, size);
134 }
135 #endif
136
137 #define SPLICE_DEF_SIZE (64*1024)
138
139 enum {
140         IOPRIO_CLASS_NONE,
141         IOPRIO_CLASS_RT,
142         IOPRIO_CLASS_BE,
143         IOPRIO_CLASS_IDLE,
144 };
145
146 enum {
147         IOPRIO_WHO_PROCESS = 1,
148         IOPRIO_WHO_PGRP,
149         IOPRIO_WHO_USER,
150 };
151
152 #define IOPRIO_BITS             16
153 #define IOPRIO_CLASS_SHIFT      13
154
155 #define IOPRIO_MIN_PRIO         0       /* highest priority */
156 #define IOPRIO_MAX_PRIO         7       /* lowest priority */
157
158 #define IOPRIO_MIN_PRIO_CLASS   0
159 #define IOPRIO_MAX_PRIO_CLASS   3
160
161 static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio)
162 {
163         /*
164          * If no class is set, assume BE
165          */
166         if (!ioprio_class)
167                 ioprio_class = IOPRIO_CLASS_BE;
168
169         ioprio |= ioprio_class << IOPRIO_CLASS_SHIFT;
170         return syscall(__NR_ioprio_set, which, who, ioprio);
171 }
172
173 #ifndef BLKGETSIZE64
174 #define BLKGETSIZE64    _IOR(0x12,114,size_t)
175 #endif
176
177 #ifndef BLKFLSBUF
178 #define BLKFLSBUF       _IO(0x12,97)
179 #endif
180
181 #ifndef BLKDISCARD
182 #define BLKDISCARD      _IO(0x12,119)
183 #endif
184
185 static inline int blockdev_invalidate_cache(struct fio_file *f)
186 {
187         return ioctl(f->fd, BLKFLSBUF);
188 }
189
190 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
191 {
192         if (!ioctl(f->fd, BLKGETSIZE64, bytes))
193                 return 0;
194
195         return errno;
196 }
197
198 static inline unsigned long long os_phys_mem(void)
199 {
200         long pagesize, pages;
201
202         pagesize = sysconf(_SC_PAGESIZE);
203         pages = sysconf(_SC_PHYS_PAGES);
204         if (pages == -1 || pagesize == -1)
205                 return 0;
206
207         return (unsigned long long) pages * (unsigned long long) pagesize;
208 }
209
210 #ifdef O_NOATIME
211 #define FIO_O_NOATIME   O_NOATIME
212 #else
213 #define FIO_O_NOATIME   0
214 #endif
215
216 /* Check for GCC or Clang byte swap intrinsics */
217 #if (__has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) \
218      && __has_builtin(__builtin_bswap64)) || (__GNUC__ > 4 \
219      || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) /* fio_swapN */
220 #define fio_swap16(x)   __builtin_bswap16(x)
221 #define fio_swap32(x)   __builtin_bswap32(x)
222 #define fio_swap64(x)   __builtin_bswap64(x)
223 #else
224 #include <byteswap.h>
225 #define fio_swap16(x)   bswap_16(x)
226 #define fio_swap32(x)   bswap_32(x)
227 #define fio_swap64(x)   bswap_64(x)
228 #endif /* fio_swapN */
229
230 #define CACHE_LINE_FILE \
231         "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"
232
233 static inline int arch_cache_line_size(void)
234 {
235         char size[32];
236         int fd, ret;
237
238         fd = open(CACHE_LINE_FILE, O_RDONLY);
239         if (fd < 0)
240                 return -1;
241
242         ret = read(fd, size, sizeof(size));
243
244         close(fd);
245
246         if (ret <= 0)
247                 return -1;
248         else
249                 return atoi(size);
250 }
251
252 static inline unsigned long long get_fs_free_size(const char *path)
253 {
254         unsigned long long ret;
255         struct statfs s;
256
257         if (statfs(path, &s) < 0)
258                 return -1ULL;
259
260         ret = s.f_bsize;
261         ret *= (unsigned long long) s.f_bfree;
262         return ret;
263 }
264
265 static inline int os_trim(struct fio_file *f, unsigned long long start,
266                           unsigned long long len)
267 {
268         uint64_t range[2];
269
270         range[0] = start;
271         range[1] = len;
272
273         if (!ioctl(f->fd, BLKDISCARD, range))
274                 return 0;
275
276         return errno;
277 }
278
279 #ifdef CONFIG_SCHED_IDLE
280 static inline int fio_set_sched_idle(void)
281 {
282         struct sched_param p = { .sched_priority = 0, };
283         return sched_setscheduler(gettid(), SCHED_IDLE, &p);
284 }
285 #endif
286
287 #endif