1 /*
2 * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3 */
4
5 #include <signal.h>
6 #include <time.h>
7 #include <pthread.h>
8 #include <fcntl.h>
9 #include <inttypes.h>
10 #include <sys/prctl.h>
11 #include <sys/time.h>
12
13 #include <poll.h>
14 #include "amp_platform.h"
15 #include "aos_system.h"
16 #include "aos/kernel.h"
17 #include "aos_network.h"
18 #include "ulog/ulog.h"
19
20 #define _SYSINFO_DEVICE_NAME "aos-linux"
21 #define SYSINFO_VERSION "0.0.1"
22
23 typedef struct {
24 timer_t timer;
25 void (*cb)(void *,void *);
26 void *user_data;
27 uint32_t ms;
28 uint32_t repeat;
29 } osal_timer_inner_t;
30
aos_putchar(char c)31 void aos_putchar(char c)
32 {
33 printf("%c", c);
34 }
35
aos_reboot(void)36 void aos_reboot(void)
37 {
38 exit(0);
39 }
40
aos_get_hz(void)41 int aos_get_hz(void)
42 {
43 return 100;
44 }
45
aos_version_get(void)46 const char *aos_version_get(void)
47 {
48 return SYSINFO_VERSION;
49 }
50
51 struct targ {
52 const char *name;
53 void (*fn)(void *);
54 void *arg;
55 };
56
dfl_entry(void * arg)57 static void *dfl_entry(void *arg)
58 {
59 struct targ *targ = arg;
60 void (*fn)(void *) = targ->fn;
61 void *farg = targ->arg;
62 prctl(PR_SET_NAME, (unsigned long)targ->name, 0, 0, 0);
63 free(targ);
64
65 fn(farg);
66
67 return 0;
68 }
69
aos_task_new(const char * name,void (* fn)(void *),void * arg,size_t stack_size)70 int aos_task_new(const char *name, void (*fn)(void *), void *arg,
71 size_t stack_size)
72 {
73 int ret;
74 pthread_t th;
75 struct targ *targ = malloc(sizeof(*targ));
76 targ->name = strdup(name);
77 targ->fn = fn;
78 targ->arg = arg;
79 ret = pthread_create(&th, NULL, dfl_entry, targ);
80 if (ret == 0) {
81 ret = pthread_detach(th);
82 }
83 return ret;
84 }
85
aos_task_new_ext(aos_task_t * task,const char * name,void (* fn)(void *),void * arg,size_t stack_size,int32_t prio)86 aos_status_t aos_task_new_ext(aos_task_t *task, const char *name, void (*fn)(void *),
87 void *arg, size_t stack_size, int32_t prio)
88 {
89 return aos_task_new(name, fn, arg, stack_size);
90 }
91
aos_task_exit(int code)92 void aos_task_exit(int code)
93 {
94 pthread_exit((void *)code);
95 }
96
aos_task_name(void)97 const char *aos_task_name(void)
98 {
99 static char name[16];
100 prctl(PR_GET_NAME, (unsigned long)name, 0, 0, 0);
101 return name;
102 }
103
aos_task_key_create(aos_task_key_t * key)104 int aos_task_key_create(aos_task_key_t *key)
105 {
106 return pthread_key_create(key, NULL);
107 }
108
aos_task_key_delete(aos_task_key_t key)109 void aos_task_key_delete(aos_task_key_t key)
110 {
111 pthread_key_delete(key);
112 }
113
aos_task_setspecific(aos_task_key_t key,void * vp)114 int aos_task_setspecific(aos_task_key_t key, void *vp)
115 {
116 return pthread_setspecific(key, vp);
117 }
118
aos_task_getspecific(aos_task_key_t key)119 void *aos_task_getspecific(aos_task_key_t key)
120 {
121 return pthread_getspecific(key);
122 }
123
aos_mutex_new(aos_mutex_t * mutex)124 aos_status_t aos_mutex_new(aos_mutex_t *mutex)
125 {
126 pthread_mutex_t *mtx = malloc(sizeof(*mtx));
127 pthread_mutex_init(mtx, NULL);
128 *mutex = mtx;
129 return 0;
130 }
131
aos_mutex_free(aos_mutex_t * mutex)132 void aos_mutex_free(aos_mutex_t *mutex)
133 {
134 pthread_mutex_destroy(*mutex);
135 free(*mutex);
136 }
137
aos_mutex_lock(aos_mutex_t * mutex,unsigned int timeout)138 int aos_mutex_lock(aos_mutex_t *mutex, unsigned int timeout)
139 {
140 if (mutex) {
141 pthread_mutex_lock(*mutex);
142 }
143 return 0;
144 }
145
aos_mutex_unlock(aos_mutex_t * mutex)146 int aos_mutex_unlock(aos_mutex_t *mutex)
147 {
148 if (mutex) {
149 pthread_mutex_unlock(*mutex);
150 }
151 return 0;
152 }
153
aos_mutex_is_valid(aos_mutex_t * mutex)154 bool aos_mutex_is_valid(aos_mutex_t *mutex)
155 {
156 return *mutex != NULL;
157 }
158
159 #include <semaphore.h>
aos_sem_new(aos_sem_t * sem,uint32_t count)160 aos_status_t aos_sem_new(aos_sem_t *sem, uint32_t count)
161 {
162 sem_t *s = malloc(sizeof(*s));
163 sem_init(s, 0, count);
164 *sem = s;
165 return 0;
166 }
167
aos_sem_free(aos_sem_t * sem)168 void aos_sem_free(aos_sem_t *sem)
169 {
170 if (sem == NULL) {
171 return;
172 }
173
174 sem_destroy(*sem);
175 free(*sem);
176 }
177
aos_sem_wait(aos_sem_t * sem,unsigned int timeout)178 int aos_sem_wait(aos_sem_t *sem, unsigned int timeout)
179 {
180 int sec;
181 int nsec;
182
183 if (sem == NULL) {
184 return -EINVAL;
185 }
186
187 if (timeout == AOS_WAIT_FOREVER) {
188 return sem_wait(*sem);
189 } else if (timeout == 0) {
190 return sem_trywait(*sem);
191 }
192
193 struct timespec ts;
194 clock_gettime(CLOCK_REALTIME, &ts);
195
196 sec = timeout / 1000;
197 nsec = (timeout % 1000) * 1000000;
198
199 ts.tv_nsec += nsec;
200 sec += (ts.tv_nsec / 1000000000);
201 ts.tv_nsec %= 1000000000;
202 ts.tv_sec += sec;
203
204 return sem_timedwait(*sem, &ts);
205 }
206
aos_sem_signal(aos_sem_t * sem)207 void aos_sem_signal(aos_sem_t *sem)
208 {
209 if (sem == NULL) {
210 return;
211 }
212
213 sem_post(*sem);
214 }
215
aos_sem_is_valid(aos_sem_t * sem)216 bool aos_sem_is_valid(aos_sem_t *sem)
217 {
218 return sem && *sem != NULL;
219 }
220
aos_sem_signal_all(aos_sem_t * sem)221 void aos_sem_signal_all(aos_sem_t *sem)
222 {
223 sem_post(*sem);
224 }
225
226 struct queue {
227 int fds[2];
228 void *buf;
229 int size;
230 int msg_size;
231 };
232
aos_queue_new(aos_queue_t * queue,void * buf,size_t size,size_t max_msg)233 aos_status_t aos_queue_new(aos_queue_t *queue, void *buf, size_t size, size_t max_msg)
234 {
235 struct queue *q = malloc(sizeof(*q) + size);
236 pipe(q->fds);
237 q->buf = q + sizeof(*q);
238 q->size = size;
239 q->msg_size = max_msg;
240 *queue = q;
241 return 0;
242 }
243
aos_queue_free(aos_queue_t * queue)244 void aos_queue_free(aos_queue_t *queue)
245 {
246 struct queue *q = *queue;
247 close(q->fds[0]);
248 close(q->fds[1]);
249 free(q);
250 }
251
aos_queue_send(aos_queue_t * queue,void * msg,size_t size)252 aos_status_t aos_queue_send(aos_queue_t *queue, void *msg, size_t size)
253 {
254 struct queue *q = *queue;
255 write(q->fds[1], msg, size);
256 return 0;
257 }
258
aos_queue_recv(aos_queue_t * queue,uint32_t ms,void * msg,size_t * size)259 aos_status_t aos_queue_recv(aos_queue_t *queue, uint32_t ms, void *msg, size_t *size)
260 {
261 struct queue *q = *queue;
262 struct pollfd rfd = {
263 .fd = q->fds[0],
264 .events = POLLIN,
265 };
266
267 poll(&rfd, 1, ms);
268 if (rfd.revents & POLLIN) {
269 int len = read(q->fds[0], msg, q->msg_size);
270 *size = len;
271 return len < 0 ? -1 : 0;
272 }
273
274 return -1;
275 }
276
aos_queue_is_valid(aos_queue_t * queue)277 bool aos_queue_is_valid(aos_queue_t *queue)
278 {
279 return *queue != NULL;
280 }
281
timer_common_cb(union sigval arg)282 static void timer_common_cb(union sigval arg)
283 {
284 osal_timer_inner_t *amp_timer = (osal_timer_inner_t *)arg.sival_ptr;
285
286 if (amp_timer && amp_timer->cb) {
287 amp_timer->cb(amp_timer, amp_timer->user_data);
288 }
289 }
290
aos_timer_create(aos_timer_t * timer,void (* fn)(void *,void *),void * arg,uint32_t ms,uint32_t options)291 aos_status_t aos_timer_create(aos_timer_t *timer, void (*fn)(void *, void *), void *arg,
292 uint32_t ms, uint32_t options)
293 {
294 struct sigevent ent;
295 osal_timer_inner_t *amp_timer = NULL;
296
297 /* check parameter */
298 if (fn == NULL) {
299 return -1;
300 }
301
302 amp_timer = aos_malloc(sizeof(osal_timer_inner_t));
303
304 if (!amp_timer) {
305 return -1;
306 }
307 memset(amp_timer, 0, sizeof(osal_timer_inner_t));
308
309 /* Init */
310 memset(&ent, 0x00, sizeof(struct sigevent));
311
312 /* create a timer */
313 ent.sigev_notify = SIGEV_THREAD;
314 ent.sigev_notify_function = (void (*)(union sigval))timer_common_cb;
315 ent.sigev_value.sival_ptr = amp_timer;
316
317 if (timer_create(CLOCK_MONOTONIC, &ent, &_timer->timer) != 0) {
318 aos_free(amp_timer);
319 return -1;
320 }
321
322 amp_timer->cb = fn;
323 amp_timer->ms = ms;
324 amp_timer->user_data = arg;
325 amp_timer->repeat = (options & AOS_TIMER_REPEAT) ? 1 : 0;
326
327 *timer = amp_timer;
328
329 return 0;
330 }
331
aos_timer_free(aos_timer_t * timer)332 void aos_timer_free(aos_timer_t *timer)
333 {
334 int ret = 0;
335 osal_timer_inner_t *amp_timer = NULL;
336
337 /* check parameter */
338 if (timer == NULL) {
339 return;
340 }
341
342 amp_timer = (osal_timer_inner_t *)*timer;
343
344 if (!amp_timer)
345 return;
346
347 ret = timer_delete(amp_timer->timer);
348
349 aos_free(amp_timer);
350 return;
351 }
352
aos_timer_start(aos_timer_t * timer)353 int aos_timer_start(aos_timer_t *timer)
354 {
355 struct itimerspec ts;
356 osal_timer_inner_t *amp_timer = NULL;
357
358 /* check parameter */
359 if (timer == NULL) {
360 return -1;
361 }
362
363 amp_timer = (osal_timer_inner_t *)*timer;
364
365 if (amp_timer->repeat) {
366 /* it_value=0: stop timer */
367 ts.it_interval.tv_sec = amp_timer->ms / 1000;
368 ts.it_interval.tv_nsec = (amp_timer->ms % 1000) * 1000000;
369 } else {
370 /* it_interval=0: timer run only once */
371 ts.it_interval.tv_sec = 0;;
372 ts.it_interval.tv_nsec = 0;
373 }
374
375 /* it_value=0: stop timer */
376 ts.it_value.tv_sec = amp_timer->ms / 1000;
377 ts.it_value.tv_nsec = (amp_timer->ms % 1000) * 1000000;
378
379 return timer_settime(amp_timer->timer, 0, &ts, NULL);
380 }
381
aos_timer_stop(aos_timer_t * timer)382 int aos_timer_stop(aos_timer_t *timer)
383 {
384 struct itimerspec ts;
385 osal_timer_inner_t *amp_timer = NULL;
386
387 /* check parameter */
388 if (timer == NULL) {
389 return -1;
390 }
391
392 amp_timer = (osal_timer_inner_t *)*timer;
393
394 /* it_interval=0: timer run only once */
395 ts.it_interval.tv_sec = 0;
396 ts.it_interval.tv_nsec = 0;
397
398 /* it_value=0: stop timer */
399 ts.it_value.tv_sec = 0;
400 ts.it_value.tv_nsec = 0;
401
402 return timer_settime(amp_timer->timer, 0, &ts, NULL);
403 }
404
aos_zalloc(size_t size)405 void *aos_zalloc(size_t size)
406 {
407 return calloc(size, 1);
408 }
409
aos_malloc(size_t size)410 void *aos_malloc(size_t size)
411 {
412 return malloc(size);
413 }
414
aos_calloc(size_t nitems,size_t size)415 void *aos_calloc(size_t nitems, size_t size)
416 {
417 return calloc(nitems, size);
418 }
419
aos_realloc(void * mem,size_t size)420 void *aos_realloc(void *mem, size_t size)
421 {
422 return realloc(mem, size);
423 }
424
aos_alloc_trace(void * addr,size_t allocator)425 void aos_alloc_trace(void *addr, size_t allocator) {}
426
aos_free(void * mem)427 void aos_free(void *mem)
428 {
429 free(mem);
430 }
431
432 static struct timeval sys_start_time;
aos_now(void)433 uint64_t aos_now(void)
434 {
435 struct timeval tv;
436 long long ns;
437 gettimeofday(&tv, NULL);
438 timersub(&tv, &sys_start_time, &tv);
439 ns = tv.tv_sec * 1000000LL + tv.tv_usec;
440 return ns * 1000LL;
441 }
442
aos_now_ms(void)443 uint64_t aos_now_ms(void)
444 {
445 struct timeval tv;
446 long long ms;
447 gettimeofday(&tv, NULL);
448 timersub(&tv, &sys_start_time, &tv);
449 ms = tv.tv_sec * 1000LL + tv.tv_usec / 1000;
450 return ms;
451 }
452
aos_now_time_str(char * buffer,size_t len)453 aos_status_t aos_now_time_str(char *buffer, size_t len)
454 {
455 if (buffer != NULL && len > 0) {
456 struct timeval curTime;
457
458 gettimeofday(&curTime, NULL);
459
460 memset(buffer, 0, len);
461 strftime(buffer, len, "%m-%d %H:%M:%S", localtime(&curTime.tv_sec));
462
463 if ((int)(len - strlen(buffer) - 1) > 0) {
464 const int milli = curTime.tv_usec / 1000;
465 char msStr[8] = {0};
466 snprintf(msStr, sizeof(msStr), ".%03d", milli);
467 strncat(buffer, msStr, len - strlen(buffer) - 1);
468 }
469 }
470 return 0;
471 }
472
aos_msleep(uint32_t ms)473 void aos_msleep(uint32_t ms)
474 {
475 usleep(ms * 1000);
476 }
477
aos_init(void)478 void aos_init(void)
479 {
480 gettimeofday(&sys_start_time, NULL);
481 }
482
aos_start(void)483 void aos_start(void)
484 {
485 while (1) {
486 usleep(1000 * 1000 * 100);
487 }
488 }
489
490 #include <sys/types.h>
491 #include <dirent.h>
dumpsys_task_func(void)492 void dumpsys_task_func(void)
493 {
494 DIR *proc = opendir("/proc/self/task");
495 while (1) {
496 struct dirent *ent = readdir(proc);
497 if (!ent) {
498 break;
499 }
500 if (ent->d_name[0] == '.') {
501 continue;
502 }
503
504 char fn[128];
505 snprintf(fn, sizeof fn, "/proc/self/task/%s/comm", ent->d_name);
506 FILE *fp = fopen(fn, "r");
507 if (!fp) {
508 continue;
509 }
510 bzero(fn, sizeof fn);
511 fread(fn, sizeof(fn) - 1, 1, fp);
512 fclose(fp);
513 printf("%8s - %s", ent->d_name, fn);
514 }
515 closedir(proc);
516 }
517
aos_printf(const char * fmt,...)518 void aos_printf(const char *fmt, ...)
519 {
520 va_list args;
521
522 va_start(args, fmt);
523 vprintf(fmt, args);
524 va_end(args);
525
526 fflush(stdout);
527 }
528
aos_snprintf(char * str,const int len,const char * fmt,...)529 int aos_snprintf(char *str, const int len, const char *fmt, ...)
530 {
531 va_list args;
532 int rc;
533
534 va_start(args, fmt);
535 rc = vsnprintf(str, len, fmt, args);
536 va_end(args);
537
538 return rc;
539 }
540
aos_vsnprintf(char * str,const int len,const char * format,va_list ap)541 int aos_vsnprintf(char *str, const int len, const char *format, va_list ap)
542 {
543 return vsnprintf(str, len, format, ap);
544 }
545
aos_get_system_version(void)546 const char *aos_get_system_version(void)
547 {
548 return SYSINFO_VERSION;
549 }
550
aos_get_platform_type(void)551 const char *aos_get_platform_type(void)
552 {
553 return _SYSINFO_DEVICE_NAME;
554 }
555
aos_get_ip(char * ip)556 int aos_get_ip(char *ip)
557 {
558 return 0;
559 }
560
aos_get_mac_addr(unsigned char mac[8])561 int aos_get_mac_addr(unsigned char mac[8])
562 {
563 // TODO: ?
564 return 0;
565 }
566
567
aos_network_status_registercb(void (* cb)(int status,void *),void * arg)568 int aos_network_status_registercb(void (*cb)(int status, void *), void *arg)
569 {
570 // TODO: ?
571 return 0;
572 }
573
aos_get_network_status(void)574 int aos_get_network_status(void)
575 {
576 // TODO: ?
577 return 1;
578 }
579
aos_get_device_name(void)580 const char *aos_get_device_name(void)
581 {
582 return "linux";
583 }
584
amp_heap_memory_info(amp_heap_info_t * heap_info)585 int amp_heap_memory_info(amp_heap_info_t *heap_info)
586 {
587 return 0;
588 }
589
aos_system_init(void)590 int aos_system_init(void)
591 {
592 return 0;
593 }
594
aos_get_module_hardware_version(void)595 const char *aos_get_module_hardware_version(void)
596 {
597 return "Module_Hardware_version";
598 }
599
aos_get_module_software_version(void)600 const char *aos_get_module_software_version(void)
601 {
602 return "Module_Software_version";
603 }
604
aos_rand(void)605 int32_t aos_rand(void)
606 {
607 return rand();
608 }
609
aos_srand(uint32_t seed)610 void aos_srand(uint32_t seed)
611 {
612 srand(seed);
613 }
614