1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 
5 #include "amp_platform.h"
6 #include "amp_defines.h"
7 #include "amp_config.h"
8 #include "aos_system.h"
9 #include "amp_task.h"
10 #include "amp_list.h"
11 
12 #define MOD_STR                 "AMP_TASK"
13 #define AMP_MSGQ_WAITIME        (2000)
14 #define AMP_MSGQ_MAX_NUM        64
15 
16 typedef struct {
17     dlist_t node;
18     void (*callback)(void);
19 } amp_source_node_t;
20 
21 static dlist_t g_sources_list = AMP_DLIST_HEAD_INIT(g_sources_list);
22 
23 static aos_queue_t amp_task_mq = NULL; /* JSEngine message queue */
24 static aos_mutex_t amp_task_mutex   = NULL; /* JSEngine mutex */
25 
26 static void (*g_task_msg_notify)(int (*msg_handler)(void));
27 
amp_module_free(void)28 void amp_module_free(void)
29 {
30     amp_source_node_t *source_node;
31     dlist_t *temp;
32 
33     dlist_for_each_entry_safe(&g_sources_list, temp, source_node, amp_source_node_t, node) {
34         source_node->callback();
35         dlist_del(&source_node->node);
36         amp_free(source_node);
37     }
38 }
39 
amp_module_free_register(void (* callback)(void))40 int32_t amp_module_free_register(void (*callback)(void))
41 {
42     amp_source_node_t *source_node;
43 
44     if (!callback) {
45         return -1;
46     }
47 
48     source_node = amp_malloc(sizeof(amp_source_node_t));
49     if (!source_node) {
50         return -1;
51     }
52     source_node->callback = callback;
53     dlist_add_tail(&source_node->node, &g_sources_list);
54     return 0;
55 }
56 
amp_task_yield(uint32_t timeout)57 int32_t amp_task_yield(uint32_t timeout)
58 {
59     int32_t ret = 0;
60     size_t revsize;
61 
62     amp_task_msg_t amp_msg;
63 
64     memset(&amp_msg, 0, sizeof(amp_msg));
65     amp_msg.type = AMP_TASK_MSG_TYPE_MAX;
66 
67     if ((ret = aos_queue_recv(&amp_task_mq, timeout, &amp_msg, &revsize)) != 0) {
68         return -1;
69     }
70 
71     if (amp_msg.type == AMP_TASK_MSG_CALLBACK) {
72         amp_msg.callback(amp_msg.param);
73     }
74 
75     else if (amp_msg.type == AMP_TASK_MSG_EXIT) {
76         return 1;
77     }
78 
79     return 0;
80 }
81 
amp_task_yield_nowait(void)82 static int amp_task_yield_nowait(void)
83 {
84     return amp_task_yield(0);
85 }
86 
amp_task_timer_cb_handler(void * timer,void * arg)87 static void amp_task_timer_cb_handler(void *timer, void *arg)
88 {
89     amp_task_msg_t *p_amp_msg = (amp_task_msg_t *)arg;
90 
91     if (amp_task_mq == NULL) {
92         return;
93     }
94 
95     aos_queue_send(&amp_task_mq, p_amp_msg, sizeof(amp_task_msg_t));
96 }
97 
amp_task_timer_action(uint32_t ms,amp_engine_call_t action,void * arg,amp_timer_type_t type,void ** timer_msg)98 aos_timer_t *amp_task_timer_action(uint32_t ms, amp_engine_call_t action, void *arg, amp_timer_type_t type,
99                                    void **timer_msg)
100 {
101     int ret = -1;
102 
103     aos_timer_t *timer_id = (aos_timer_t *)amp_malloc(sizeof(aos_timer_t));
104     if (timer_id == NULL) {
105         return NULL;
106     }
107 
108     amp_task_msg_t *p_param = (amp_task_msg_t *)amp_calloc(1, sizeof(amp_task_msg_t));
109 
110     if (!p_param)
111         return NULL;
112 
113     *timer_msg = p_param;
114 
115     if (amp_task_mq == NULL) {
116         goto fail;
117     }
118 
119     p_param->callback = action;
120     p_param->param = arg;
121     p_param->type = AMP_TASK_MSG_CALLBACK;
122 
123     if (type == AMP_TIMER_REPEAT) {
124         ret = aos_timer_create(timer_id, amp_task_timer_cb_handler, p_param, ms, AOS_TIMER_REPEAT);
125     } else if (type == AMP_TIMER_ONCE) {
126         ret = aos_timer_create(timer_id, amp_task_timer_cb_handler, p_param, ms, 0);
127     } else {
128         goto fail;
129     }
130 
131     if (ret != 0)
132         goto fail;
133 
134     ret = aos_timer_start(timer_id);
135     if (ret) {
136         aos_timer_free(timer_id);
137         goto fail;
138     }
139 
140     return timer_id;
141 
142 fail:
143     amp_free(p_param);
144     amp_free(timer_id);
145     return NULL;
146 }
147 
amp_task_schedule_call(amp_engine_call_t call,void * arg)148 int32_t amp_task_schedule_call(amp_engine_call_t call, void *arg)
149 {
150     amp_task_msg_t msg_buf;
151     amp_task_msg_t *p_param = &msg_buf;
152 
153     if (amp_task_mq == NULL) {
154         return -1;
155     }
156 
157     p_param->callback = call;
158     p_param->param = arg;
159     p_param->type = AMP_TASK_MSG_CALLBACK;
160     if (amp_task_mq == NULL) {
161         amp_warn(MOD_STR, "amp_task_mq has not been initlized");
162         return -1;
163     }
164     aos_queue_send(&amp_task_mq, p_param, sizeof(amp_task_msg_t));
165 #ifdef HAASUI_AMP_BUILD
166     if (g_task_msg_notify)
167         g_task_msg_notify(amp_task_yield_nowait);
168 #endif
169     return 0;
170 }
171 
amp_task_msg_register(void (* msg_notify)(int (* msg_handler)(void)))172 void amp_task_msg_register(void (*msg_notify)(int (*msg_handler)(void)))
173 {
174     g_task_msg_notify = msg_notify;
175 }
176 
amp_task_exit_call(amp_engine_call_t call,void * arg)177 int32_t amp_task_exit_call(amp_engine_call_t call, void *arg)
178 {
179     amp_task_msg_t msg_buf;
180     amp_task_msg_t *p_param = &msg_buf;
181 
182     memset(p_param, 0, sizeof(amp_task_msg_t));
183     p_param->callback = call;
184     p_param->param = arg;
185     p_param->type = AMP_TASK_MSG_EXIT;
186     if (amp_task_mq == NULL) {
187         amp_warn(MOD_STR, "amp_task_mq has not been initlized");
188         return -1;
189     }
190     aos_mutex_lock(&amp_task_mutex, AOS_WAIT_FOREVER);
191     aos_queue_send(&amp_task_mq, p_param, sizeof(amp_task_msg_t));
192     aos_mutex_unlock(&amp_task_mutex);
193     return 0;
194 }
195 
amp_task_init()196 int32_t amp_task_init()
197 {
198     if (amp_task_mq != NULL) {
199         return 0;
200     }
201 
202     if (aos_queue_new(&amp_task_mq, NULL, AMP_MSGQ_MAX_NUM * sizeof(amp_task_msg_t), sizeof(amp_task_msg_t)) != 0) {
203         amp_error(MOD_STR, "create messageQ error");
204         return -1;
205     }
206     if (aos_mutex_new(&amp_task_mutex) != 0) {
207         amp_error(MOD_STR, "create mutex error");
208         return -1;
209     }
210 
211     amp_debug(MOD_STR, "jsengine task init");
212     return 0;
213 }
214 
amp_task_deinit()215 int32_t amp_task_deinit()
216 {
217     if (amp_task_mq != NULL) {
218         aos_queue_free(&amp_task_mq);
219         amp_task_mq = NULL;
220     }
221 
222     if (amp_task_mutex != NULL) {
223         aos_mutex_free(&amp_task_mutex);
224         amp_task_mutex = NULL;
225     }
226 
227     /* free all jsengine heap */
228     jsengine_exit();
229 
230     amp_debug(MOD_STR, "jsengine task free");
231     return 0;
232 }
233