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