engines/exec: Code cleanup to remove leaks
[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 #include <android/api-level.h>
75 #if __ANDROID_API__ >= __ANDROID_API_O__
76 #include <android/sharedmem.h>
77 #else
78 #define ASHMEM_DEVICE   "/dev/ashmem"
79 #endif
80 #define shmid_ds shmid64_ds
81 #define SHM_HUGETLB    04000
82
83 static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf)
84 {
85         int ret=0;
86         if (__cmd == IPC_RMID)
87         {
88                 int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
89                 struct ashmem_pin pin = {0 , length};
90                 ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
91                 close(__shmid);
92         }
93         return ret;
94 }
95
96 #if __ANDROID_API__ >= __ANDROID_API_O__
97 static inline int shmget(key_t __key, size_t __size, int __shmflg)
98 {
99         char keybuf[11];
100
101         sprintf(keybuf, "%d", __key);
102
103         return ASharedMemory_create(keybuf, __size + sizeof(uint64_t));
104 }
105 #else
106 static inline int shmget(key_t __key, size_t __size, int __shmflg)
107 {
108         int fd,ret;
109         char keybuf[11];
110
111         fd = open(ASHMEM_DEVICE, O_RDWR);
112         if (fd < 0)
113                 return fd;
114
115         sprintf(keybuf,"%d",__key);
116         ret = ioctl(fd, ASHMEM_SET_NAME, keybuf);
117         if (ret < 0)
118                 goto error;
119
120         /* Stores size in first 8 bytes, allocate extra space */
121         ret = ioctl(fd, ASHMEM_SET_SIZE, __size + sizeof(uint64_t));
122         if (ret < 0)
123                 goto error;
124
125         return fd;
126
127 error:
128         close(fd);
129         return ret;
130 }
131 #endif
132
133 static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg)
134 {
135         size_t size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
136         /* Needs to be 8-byte aligned to prevent SIGBUS on 32-bit ARM */
137         uint64_t *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0);
138         /* Save size at beginning of buffer, for use with munmap */
139         *ptr = size;
140         return ptr + 1;
141 }
142
143 static inline int shmdt (const void *__shmaddr)
144 {
145         /* Find mmap size which we stored at the beginning of the buffer */
146         uint64_t *ptr = (uint64_t *)__shmaddr - 1;
147         size_t size = *ptr;
148         return munmap(ptr, size);
149 }
150 #endif
151
152 #define SPLICE_DEF_SIZE (64*1024)
153
154 enum {
155         IOPRIO_CLASS_NONE,
156         IOPRIO_CLASS_RT,
157         IOPRIO_CLASS_BE,
158         IOPRIO_CLASS_IDLE,
159 };
160
161 enum {
162         IOPRIO_WHO_PROCESS = 1,
163         IOPRIO_WHO_PGRP,
164         IOPRIO_WHO_USER,
165 };
166
167 #define IOPRIO_BITS             16
168 #define IOPRIO_CLASS_SHIFT      13
169
170 #define IOPRIO_MIN_PRIO         0       /* highest priority */
171 #define IOPRIO_MAX_PRIO         7       /* lowest priority */
172
173 #define IOPRIO_MIN_PRIO_CLASS   0
174 #define IOPRIO_MAX_PRIO_CLASS   3
175
176 static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio)
177 {
178         /*
179          * If no class is set, assume BE
180          */
181         if (!ioprio_class)
182                 ioprio_class = IOPRIO_CLASS_BE;
183
184         ioprio |= ioprio_class << IOPRIO_CLASS_SHIFT;
185         return syscall(__NR_ioprio_set, which, who, ioprio);
186 }
187
188 #ifndef BLKGETSIZE64
189 #define BLKGETSIZE64    _IOR(0x12,114,size_t)
190 #endif
191
192 #ifndef BLKFLSBUF
193 #define BLKFLSBUF       _IO(0x12,97)
194 #endif
195
196 #ifndef BLKDISCARD
197 #define BLKDISCARD      _IO(0x12,119)
198 #endif
199
200 static inline int blockdev_invalidate_cache(struct fio_file *f)
201 {
202         return ioctl(f->fd, BLKFLSBUF);
203 }
204
205 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
206 {
207         if (!ioctl(f->fd, BLKGETSIZE64, bytes))
208                 return 0;
209
210         return errno;
211 }
212
213 static inline unsigned long long os_phys_mem(void)
214 {
215         long pagesize, pages;
216
217         pagesize = sysconf(_SC_PAGESIZE);
218         pages = sysconf(_SC_PHYS_PAGES);
219         if (pages == -1 || pagesize == -1)
220                 return 0;
221
222         return (unsigned long long) pages * (unsigned long long) pagesize;
223 }
224
225 #ifdef O_NOATIME
226 #define FIO_O_NOATIME   O_NOATIME
227 #else
228 #define FIO_O_NOATIME   0
229 #endif
230
231 /* Check for GCC or Clang byte swap intrinsics */
232 #if (__has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) \
233      && __has_builtin(__builtin_bswap64)) || (__GNUC__ > 4 \
234      || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) /* fio_swapN */
235 #define fio_swap16(x)   __builtin_bswap16(x)
236 #define fio_swap32(x)   __builtin_bswap32(x)
237 #define fio_swap64(x)   __builtin_bswap64(x)
238 #else
239 #include <byteswap.h>
240 #define fio_swap16(x)   bswap_16(x)
241 #define fio_swap32(x)   bswap_32(x)
242 #define fio_swap64(x)   bswap_64(x)
243 #endif /* fio_swapN */
244
245 #define CACHE_LINE_FILE \
246         "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"
247
248 static inline int arch_cache_line_size(void)
249 {
250         char size[32];
251         int fd, ret;
252
253         fd = open(CACHE_LINE_FILE, O_RDONLY);
254         if (fd < 0)
255                 return -1;
256
257         ret = read(fd, size, sizeof(size));
258
259         close(fd);
260
261         if (ret <= 0)
262                 return -1;
263         else
264                 return atoi(size);
265 }
266
267 static inline unsigned long long get_fs_free_size(const char *path)
268 {
269         unsigned long long ret;
270         struct statfs s;
271
272         if (statfs(path, &s) < 0)
273                 return -1ULL;
274
275         ret = s.f_bsize;
276         ret *= (unsigned long long) s.f_bfree;
277         return ret;
278 }
279
280 static inline int os_trim(struct fio_file *f, unsigned long long start,
281                           unsigned long long len)
282 {
283         uint64_t range[2];
284
285         range[0] = start;
286         range[1] = len;
287
288         if (!ioctl(f->fd, BLKDISCARD, range))
289                 return 0;
290
291         return errno;
292 }
293
294 #ifdef CONFIG_SCHED_IDLE
295 static inline int fio_set_sched_idle(void)
296 {
297         struct sched_param p = { .sched_priority = 0, };
298         return sched_setscheduler(gettid(), SCHED_IDLE, &p);
299 }
300 #endif
301
302 #endif