Enable CPU affinity support on Android
[fio.git] / os / os-android.h
CommitLineData
ec5c6b12
AC
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>
93eeb558 7#include <sys/mman.h>
ec5c6b12
AC
8#include <sys/uio.h>
9#include <sys/syscall.h>
036a1599 10#include <sys/sysmacros.h>
ec5c6b12
AC
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>
da52c582 18#include <asm/byteorder.h>
ec5c6b12 19
eec97b93 20#include "./os-linux-syscall.h"
ec5c6b12
AC
21#include "../file.h"
22
0fa5c986
OM
23#ifndef __has_builtin // Optional of course.
24 #define __has_builtin(x) 0 // Compatibility with non-clang compilers.
25#endif
26
5446b11a 27#define FIO_HAVE_CPU_AFFINITY
ec5c6b12 28#define FIO_HAVE_DISK_UTIL
ec5c6b12 29#define FIO_HAVE_IOSCHED_SWITCH
177380ab 30#define FIO_HAVE_IOPRIO
32ef447a 31#define FIO_HAVE_IOPRIO_CLASS
ec5c6b12
AC
32#define FIO_HAVE_ODIRECT
33#define FIO_HAVE_HUGETLB
34#define FIO_HAVE_BLKTRACE
ec5c6b12 35#define FIO_HAVE_CL_SIZE
3714a963 36#define FIO_HAVE_CGROUPS
ec5c6b12
AC
37#define FIO_HAVE_FS_STAT
38#define FIO_HAVE_TRIM
ec5c6b12
AC
39#define FIO_HAVE_GETTID
40#define FIO_USE_GENERIC_INIT_RANDOM_STATE
41#define FIO_HAVE_E4_ENG
42#define FIO_HAVE_BYTEORDER_FUNCS
6d0e9f83 43#define FIO_HAVE_MMAP_HUGE
a5e0ee11 44#define FIO_NO_HAVE_SHM_H
ec5c6b12
AC
45
46#define OS_MAP_ANON MAP_ANONYMOUS
47
5446b11a
BVA
48typedef cpu_set_t os_cpu_mask_t;
49
50#define fio_setaffinity(pid, cpumask) \
51 sched_setaffinity((pid), sizeof(cpumask), &(cpumask))
52#define fio_getaffinity(pid, ptr) \
53 sched_getaffinity((pid), sizeof(cpu_set_t), (ptr))
54
93eeb558 55#ifndef POSIX_MADV_DONTNEED
ec5c6b12
AC
56#define posix_madvise madvise
57#define POSIX_MADV_DONTNEED MADV_DONTNEED
58#define POSIX_MADV_SEQUENTIAL MADV_SEQUENTIAL
59#define POSIX_MADV_RANDOM MADV_RANDOM
93eeb558 60#endif
61
ec5c6b12
AC
62#ifdef MADV_REMOVE
63#define FIO_MADV_FREE MADV_REMOVE
64#endif
a5e0ee11
O
65#ifndef MAP_HUGETLB
66#define MAP_HUGETLB 0x40000 /* arch specific */
67#endif
ec5c6b12 68
e9d2a04d
TK
69#ifdef CONFIG_PTHREAD_GETAFFINITY
70#define FIO_HAVE_GET_THREAD_AFFINITY
71#define fio_get_thread_affinity(mask) \
72 pthread_getaffinity_np(pthread_self(), sizeof(mask), &(mask))
73#endif
74
5446b11a
BVA
75#define fio_cpu_clear(mask, cpu) CPU_CLR((cpu), (mask))
76#define fio_cpu_set(mask, cpu) CPU_SET((cpu), (mask))
77#define fio_cpu_isset(mask, cpu) (CPU_ISSET((cpu), (mask)) != 0)
78#define fio_cpu_count(mask) CPU_COUNT((mask))
79
80static inline int fio_cpuset_init(os_cpu_mask_t *mask)
81{
82 CPU_ZERO(mask);
83 return 0;
84}
85
86static inline int fio_cpuset_exit(os_cpu_mask_t *mask)
87{
88 return 0;
89}
90
91#define FIO_MAX_CPUS CPU_SETSIZE
92
6ca9b06d 93#ifndef CONFIG_NO_SHM
ec5c6b12 94/*
fc002f14 95 * Bionic doesn't support SysV shared memory, so implement it using ashmem
ec5c6b12 96 */
239a11de
AJ
97#include <stdio.h>
98#include <linux/ashmem.h>
68bf62a0 99#include <linux/shm.h>
d7e3adb6
D
100#include <android/api-level.h>
101#if __ANDROID_API__ >= __ANDROID_API_O__
102#include <android/sharedmem.h>
103#else
104#define ASHMEM_DEVICE "/dev/ashmem"
105#endif
68bf62a0
OM
106#define shmid_ds shmid64_ds
107#define SHM_HUGETLB 04000
239a11de 108
68bf62a0 109static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf)
ec5c6b12 110{
239a11de
AJ
111 int ret=0;
112 if (__cmd == IPC_RMID)
113 {
114 int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
115 struct ashmem_pin pin = {0 , length};
116 ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
117 close(__shmid);
118 }
119 return ret;
ec5c6b12
AC
120}
121
d7e3adb6
D
122#if __ANDROID_API__ >= __ANDROID_API_O__
123static inline int shmget(key_t __key, size_t __size, int __shmflg)
124{
125 char keybuf[11];
126
127 sprintf(keybuf, "%d", __key);
128
129 return ASharedMemory_create(keybuf, __size + sizeof(uint64_t));
130}
131#else
68bf62a0 132static inline int shmget(key_t __key, size_t __size, int __shmflg)
ec5c6b12 133{
239a11de 134 int fd,ret;
91f64346
OM
135 char keybuf[11];
136
239a11de
AJ
137 fd = open(ASHMEM_DEVICE, O_RDWR);
138 if (fd < 0)
139 return fd;
140
91f64346
OM
141 sprintf(keybuf,"%d",__key);
142 ret = ioctl(fd, ASHMEM_SET_NAME, keybuf);
239a11de
AJ
143 if (ret < 0)
144 goto error;
145
d8767475
OM
146 /* Stores size in first 8 bytes, allocate extra space */
147 ret = ioctl(fd, ASHMEM_SET_SIZE, __size + sizeof(uint64_t));
239a11de
AJ
148 if (ret < 0)
149 goto error;
150
151 return fd;
91f64346 152
239a11de
AJ
153error:
154 close(fd);
155 return ret;
ec5c6b12 156}
d7e3adb6 157#endif
ec5c6b12 158
68bf62a0 159static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg)
ec5c6b12 160{
d8767475
OM
161 size_t size = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
162 /* Needs to be 8-byte aligned to prevent SIGBUS on 32-bit ARM */
163 uint64_t *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, __shmid, 0);
164 /* Save size at beginning of buffer, for use with munmap */
165 *ptr = size;
166 return ptr + 1;
ec5c6b12
AC
167}
168
169static inline int shmdt (const void *__shmaddr)
170{
d8767475
OM
171 /* Find mmap size which we stored at the beginning of the buffer */
172 uint64_t *ptr = (uint64_t *)__shmaddr - 1;
173 size_t size = *ptr;
174 return munmap(ptr, size);
ec5c6b12 175}
6ca9b06d 176#endif
ec5c6b12 177
ec5c6b12
AC
178#define SPLICE_DEF_SIZE (64*1024)
179
177380ab
AC
180enum {
181 IOPRIO_CLASS_NONE,
182 IOPRIO_CLASS_RT,
183 IOPRIO_CLASS_BE,
184 IOPRIO_CLASS_IDLE,
185};
186
187enum {
188 IOPRIO_WHO_PROCESS = 1,
189 IOPRIO_WHO_PGRP,
190 IOPRIO_WHO_USER,
191};
192
193#define IOPRIO_BITS 16
194#define IOPRIO_CLASS_SHIFT 13
195
1767bd34
TK
196#define IOPRIO_MIN_PRIO 0 /* highest priority */
197#define IOPRIO_MAX_PRIO 7 /* lowest priority */
198
199#define IOPRIO_MIN_PRIO_CLASS 0
200#define IOPRIO_MAX_PRIO_CLASS 3
201
8d6e8d99 202static inline int ioprio_value(int ioprio_class, int ioprio)
a415b2cc
AC
203{
204 /*
205 * If no class is set, assume BE
206 */
8d6e8d99
DLM
207 if (!ioprio_class)
208 ioprio_class = IOPRIO_CLASS_BE;
209
210 return (ioprio_class << IOPRIO_CLASS_SHIFT) | ioprio;
211}
a415b2cc 212
03ec570f
DLM
213static inline bool ioprio_value_is_class_rt(unsigned int priority)
214{
215 return (priority >> IOPRIO_CLASS_SHIFT) == IOPRIO_CLASS_RT;
216}
217
8d6e8d99
DLM
218static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio)
219{
220 return syscall(__NR_ioprio_set, which, who,
221 ioprio_value(ioprio_class, ioprio));
a415b2cc
AC
222}
223
ec5c6b12
AC
224#ifndef BLKGETSIZE64
225#define BLKGETSIZE64 _IOR(0x12,114,size_t)
226#endif
227
228#ifndef BLKFLSBUF
229#define BLKFLSBUF _IO(0x12,97)
230#endif
231
232#ifndef BLKDISCARD
233#define BLKDISCARD _IO(0x12,119)
234#endif
235
236static inline int blockdev_invalidate_cache(struct fio_file *f)
237{
238 return ioctl(f->fd, BLKFLSBUF);
239}
240
241static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
242{
243 if (!ioctl(f->fd, BLKGETSIZE64, bytes))
244 return 0;
245
246 return errno;
247}
248
249static inline unsigned long long os_phys_mem(void)
250{
251 long pagesize, pages;
252
253 pagesize = sysconf(_SC_PAGESIZE);
254 pages = sysconf(_SC_PHYS_PAGES);
255 if (pages == -1 || pagesize == -1)
256 return 0;
257
258 return (unsigned long long) pages * (unsigned long long) pagesize;
259}
260
ec5c6b12
AC
261#ifdef O_NOATIME
262#define FIO_O_NOATIME O_NOATIME
263#else
264#define FIO_O_NOATIME 0
265#endif
266
0fa5c986
OM
267/* Check for GCC or Clang byte swap intrinsics */
268#if (__has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) \
269 && __has_builtin(__builtin_bswap64)) || (__GNUC__ > 4 \
270 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) /* fio_swapN */
271#define fio_swap16(x) __builtin_bswap16(x)
272#define fio_swap32(x) __builtin_bswap32(x)
273#define fio_swap64(x) __builtin_bswap64(x)
274#else
275#include <byteswap.h>
276#define fio_swap16(x) bswap_16(x)
277#define fio_swap32(x) bswap_32(x)
278#define fio_swap64(x) bswap_64(x)
279#endif /* fio_swapN */
ec5c6b12
AC
280
281#define CACHE_LINE_FILE \
282 "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"
283
284static inline int arch_cache_line_size(void)
285{
286 char size[32];
287 int fd, ret;
288
289 fd = open(CACHE_LINE_FILE, O_RDONLY);
290 if (fd < 0)
291 return -1;
292
293 ret = read(fd, size, sizeof(size));
294
295 close(fd);
296
297 if (ret <= 0)
298 return -1;
299 else
300 return atoi(size);
301}
302
c08ad04c 303static inline unsigned long long get_fs_free_size(const char *path)
ec5c6b12
AC
304{
305 unsigned long long ret;
306 struct statfs s;
307
308 if (statfs(path, &s) < 0)
309 return -1ULL;
310
311 ret = s.f_bsize;
312 ret *= (unsigned long long) s.f_bfree;
313 return ret;
314}
315
496b1f9e 316static inline int os_trim(struct fio_file *f, unsigned long long start,
ec5c6b12
AC
317 unsigned long long len)
318{
319 uint64_t range[2];
320
321 range[0] = start;
322 range[1] = len;
323
496b1f9e 324 if (!ioctl(f->fd, BLKDISCARD, range))
ec5c6b12
AC
325 return 0;
326
327 return errno;
328}
329
93eeb558 330#ifdef CONFIG_SCHED_IDLE
331static inline int fio_set_sched_idle(void)
332{
333 struct sched_param p = { .sched_priority = 0, };
334 return sched_setscheduler(gettid(), SCHED_IDLE, &p);
335}
336#endif
337
d2257a27
BVA
338#ifndef RWF_UNCACHED
339#define RWF_UNCACHED 0x00000040
340#endif
341
ec5c6b12 342#endif