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, &amp_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