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