• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 /* ****************************************************************************
20   1 头文件包含
21 **************************************************************************** */
22 #include "frw_event_sched.h"
23 #include "oam_ext_if.h"
24 #include "frw_event.h"
25 
26 #ifdef __cplusplus
27 #if __cplusplus
28 extern "C" {
29 #endif
30 #endif
31 
32 /* ****************************************************************************
33   2 宏定义
34 **************************************************************************** */
35 /* ****************************************************************************
36   3 函数原型声明
37 **************************************************************************** */
38 /* ****************************************************************************
39   4 全局变量定义
40 **************************************************************************** */
41 /* ****************************************************************************
42   5 函数实现
43 **************************************************************************** */
44 /* ****************************************************************************
45  功能描述  : 重置调度队列上各个事件队列的权重计数器
46  输入参数  : pst_sched_queue: 调度队列指针
47 **************************************************************************** */
frw_event_sched_reset_weight(frw_event_sched_queue_stru * sched_queue)48 hi_void frw_event_sched_reset_weight(frw_event_sched_queue_stru *sched_queue)
49 {
50     hi_list *list = HI_NULL;
51     frw_event_queue_stru *event_queue = HI_NULL;
52 
53     /* 遍历整个调度链表 */
54     hi_list_for_each(list, &sched_queue->head) {
55         /* 获取调度链表中的一个事件队列 */
56         event_queue = hi_list_entry(list, frw_event_queue_stru, list);
57         /* 只是重置恢复状态VAP的权重值 */
58         if (event_queue->vap_state == FRW_VAP_STATE_RESUME) {
59             /* 重置事件队列的权重计数器 */
60             event_queue->weight_cnt = event_queue->weight;
61             /* 更新调度队列上的总权重计数器 */
62             sched_queue->total_weight_cnt += event_queue->weight;
63         }
64     }
65 }
66 
67 /* ****************************************************************************
68  功能描述  : 事件调度入口函数
69 
70  修改历史      :
71   1.日    期   : 2012年10月17日
72     作    者   : HiSilicon
73     修改内容   : 新生成函数
74 
75 **************************************************************************** */
frw_event_schedule(frw_event_sched_queue_stru * sched_queue)76 hi_void *frw_event_schedule(frw_event_sched_queue_stru *sched_queue)
77 {
78     hi_void                     *event = HI_NULL;
79     frw_event_sched_queue_stru  *queue = HI_NULL;
80 
81     /* 遍历全部调度类 */
82     queue = &sched_queue[FRW_SCHED_POLICY_HI];
83 
84     /* 如果高优先级调度队列为空,则取下一个调度队列 */
85     if (!hi_is_list_empty(&queue->head)) {
86         /* 从调度类中挑选下一个待处理的事件 */
87         event = frw_event_sched_pick_next_event_queue_wrr(queue);
88         if (event != HI_NULL) {
89             return event;
90         }
91     }
92 
93     queue = &sched_queue[FRW_SCHED_POLICY_NORMAL];
94 
95     /* 如果普通优先级调度队列为空,则取下一个调度队列 */
96     if (!hi_is_list_empty(&queue->head)) {
97         /* 从调度类中挑选下一个待处理的事件 */
98         event = frw_event_sched_pick_next_event_queue_wrr(queue);
99         if (event != HI_NULL) {
100             return event;
101         }
102     }
103 
104     return HI_NULL;
105 }
106 /* ****************************************************************************
107  功能描述  : 从调度队列删除一个事件队列
108  输入参数  : pst_sched_queue: 调度队列指针
109              pst_event_queue: 事件队列指针
110 
111  修改历史      :
112   1.日    期   : 2015年3月31日
113     作    者   : HiSilicon
114     修改内容   : 新生成函数
115 
116 *****************************************************************************/
frw_event_sched_deactivate_queue_no_lock(frw_event_sched_queue_stru * sched_queue,frw_event_queue_stru * event_queue)117 hi_void frw_event_sched_deactivate_queue_no_lock(frw_event_sched_queue_stru  *sched_queue,
118                                                  frw_event_queue_stru  *event_queue)
119 {
120     if (event_queue->queue.element_cnt != 0) {
121         return;
122     }
123 
124     /* 更新调度队列上的总权重计数器 */
125     sched_queue->total_weight_cnt -= event_queue->weight_cnt;
126     /* 将事件队列的权重计数器清零 */
127     event_queue->weight_cnt = 0;
128     /* 将事件队列从调度链表上删除 */
129     hi_list_delete(&event_queue->list);
130     /* 将事件队列置为不活跃状态 */
131     event_queue->state = FRW_EVENT_QUEUE_STATE_INACTIVE;
132 }
133 
134 /* ****************************************************************************
135  功能描述  : 向调度队列添加一个新的事件队列
136  输入参数  : past_sched_queue: 调度队列指针
137              pst_event_queue : 事件队列指针
138 
139  修改历史      :
140   1.日    期   : 2012年11月5日
141     作    者   : HiSilicon
142     修改内容   : 新生成函数
143 
144   2.日    期   : 2015年4月23日
145     作    者   : HiSilicon
146     修改内容   : 封装为不加锁接口,保持接口对称性,供加锁接口调用
147 *****************************************************************************/
frw_event_sched_activate_queue_no_lock(frw_event_sched_queue_stru * sched_queue,frw_event_queue_stru * event_queue)148 hi_u32 frw_event_sched_activate_queue_no_lock(frw_event_sched_queue_stru   *sched_queue,
149                                               frw_event_queue_stru         *event_queue)
150 {
151     /* 如果事件队列已经在可执行队列上(处于激活状态),则直接返回成功 */
152     if (event_queue->state == FRW_EVENT_QUEUE_STATE_ACTIVE) {
153         return HI_SUCCESS;
154     }
155 
156     /* 置为事件队列的权重计数器 */
157     event_queue->weight_cnt = event_queue->weight;
158     /* 更新调度队列上的总权重计数器 */
159     sched_queue->total_weight_cnt += event_queue->weight_cnt;
160 
161     /* 将事件队列加入调度链表的末尾 */
162     hi_list_tail_insert(&event_queue->list, &sched_queue->head);
163 
164     /* 将事件队列置为激活状态 */
165     event_queue->state = FRW_EVENT_QUEUE_STATE_ACTIVE;
166 
167     return HI_SUCCESS;
168 }
169 
170 /* ****************************************************************************
171  功能描述  : 调度器初始化
172  输入参数  : pst_sched_queue: 调度队列指针
173 
174  修改历史      :
175   1.日    期   : 2012年11月5日
176     作    者   : HiSilicon
177     修改内容   : 新生成函数
178 **************************************************************************** */
frw_event_sched_init(frw_event_sched_queue_stru * sched_queue)179 hi_u32 frw_event_sched_init(frw_event_sched_queue_stru *sched_queue)
180 {
181     /* 初始化锁 */
182     /* 初始化调度队列总权重计数器 */
183     sched_queue->total_weight_cnt = 0;
184 
185     /* 初始化调度链表头 */
186     hi_list_init(&sched_queue->head);
187     oal_spin_lock_init(&sched_queue->st_lock);
188 
189     return HI_SUCCESS;
190 }
191 
192 /* ****************************************************************************
193  功能描述  : 设置事件队列参数
194  输入参数  : pst_prio_queue: 事件队列指针
195              us_weight     : 队列权重
196              en_policy     : 队列调度策略
197              en_state      : 事件队列状态
198 *****************************************************************************/
frw_event_queue_set(frw_event_queue_stru * event_queue,hi_u8 weight,frw_sched_policy_enum_uint8 policy,frw_event_queue_state_enum_uint8 state)199 hi_void frw_event_queue_set(frw_event_queue_stru *event_queue, hi_u8 weight,
200                             frw_sched_policy_enum_uint8 policy, frw_event_queue_state_enum_uint8 state)
201 {
202     event_queue->weight     = weight;
203     event_queue->weight_cnt = 0;
204     event_queue->policy     = policy;
205     event_queue->state      = state;
206     event_queue->vap_state  = FRW_VAP_STATE_RESUME;
207 }
208 
209 /* ****************************************************************************
210  功能描述  : 队列初始化, uc_max_events必须是2的整数次幂
211  输入参数  : pst_queue      : 队列指针
212              uc_max_events: 最大元素个数
213 **************************************************************************** */
oal_queue_init(oal_queue_stru * queue,hi_u8 max_events)214 hi_u32 oal_queue_init(oal_queue_stru *queue, hi_u8 max_events)
215 {
216     hi_u32 *pul_buf = HI_NULL;
217 
218     if (max_events == 0) {
219         return HI_SUCCESS;
220     } else {
221         if (oal_unlikely(oal_is_not_pow_of_2(max_events))) {
222             return HI_ERR_CODE_CONFIG_UNSUPPORT;
223         }
224 
225         pul_buf = (hi_u32 *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, (hi_u16)(max_events * sizeof(hi_u32)));
226         if (oal_unlikely(pul_buf == HI_NULL)) {
227             return HI_ERR_CODE_ALLOC_MEM_FAIL;
228         }
229         /* 安全编程规则6.6例外(3)从堆中分配内存后,赋予初值 */
230         memset_s(pul_buf, max_events * sizeof(hi_u32), 0, max_events * sizeof(hi_u32));
231         oal_queue_set(queue, pul_buf, max_events);
232 
233         return HI_SUCCESS;
234     }
235 }
236 
237 /* ****************************************************************************
238  功能描述  : 事件队列初始化
239  输入参数  : pst_event_queue: 事件队列指针
240              us_weight      : 队列权重
241              en_policy      : 队列调度策略
242              en_state       : 事件队列状态
243              us_max_events  : 最大事件个数
244 
245  修改历史      :
246   1.日    期   : 2012年10月17日
247     作    者   : HiSilicon
248     修改内容   : 新生成函数
249 
250 *****************************************************************************/
frw_event_queue_init(frw_event_queue_stru * event_queue,hi_u8 weight,frw_sched_policy_enum_uint8 policy,frw_event_queue_state_enum_uint8 state,hi_u8 max_events)251 hi_u32 frw_event_queue_init(frw_event_queue_stru *event_queue, hi_u8 weight,
252                             frw_sched_policy_enum_uint8 policy,
253                             frw_event_queue_state_enum_uint8 state, hi_u8 max_events)
254 {
255     hi_u32 ret;
256 
257     /* 初始化锁 */
258     oal_spin_lock_init(&event_queue->st_lock);
259     ret = oal_queue_init(&event_queue->queue, max_events);
260     if (oal_unlikely(ret != HI_SUCCESS)) {
261         oam_warning_log1(0, OAM_SF_FRW, "{frw_event_queue_init:: OAL_QUEUE_INIT return != HI_SUCCESS! %d}", ret);
262         frw_event_queue_set(event_queue, 0, FRW_SCHED_POLICY_BUTT, FRW_EVENT_QUEUE_STATE_INACTIVE);
263 
264         return ret;
265     }
266 
267     frw_event_queue_set(event_queue, weight, policy, state);
268 
269     return HI_SUCCESS;
270 }
271 
272 /* ****************************************************************************
273  功能描述  : 销毁事件队列
274  输入参数  : pst_event_queue: 事件队列指针
275 
276  修改历史      :
277   1.日    期   : 2012年10月18日
278     作    者   : HiSilicon
279     修改内容   : 新生成函数
280 
281 **************************************************************************** */
frw_event_queue_destroy(frw_event_queue_stru * event_queue)282 hi_void frw_event_queue_destroy(frw_event_queue_stru *event_queue)
283 {
284     oal_queue_destroy(&event_queue->queue);
285 
286     frw_event_queue_set(event_queue, 0, FRW_SCHED_POLICY_BUTT, FRW_EVENT_QUEUE_STATE_INACTIVE);
287 }
288 
289 /* ****************************************************************************
290  功能描述  : 从调度类中挑选下一个待处理的事件
291 
292  修改历史      :
293   1.日    期   : 2012年10月17日
294     作    者   : HiSilicon
295     修改内容   : 新生成函数
296 
297 **************************************************************************** */
frw_event_sched_pick_next_event_queue_wrr(frw_event_sched_queue_stru * sched_queue)298 hi_void *frw_event_sched_pick_next_event_queue_wrr(frw_event_sched_queue_stru *sched_queue)
299 {
300     hi_list                   *list = HI_NULL;
301     frw_event_queue_stru      *event_queue = HI_NULL;
302     hi_void                   *event = HI_NULL;
303     unsigned long             flag;
304     unsigned long             irq_flag;
305 
306     oal_spin_lock_irq_save(&sched_queue->st_lock, &flag);
307 
308     /* 遍历整个调度链表 */
309     hi_list_for_each(list, &sched_queue->head) {
310         event_queue = hi_list_entry(list, frw_event_queue_stru, list);
311         oal_spin_lock_irq_save(&event_queue->st_lock, &irq_flag);
312         /* 如果事件队列的vap_state为暂停,则跳过,继续挑选下一个事件队列 */
313         if (event_queue->vap_state == FRW_VAP_STATE_PAUSE) {
314             oal_spin_unlock_irq_restore(&event_queue->st_lock, &irq_flag);
315             continue;
316         }
317 
318         /* 如果事件队列的权重计数器为0,则挑选下一个事件队列 */
319         if (event_queue->weight_cnt == 0) {
320             oal_spin_unlock_irq_restore(&event_queue->st_lock, &irq_flag);
321             continue;
322         }
323 
324         /* 更新事件队列权重计数器 */
325         event_queue->weight_cnt--;
326         /* 更新调度队列的总权重计数器 */
327         sched_queue->total_weight_cnt--;
328         /* 从事件队列中取出一个事件 */
329         event = (frw_event_mem_stru *)oal_queue_dequeue(&event_queue->queue);
330 
331         /* 如果事件队列变空,需要将其从调度队列上删除,并将事件队列状态置为不活跃(不可被调度) */
332         frw_event_sched_deactivate_queue_no_lock(sched_queue, event_queue);
333         /* } */
334         oal_spin_unlock_irq_restore(&event_queue->st_lock, &irq_flag);
335         break;
336     }
337 
338     /* 如果调度队列的总权重计数器为0,则需要重置调度队列上各个事件队列的权重计数器 */
339     if (sched_queue->total_weight_cnt == 0) {
340         frw_event_sched_reset_weight(sched_queue);
341     }
342 
343     oal_spin_unlock_irq_restore(&sched_queue->st_lock, &flag);
344     return event;
345 }
346 
347 /* ****************************************************************************
348  功能描述  : 从调度队列删除一个事件队列
349  输入参数  : pst_sched_queue: 调度队列指针
350              pst_event_queue: 事件队列指针
351 
352  修改历史      :
353   1.日    期   : 2012年11月12日
354     作    者   : HiSilicon
355     修改内容   : 新生成函数
356 
357 **************************************************************************** */
frw_event_sched_deactivate_queue(frw_event_sched_queue_stru * sched_queue,frw_event_queue_stru * event_queue)358 hi_void frw_event_sched_deactivate_queue(frw_event_sched_queue_stru *sched_queue, frw_event_queue_stru *event_queue)
359 {
360     unsigned long flag;
361 
362     /* 关中断,加锁 */
363     oal_spin_lock_irq_save(&sched_queue->st_lock, &flag);
364 
365     frw_event_sched_deactivate_queue_no_lock(sched_queue, event_queue);
366 
367     /* 解锁,开中断 */
368     oal_spin_unlock_irq_restore(&sched_queue->st_lock, &flag);
369 }
370 
371 #ifdef __cplusplus
372 #if __cplusplus
373 }
374 #endif
375 #endif
376