os: introduce ioprio_value() helper
[fio.git] / os / os-android.h
... / ...
CommitLineData
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
83static 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__
97static 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
106static 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
127error:
128 close(fd);
129 return ret;
130}
131#endif
132
133static 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
143static 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
154enum {
155 IOPRIO_CLASS_NONE,
156 IOPRIO_CLASS_RT,
157 IOPRIO_CLASS_BE,
158 IOPRIO_CLASS_IDLE,
159};
160
161enum {
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
176static inline int ioprio_value(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 return (ioprio_class << IOPRIO_CLASS_SHIFT) | ioprio;
185}
186
187static inline int ioprio_set(int which, int who, int ioprio_class, int ioprio)
188{
189 return syscall(__NR_ioprio_set, which, who,
190 ioprio_value(ioprio_class, ioprio));
191}
192
193#ifndef BLKGETSIZE64
194#define BLKGETSIZE64 _IOR(0x12,114,size_t)
195#endif
196
197#ifndef BLKFLSBUF
198#define BLKFLSBUF _IO(0x12,97)
199#endif
200
201#ifndef BLKDISCARD
202#define BLKDISCARD _IO(0x12,119)
203#endif
204
205static inline int blockdev_invalidate_cache(struct fio_file *f)
206{
207 return ioctl(f->fd, BLKFLSBUF);
208}
209
210static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
211{
212 if (!ioctl(f->fd, BLKGETSIZE64, bytes))
213 return 0;
214
215 return errno;
216}
217
218static inline unsigned long long os_phys_mem(void)
219{
220 long pagesize, pages;
221
222 pagesize = sysconf(_SC_PAGESIZE);
223 pages = sysconf(_SC_PHYS_PAGES);
224 if (pages == -1 || pagesize == -1)
225 return 0;
226
227 return (unsigned long long) pages * (unsigned long long) pagesize;
228}
229
230#ifdef O_NOATIME
231#define FIO_O_NOATIME O_NOATIME
232#else
233#define FIO_O_NOATIME 0
234#endif
235
236/* Check for GCC or Clang byte swap intrinsics */
237#if (__has_builtin(__builtin_bswap16) && __has_builtin(__builtin_bswap32) \
238 && __has_builtin(__builtin_bswap64)) || (__GNUC__ > 4 \
239 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) /* fio_swapN */
240#define fio_swap16(x) __builtin_bswap16(x)
241#define fio_swap32(x) __builtin_bswap32(x)
242#define fio_swap64(x) __builtin_bswap64(x)
243#else
244#include <byteswap.h>
245#define fio_swap16(x) bswap_16(x)
246#define fio_swap32(x) bswap_32(x)
247#define fio_swap64(x) bswap_64(x)
248#endif /* fio_swapN */
249
250#define CACHE_LINE_FILE \
251 "/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size"
252
253static inline int arch_cache_line_size(void)
254{
255 char size[32];
256 int fd, ret;
257
258 fd = open(CACHE_LINE_FILE, O_RDONLY);
259 if (fd < 0)
260 return -1;
261
262 ret = read(fd, size, sizeof(size));
263
264 close(fd);
265
266 if (ret <= 0)
267 return -1;
268 else
269 return atoi(size);
270}
271
272static inline unsigned long long get_fs_free_size(const char *path)
273{
274 unsigned long long ret;
275 struct statfs s;
276
277 if (statfs(path, &s) < 0)
278 return -1ULL;
279
280 ret = s.f_bsize;
281 ret *= (unsigned long long) s.f_bfree;
282 return ret;
283}
284
285static inline int os_trim(struct fio_file *f, unsigned long long start,
286 unsigned long long len)
287{
288 uint64_t range[2];
289
290 range[0] = start;
291 range[1] = len;
292
293 if (!ioctl(f->fd, BLKDISCARD, range))
294 return 0;
295
296 return errno;
297}
298
299#ifdef CONFIG_SCHED_IDLE
300static inline int fio_set_sched_idle(void)
301{
302 struct sched_param p = { .sched_priority = 0, };
303 return sched_setscheduler(gettid(), SCHED_IDLE, &p);
304}
305#endif
306
307#endif