source: rubycfg_ssp/trunk/task.trb@ 288

Last change on this file since 288 was 288, checked in by nmir-saito, 7 years ago

tsk_epri_list変数を使わないように修正

  • Property svn:mime-type set to text/plain; charset=utf-8
File size: 13.9 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TOPPERS/SSP Kernel
4# Toyohashi Open Platform for Embedded Real-Time Systems/
5# Advanced Standard Profile Kernel
6#
7# Copyright (C) 2015 by FUJI SOFT INCORPORATED, JAPAN
8# Copyright (C) 2015,2016 by Embedded and Real-Time Systems Laboratory
9# Graduate School of Information Science, Nagoya Univ., JAPAN
10# Copyright (C) 2017 by Naoki Saito
11# Nagoya Municipal Industrial Research Institute, JAPAN
12#
13# 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ
14# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
15# 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
16# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
17# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
18# スコード中に含まれていること.
19# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
20# 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
21# 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
22# の無保証規定を掲載すること.
23# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
24# 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
25# と.
26# (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
27# 作権表示,この利用条件および下記の無保証規定を掲載すること.
28# (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
29# 報告すること.
30# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
31# 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
32# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
33# 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
34# 免責すること.
35#
36# 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
37# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
38# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
39# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
40# の責任を負わない.
41#
42# $Id: task.trb 668 2016-03-03 13:57:53Z ertl-hiro $
43#
44
45#
46# タスク管理モジュールの生成スクリプト
47#
48
49class TaskObject < KernelObject
50 def initialize()
51 super("tsk", "task")
52 @tsk_apri_list = []
53 @reallocate_atskpri = {}
54 @reallocate_etskpri = {}
55 @higher_pri_tsklist = {}
56 @stacksize_of_tasks = {}
57 end
58
59 # オブジェクトのID番号のマクロ定義の生成
60 def generateIdMacro()
61 # タスクIDを起動優先度(atskpri)の高い順に reallocate_atskpri へ割り当てて定義を kernel_cfg.h へ出力
62
63 ($cfgData[:CRE_TSK].sort_by {|e| e[1][:atskpri].val}).each.with_index(1) do |e, index|
64 @tsk_apri_list.push(e[0])
65 @reallocate_atskpri[e[0]] = index
66 $kernelCfgH.add("#define #{e[1][:tskid].str} #{index}")
67 end
68
69 $kernelCfgH.add()
70 end
71
72 #
73 # 指定したタスクに対するスタック使用量の最大を計算
74 # 引数:tskid:タスクID(内部表現.起動時優先度の内部表現に等しい)
75 # 返値:当該タスクに足しするスタック使用量の最大値.
76 # この値は,当該タスクの実行開始から終了までの間に
77 # そのタスクに対するプリエンプトを考慮してスタック使用量を
78 # 計算した場合に,可能性のある組み合わせの中で最大となる値を返す.
79 #
80 def calc_stksz(tskid, nest_level=1)
81 higher_pri_maxstksz = 0
82 calculated_stack_size = 0
83 stksz = 0
84 taskEntry = $cfgData[@api][tskid]
85
86 $kernelCfgC.add(" * " + ("\t" * nest_level) + "Calculation Start (Task ID = #{taskEntry[:tskid].str}, StackSize = #{taskEntry[:stksz]})")
87
88 if @stacksize_of_tasks[tskid]
89 # 計算が既に完了している場合,計算をスキップする
90 $kernelCfgC.add(" * " + ("\t" * nest_level) + "SKIP(max_stksz[#{taskEntry[:tskid].str}] = #{@stacksize_of_tasks[tskid]})")
91 stksz = @stacksize_of_tasks[tskid]
92 else
93 # 完了していない場合
94 $kernelCfgC.append(" * " + ("\t" * nest_level) + "Task list with higher priority than #{taskEntry[:tskid].str} = ")
95 @higher_pri_tsklist[tskid].each.with_index do |id, index|
96 $kernelCfgC.append(",") if index > 0
97 $kernelCfgC.append("(#{$cfgData[@api][id][:tskid].str})")
98 end
99 $kernelCfgC.add()
100
101 # 変数の初期化
102 higher_pri_maxstksz = 0
103
104 # 当該タスクID の実行時優先度より高い起動優先度を持つタスクが存在する場合
105 if @higher_pri_tsklist[tskid].size > 0
106 # それぞれの高優先度タスクに対し,スタック計算を実行する
107 @higher_pri_tsklist[tskid].each do |id|
108 calculated_stack_size = calc_stksz(id, nest_level+1)
109 # 最もサイズが大きいものだけを覚えておく
110 if higher_pri_maxstksz < calculated_stack_size
111 higher_pri_maxstksz = calculated_stack_size
112 end
113 end
114 end
115
116 $kernelCfgC.add(" * " + ("\t" * nest_level) + "higher_pri_maxstksz[#{taskEntry[:tskid].str}] = #{higher_pri_maxstksz}")
117
118 # 高優先度タスクのスタック使用量に,当該タスクの使用量を加算する
119 stksz = higher_pri_maxstksz + taskEntry[:stksz]
120
121 # 当該タスクIDに対して計算済みであることを記録
122 @stacksize_of_tasks[tskid] = stksz
123 $kernelCfgC.add(" * " + ("\t" * nest_level) + "DONE(stksz[#{taskEntry[:tskid].str}] = #{stksz})")
124 end
125
126 # 見積もりの最大を返す
127 return stksz
128 end
129
130 # 事前のチェック
131 def prepare()
132
133 $cfgData[@api].sort.each do |key, params|
134
135 # tskatrが無効(E_RSATR)
136 #(TA_ACT,TA_RSTR,TA_NULL,TARGET_TSKATR以外のビットがセットされている場合)
137 if (params[:tskatr] & ~($TA_ACT|$TA_RSTR|$TARGET_TSKATR)) != 0
138 error_illegal_id("E_RSATR", params, :tskatr, :tskid)
139 end
140
141 # (TMIN_TPRI <= atskpri && atskpri <= TMAX_TPRI)でない場合
142 if !($TMIN_TPRI <= params[:atskpri] && params[:atskpri] <= $TMAX_TPRI)
143 error_illegal_id("E_PAR", params, :atskpri, :tskid)
144 end
145
146 # atskpri が重複する場合 (E_PAR)
147 @tsk_apri_list.each do |id|
148 if (params[:tskid].val != id) && (params[:atskpri] == $cfgData[@api][id][:atskpri])
149 error_illegal_id("E_PAR", params, :atskpri, :tskid)
150 end
151 end
152
153 # 実行時優先度
154 if $cfgData[:DEF_EPR][params[:tskid].val]
155 # exepri は TMIN_TPRI 以上 かつ TMAX_TPRI 以下(E_PAR)
156 exepri = $cfgData[:DEF_EPR][params[:tskid].val][:exepri]
157 if $TMIN_TPRI > exepri || $TMAX_TPRI < exepri
158 $defepr_success = false
159 error_illegal_id("E_PAR", params, :exepri, :tskid)
160 end
161
162 # exepri は atskpri 以下の値をもつ(優先度が高い) (E_ILUSE)
163 if exepri > params[:atskpri]
164 $defepr_success = false
165 error_illegal_id("E_ILUSE", params, :exepri, :tskid)
166 end
167 end
168
169 # stkszがターゲット定義の最小値(TARGET_MIN_STKSZ,未定義の場合は1)
170 # よりも小さい場合
171 if params[:stksz] < $TARGET_MIN_STKSZ
172 error_ercd("E_PAR", params, "stksz is too small.")
173 end
174
175 # スタックの先頭番地(stk)
176 # 全ての処理単位のスタックは共有される.
177 # そのため,スタックサイズに関するチェックは
178 # 共有スタック設定のところでまとめて行う.
179 if params[:stk] != "NULL"
180 error_ercd("E_PAR", params, "stk must be NULL.")
181 end
182 end
183 end
184
185 # データ構造の生成
186 def generateData()
187
188 # 事前準備(エラーチェック,メモリ領域の生成)
189 prepare()
190
191 #
192 # オブジェクト初期化ブロックの生成
193 #
194 init_rdypmap = 0
195
196 # タスク属性(tskatr)
197 $kernelCfgC.append("const ATR\t_kernel_tinib_tskatr[TNUM_TSKID] = {")
198 @tsk_apri_list.each.with_index do |id, index|
199 tskatr = $cfgData[@api][id][:tskatr]
200 $kernelCfgC.append(",") if index > 0
201 $kernelCfgC.append("(#{tskatr.str})")
202 if tskatr & $TA_ACT != 0
203 init_rdypmap = init_rdypmap + (1 << index)
204 end
205 end
206 $kernelCfgC.add("};")
207
208 $kernelCfgC.add("const uint_t\t_kernel_init_rdypmap = #{init_rdypmap}U;")
209
210 # 拡張情報(exinf)
211 $kernelCfgC.append("const intptr_t\t_kernel_tinib_exinf[TNUM_TSKID] = {")
212 @tsk_apri_list.each.with_index do |id, index|
213 exinf = $cfgData[@api][id][:exinf]
214 $kernelCfgC.append(",") if index > 0
215 $kernelCfgC.append("(intptr_t)(#{exinf})")
216 end
217 $kernelCfgC.add("};")
218
219 # 起動番地(task)
220 $kernelCfgC.append("const TASK\t_kernel_tinib_task[TNUM_TSKID] = {")
221 @tsk_apri_list.each.with_index do |id, index|
222 task = $cfgData[@api][id][:task]
223 $kernelCfgC.append(",") if index > 0
224 $kernelCfgC.append("(#{task})")
225 end
226 $kernelCfgC.add("};")
227
228 # 実行時優先度(etskpri)
229 $kernelCfgC.append("const uint_t\t_kernel_tinib_epriority[TNUM_TSKID] = {")
230 @tsk_apri_list.each.with_index do |id, index|
231 begin
232 # 実行時優先度がDEF_EPR で定義されていない場合,起動優先度の設定値を使う
233 defepr_entry = $cfgData[:DEF_EPR].find {|i| i[1][:tskid].val == $cfgData[@api][id][:tskid].val}
234 if defepr_entry
235 epri = defepr_entry[1][:exepri].val
236 else
237 epri = $cfgData[@api][id][:atskpri].val
238 end
239
240 @tsk_apri_list.each do |id2|
241 if epri <= $cfgData[@api][id2][:atskpri]
242 $kernelCfgC.append(",") if index > 0
243 $kernelCfgC.append("INT_PRIORITY(#{@reallocate_atskpri[id2]})")
244 @reallocate_etskpri[id] = @reallocate_atskpri[id2]
245 break
246 end
247 end
248 raise "the exepri of #{$cfgData[@api][id][:tskid].str} is invalid." if !@reallocate_etskpri[id]
249 rescue => e
250 error_exit(e.message + " Abort.")
251 end
252 end
253 $kernelCfgC.add("};")
254
255 #
256 # 優先度割り当て結果を出力
257 #
258 $kernelCfgC.add("/*")
259 $kernelCfgC.add(" * Configuration result of task priority:")
260 @tsk_apri_list.each do |id|
261 $kernelCfgC.append(" * \t#{$cfgData[@api][id][:tskid]}:\tIPRI = #{@reallocate_atskpri[id]}")
262 $kernelCfgC.add(", EXEPRI = #{@reallocate_etskpri[id]}")
263 end
264 $kernelCfgC.add2(" */")
265
266 #
267 # タスクの最大スタック使用量の計算
268 #
269
270 # 木構造のデータ作成
271 $root_apri = []
272 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id|
273 # 各タスク毎に,その実行時優先度よりも高い起動時優先度をもつタスクのリストを作る
274 # それはプリエンプトされる可能性のあるタスクのリストとなる.
275 @higher_pri_tsklist[id[0]] = []
276 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id2|
277 if @reallocate_etskpri[id[0]] > id2[1]
278 @higher_pri_tsklist[id[0]].push(id2[0])
279 end
280 end
281 end
282
283 # プリエンプトする・される関係を示す木構造の根(root)となるタスクの探索
284 # 対象タスク(id)の起動時優先度(reallocate_atskpri[id]より低い
285 # (値としては大きい)起動時優先度をもつタスクの higher_pri_tsklist に
286 # 対象タスク(id)が含まれなければ,根となる
287 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id|
288 $is_root = true
289 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id2|
290 if $is_root && (@reallocate_atskpri[id[0]] < @reallocate_atskpri[id2[0]])
291 if @higher_pri_tsklist[id2[0]].index(id[0])
292 $is_root = false
293 end
294 end
295 end
296 if $is_root
297 $root_apri.push(id)
298 end
299 end
300
301 #
302 # 出力開始
303 #
304 $kernelCfgC.add("/* \n * Task Stack Size Estimation:")
305
306 # 根となるタスクに対し,その最大タスク使用量を計算し,リストへ追加する
307 $tstksz = 0
308 $stksz_estimated = []
309 $root_apri.each do |id|
310 $stksz_estimated.push(calc_stksz(id[1]))
311 end
312
313 # タスクのスタック使用量の最大値を決定
314 # リスト中の要素の最大値がタスクの最大スタック使用量となる.
315 $tstksz = 0
316 $stksz_estimated.each do |size|
317 if size > $tstksz
318 $tstksz = size
319 end
320 end
321
322 # 確認
323 $kernelCfgC.add2(<<EOS)
324 * List of Estimated Total Stack Sizes of Tasks = #{$stksz_estimated}
325 * Estimated Maximum Total Stack Size of Tasks = #{$tstksz}
326 */
327#define TOPPERS_TSTKSZ (#{$tstksz})
328EOS
329
330 #
331 # 優先度割り当て結果を標準出力へ表示
332 #
333 puts <<~EOS
334 =====================================
335 Task priority configuration result:
336 EOS
337 @reallocate_atskpri.each do |e|
338 puts "\t#{$cfgData[@api][e[0]][:tskid].str}:\tIPRI = #{e[1]}, EXEPRI = #{@reallocate_etskpri[e[0]]}\n"
339 end
340 puts "====================================="
341
342
343 end
344end
345
346#
347# タスク管理に関する情報の生成
348#
349
350# 実行時優先度のコンフィギュレーションに成功したかどうか
351$defepr_success = true
352
353$kernelCfgC.comment_header("Task Management Functions")
354if $cfgData[:CRE_TSK].size() == 0
355 error("no task is registered")
356end
357
358TaskObject.new.generate()
359
Note: See TracBrowser for help on using the repository browser.