Introduce plat_get_skin_dir and update plat_get_root_dir functions
[libpicofe.git] / linux / plat.c
CommitLineData
957a9eac 1/*
f89d8471 2 * (C) GraÅžvydas "notaz" Ignotas, 2008-2012
957a9eac 3 *
4 * This work is licensed under the terms of any of these licenses
5 * (at your option):
6 * - GNU GPL, version 2 or later.
7 * - GNU LGPL, version 2.1 or later.
f89d8471 8 * - MAME license.
957a9eac 9 * See the COPYING file in the top-level directory.
10 */
11
705bdf63 12#define _GNU_SOURCE 1
4ab30ad4 13#include <stdio.h>
d2f29611 14#include <string.h>
2b9f9c51 15#include <stdarg.h>
049a6b3e 16#include <dirent.h>
4ab30ad4 17#include <sys/time.h>
18#include <time.h>
19#include <unistd.h>
997b2e4f 20#include <sys/mman.h>
ca69c3e5 21#include <errno.h>
c52e6628 22#include <sys/stat.h>
4ab30ad4 23
a86e9a3e 24#include "../plat.h"
049a6b3e 25
ca69c3e5 26/* XXX: maybe unhardcode pagesize? */
27#define HUGETLB_PAGESIZE (2 * 1024 * 1024)
28#define HUGETLB_THRESHOLD (HUGETLB_PAGESIZE / 2)
29#ifndef MAP_HUGETLB
30#define MAP_HUGETLB 0x40000 /* arch specific */
31#endif
32
049a6b3e 33
34int plat_is_dir(const char *path)
35{
36 DIR *dir;
37 if ((dir = opendir(path))) {
38 closedir(dir);
39 return 1;
40 }
41 return 0;
42}
43
c52e6628 44static int plat_get_data_dir(char *dst, int len)
d2f29611 45{
c52e6628
PC
46#ifdef PICO_DATA_DIR
47 memcpy(dst, PICO_DATA_DIR, sizeof PICO_DATA_DIR);
48 return sizeof(PICO_DATA_DIR) - 1;
49#else
50 int j, ret = readlink("/proc/self/exe", dst, len - 1);
2b9f9c51 51 if (ret < 0) {
52 perror("readlink");
53 ret = 0;
54 }
55 dst[ret] = 0;
d2f29611 56
c52e6628 57 for (j = ret - 1; j > 0; j--)
2b9f9c51 58 if (dst[j] == '/') {
59 dst[++j] = 0;
60 break;
61 }
f35e50ef 62 return j;
c52e6628
PC
63#endif
64}
65
66int plat_get_skin_dir(char *dst, int len)
67{
68 int ret = plat_get_data_dir(dst, len);
69 if (ret < 0)
70 return ret;
71
72 memcpy(dst + ret, "skin/", sizeof "skin/");
73 return ret + sizeof("skin/") - 1;
74}
75
76#ifndef PICO_HOME_DIR
77#define PICO_HOME_DIR "/.picodrive/"
78#endif
79int plat_get_root_dir(char *dst, int len)
80{
81#if defined(__GP2X__) || defined(PANDORA)
82 return plat_get_data_dir(dst, len);
83#else
84 char *home = getenv("HOME");
85 size_t nb = strlen(home);
86
87 memcpy(dst, home, nb);
88 memcpy(dst + nb, PICO_HOME_DIR, sizeof PICO_HOME_DIR);
89 mkdir(dst, 0755);
90 return nb + sizeof(PICO_HOME_DIR) - 1;
91#endif
d2f29611 92}
93
b5bfb864 94#ifdef __GP2X__
95/* Wiz has a borked gettimeofday().. */
1eb704b6 96#define plat_get_ticks_ms plat_get_ticks_ms_good
97#define plat_get_ticks_us plat_get_ticks_us_good
b5bfb864 98#endif
99
4ab30ad4 100unsigned int plat_get_ticks_ms(void)
101{
102 struct timeval tv;
103 unsigned int ret;
104
105 gettimeofday(&tv, NULL);
106
107 ret = (unsigned)tv.tv_sec * 1000;
b5bfb864 108 /* approximate /= 1000 */
4ab30ad4 109 ret += ((unsigned)tv.tv_usec * 4195) >> 22;
110
111 return ret;
112}
113
b5bfb864 114unsigned int plat_get_ticks_us(void)
115{
116 struct timeval tv;
117 unsigned int ret;
118
119 gettimeofday(&tv, NULL);
120
121 ret = (unsigned)tv.tv_sec * 1000000;
122 ret += (unsigned)tv.tv_usec;
123
124 return ret;
125}
126
4ab30ad4 127void plat_sleep_ms(int ms)
128{
129 usleep(ms * 1000);
130}
131
132int plat_wait_event(int *fds_hnds, int count, int timeout_ms)
133{
134 struct timeval tv, *timeout = NULL;
135 int i, ret, fdmax = -1;
136 fd_set fdset;
137
138 if (timeout_ms >= 0) {
139 tv.tv_sec = timeout_ms / 1000;
140 tv.tv_usec = (timeout_ms % 1000) * 1000;
141 timeout = &tv;
142 }
143
144 FD_ZERO(&fdset);
145 for (i = 0; i < count; i++) {
146 if (fds_hnds[i] > fdmax) fdmax = fds_hnds[i];
147 FD_SET(fds_hnds[i], &fdset);
148 }
149
150 ret = select(fdmax + 1, &fdset, NULL, NULL, timeout);
151 if (ret == -1)
152 {
153 perror("plat_wait_event: select failed");
154 sleep(1);
155 return -1;
156 }
157
158 if (ret == 0)
159 return -1; /* timeout */
160
161 ret = -1;
162 for (i = 0; i < count; i++)
163 if (FD_ISSET(fds_hnds[i], &fdset))
164 ret = fds_hnds[i];
165
166 return ret;
167}
168
ca69c3e5 169void *plat_mmap(unsigned long addr, size_t size, int need_exec, int is_fixed)
997b2e4f 170{
f4750ef3 171 static int hugetlb_warned;
ca69c3e5 172 int prot = PROT_READ | PROT_WRITE;
173 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
997b2e4f 174 void *req, *ret;
1ed48049 175
997b2e4f 176 req = (void *)addr;
ca69c3e5 177 if (need_exec)
178 prot |= PROT_EXEC;
179 if (is_fixed)
180 flags |= MAP_FIXED;
f4750ef3 181 if (size >= HUGETLB_THRESHOLD)
ca69c3e5 182 flags |= MAP_HUGETLB;
183
184 ret = mmap(req, size, prot, flags, -1, 0);
185 if (ret == MAP_FAILED && (flags & MAP_HUGETLB)) {
f4750ef3 186 if (!hugetlb_warned) {
187 fprintf(stderr,
188 "warning: failed to do hugetlb mmap (%p, %zu): %d\n",
189 req, size, errno);
190 hugetlb_warned = 1;
191 }
ca69c3e5 192 flags &= ~MAP_HUGETLB;
193 ret = mmap(req, size, prot, flags, -1, 0);
194 }
997b2e4f 195 if (ret == MAP_FAILED)
196 return NULL;
ca69c3e5 197
198 if (req != NULL && ret != req)
199 fprintf(stderr,
200 "warning: mmaped to %p, requested %p\n", ret, req);
997b2e4f 201
202 return ret;
203}
204
1ed48049 205void *plat_mremap(void *ptr, size_t oldsize, size_t newsize)
206{
207 void *ret;
208
209 ret = mremap(ptr, oldsize, newsize, MREMAP_MAYMOVE);
210 if (ret == MAP_FAILED)
211 return NULL;
212 if (ret != ptr)
213 printf("warning: mremap moved: %p -> %p\n", ptr, ret);
214
215 return ret;
216}
217
997b2e4f 218void plat_munmap(void *ptr, size_t size)
219{
ca69c3e5 220 int ret;
221
222 ret = munmap(ptr, size);
223 if (ret != 0 && (size & (HUGETLB_PAGESIZE - 1))) {
224 // prehaps an autorounded hugetlb mapping?
225 size = (size + HUGETLB_PAGESIZE - 1) & ~(HUGETLB_PAGESIZE - 1);
226 ret = munmap(ptr, size);
227 }
228 if (ret != 0) {
229 fprintf(stderr,
230 "munmap(%p, %zu) failed: %d\n", ptr, size, errno);
231 }
997b2e4f 232}
233
6282e17e
GI
234int plat_mem_set_exec(void *ptr, size_t size)
235{
236 int ret = mprotect(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC);
237 if (ret != 0)
238 fprintf(stderr, "mprotect(%p, %zd) failed: %d\n",
239 ptr, size, errno);
240
241 return ret;
242}
243
2b9f9c51 244/* lprintf */
245void lprintf(const char *fmt, ...)
246{
247 va_list vl;
248
249 va_start(vl, fmt);
250 vprintf(fmt, vl);
251 va_end(vl);
252}
253