source: rubycfg_ssp/trunk/task.trb

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

defepr_success変数の削除およびDEF_EPRのエラー出力の修正

  • 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 @reallocate_atskpri = {}
53 @reallocate_etskpri = {}
54 @higher_pri_tsklist = {}
55 @stacksize_of_tasks = {}
56 end
57
58 # オブジェクトのID番号のマクロ定義の生成
59 def generateIdMacro()
60 # タスクIDを起動優先度(atskpri)の高い順に reallocate_atskpri へ割り当てて定義を kernel_cfg.h へ出力
61
62 ($cfgData[:CRE_TSK].sort_by {|e| e[1][:atskpri].val}).each.with_index(1) do |e, index|
63 @reallocate_atskpri[e[0]] = index
64 $kernelCfgH.add("#define #{e[1][:tskid].str} #{index}")
65 end
66
67 $kernelCfgH.add()
68 end
69
70 #
71 # 指定したタスクに対するスタック使用量の最大を計算
72 # 引数:tskid:タスクID(内部表現.起動時優先度の内部表現に等しい)
73 # 返値:当該タスクに足しするスタック使用量の最大値.
74 # この値は,当該タスクの実行開始から終了までの間に
75 # そのタスクに対するプリエンプトを考慮してスタック使用量を
76 # 計算した場合に,可能性のある組み合わせの中で最大となる値を返す.
77 #
78 def calc_stksz(tskid, nest_level=1)
79 higher_pri_maxstksz = 0
80 calculated_stack_size = 0
81 stksz = 0
82 taskEntry = $cfgData[@api][tskid]
83
84 $kernelCfgC.add(" * " + ("\t" * nest_level) + "Calculation Start (Task ID = #{taskEntry[:tskid].str}, StackSize = #{taskEntry[:stksz]})")
85
86 if @stacksize_of_tasks[tskid]
87 # 計算が既に完了している場合,計算をスキップする
88 $kernelCfgC.add(" * " + ("\t" * nest_level) + "SKIP(max_stksz[#{taskEntry[:tskid].str}] = #{@stacksize_of_tasks[tskid]})")
89 stksz = @stacksize_of_tasks[tskid]
90 else
91 # 完了していない場合
92 $kernelCfgC.append(" * " + ("\t" * nest_level) + "Task list with higher priority than #{taskEntry[:tskid].str} = ")
93 @higher_pri_tsklist[tskid].each.with_index do |id, index|
94 $kernelCfgC.append(",") if index > 0
95 $kernelCfgC.append("(#{$cfgData[@api][id][:tskid].str})")
96 end
97 $kernelCfgC.add()
98
99 # 変数の初期化
100 higher_pri_maxstksz = 0
101
102 # 当該タスクID の実行時優先度より高い起動優先度を持つタスクが存在する場合
103 if @higher_pri_tsklist[tskid].size > 0
104 # それぞれの高優先度タスクに対し,スタック計算を実行する
105 @higher_pri_tsklist[tskid].each do |id|
106 calculated_stack_size = calc_stksz(id, nest_level+1)
107 # 最もサイズが大きいものだけを覚えておく
108 if higher_pri_maxstksz < calculated_stack_size
109 higher_pri_maxstksz = calculated_stack_size
110 end
111 end
112 end
113
114 $kernelCfgC.add(" * " + ("\t" * nest_level) + "higher_pri_maxstksz[#{taskEntry[:tskid].str}] = #{higher_pri_maxstksz}")
115
116 # 高優先度タスクのスタック使用量に,当該タスクの使用量を加算する
117 stksz = higher_pri_maxstksz + taskEntry[:stksz]
118
119 # 当該タスクIDに対して計算済みであることを記録
120 @stacksize_of_tasks[tskid] = stksz
121 $kernelCfgC.add(" * " + ("\t" * nest_level) + "DONE(stksz[#{taskEntry[:tskid].str}] = #{stksz})")
122 end
123
124 # 見積もりの最大を返す
125 return stksz
126 end
127
128 # 事前のチェック
129 def prepare()
130
131 $cfgData[@api].sort.each do |key, params|
132
133 # tskatrが無効(E_RSATR)
134 #(TA_ACT,TA_RSTR,TA_NULL,TARGET_TSKATR以外のビットがセットされている場合)
135 if (params[:tskatr] & ~($TA_ACT|$TA_RSTR|$TARGET_TSKATR)) != 0
136 error_illegal_id("E_RSATR", params, :tskatr, :tskid)
137 end
138
139 # (TMIN_TPRI <= atskpri && atskpri <= TMAX_TPRI)でない場合
140 if !($TMIN_TPRI <= params[:atskpri] && params[:atskpri] <= $TMAX_TPRI)
141 error_illegal_id("E_PAR", params, :atskpri, :tskid)
142 end
143
144 # atskpri が重複する場合 (E_PAR)
145 @reallocate_atskpri.each_key do |id|
146 if (params[:tskid].val != id) && (params[:atskpri] == $cfgData[@api][id][:atskpri])
147 error_illegal_id("E_PAR", params, :atskpri, :tskid)
148 end
149 end
150
151 # 実行時優先度
152 defepr_params = $cfgData[:DEF_EPR][params[:tskid].val]
153
154 if defepr_params
155 exepri = defepr_params[:exepri]
156
157 # exepri は TMIN_TPRI 以上 かつ TMAX_TPRI 以下(E_PAR)
158 if $TMIN_TPRI > exepri || $TMAX_TPRI < exepri
159 error_exit("E_PAR: illegal exepri '#{exepri}' in DEF_EPR of #{params[:tskid]}", \
160 "#{defepr_params[:_file_]}:#{defepr_params[:_line_]}:")
161 end
162
163 # exepri は atskpri 以下の値をもつ(優先度が高い) (E_ILUSE)
164 if exepri > params[:atskpri]
165 error_exit("E_ILUSE: illegal exepri '#{exepri}' in DEF_EPR of #{params[:tskid]}", \
166 "#{defepr_params[:_file_]}:#{defepr_params[:_line_]}:")
167 end
168 end
169
170 # stkszがターゲット定義の最小値(TARGET_MIN_STKSZ,未定義の場合は1)
171 # よりも小さい場合
172 if params[:stksz] < $TARGET_MIN_STKSZ
173 error_ercd("E_PAR", params, "stksz is too small.")
174 end
175
176 # スタックの先頭番地(stk)
177 # 全ての処理単位のスタックは共有される.
178 # そのため,スタックサイズに関するチェックは
179 # 共有スタック設定のところでまとめて行う.
180 if params[:stk] != "NULL"
181 error_ercd("E_PAR", params, "stk must be NULL.")
182 end
183 end
184 end
185
186 # データ構造の生成
187 def generateData()
188
189 # 事前準備(エラーチェック,メモリ領域の生成)
190 prepare()
191
192 #
193 # オブジェクト初期化ブロックの生成
194 #
195 init_rdypmap = 0
196
197 # タスク属性(tskatr)
198 $kernelCfgC.append("const ATR\t_kernel_tinib_tskatr[TNUM_TSKID] = {")
199 @reallocate_atskpri.each_key.with_index do |id, index|
200 tskatr = $cfgData[@api][id][:tskatr]
201 $kernelCfgC.append(",") if index > 0
202 $kernelCfgC.append("(#{tskatr.str})")
203 if tskatr & $TA_ACT != 0
204 init_rdypmap = init_rdypmap + (1 << index)
205 end
206 end
207 $kernelCfgC.add("};")
208
209 $kernelCfgC.add("const uint_t\t_kernel_init_rdypmap = #{init_rdypmap}U;")
210
211 # 拡張情報(exinf)
212 $kernelCfgC.append("const intptr_t\t_kernel_tinib_exinf[TNUM_TSKID] = {")
213 @reallocate_atskpri.each_key.with_index do |id, index|
214 exinf = $cfgData[@api][id][:exinf]
215 $kernelCfgC.append(",") if index > 0
216 $kernelCfgC.append("(intptr_t)(#{exinf})")
217 end
218 $kernelCfgC.add("};")
219
220 # 起動番地(task)
221 $kernelCfgC.append("const TASK\t_kernel_tinib_task[TNUM_TSKID] = {")
222 @reallocate_atskpri.each_key.with_index do |id, index|
223 task = $cfgData[@api][id][:task]
224 $kernelCfgC.append(",") if index > 0
225 $kernelCfgC.append("(#{task})")
226 end
227 $kernelCfgC.add("};")
228
229 # 実行時優先度(etskpri)
230 $kernelCfgC.append("const uint_t\t_kernel_tinib_epriority[TNUM_TSKID] = {")
231 @reallocate_atskpri.each_key.with_index do |id, index|
232 begin
233 # 実行時優先度がDEF_EPR で定義されていない場合,起動優先度の設定値を使う
234 defepr_entry = $cfgData[:DEF_EPR].find {|i| i[1][:tskid].val == $cfgData[@api][id][:tskid].val}
235 if defepr_entry
236 epri = defepr_entry[1][:exepri].val
237 else
238 epri = $cfgData[@api][id][:atskpri].val
239 end
240
241 @reallocate_atskpri.each_key do |id2|
242 if epri <= $cfgData[@api][id2][:atskpri]
243 $kernelCfgC.append(",") if index > 0
244 $kernelCfgC.append("INT_PRIORITY(#{@reallocate_atskpri[id2]})")
245 @reallocate_etskpri[id] = @reallocate_atskpri[id2]
246 break
247 end
248 end
249 raise "the exepri of #{$cfgData[@api][id][:tskid].str} is invalid." if !@reallocate_etskpri[id]
250 rescue => e
251 error_exit(e.message + " Abort.")
252 end
253 end
254 $kernelCfgC.add("};")
255
256 #
257 # 優先度割り当て結果を出力
258 #
259 $kernelCfgC.add("/*")
260 $kernelCfgC.add(" * Configuration result of task priority:")
261 @reallocate_atskpri.each_key do |id|
262 $kernelCfgC.append(" * \t#{$cfgData[@api][id][:tskid]}:\tIPRI = #{@reallocate_atskpri[id]}")
263 $kernelCfgC.add(", EXEPRI = #{@reallocate_etskpri[id]}")
264 end
265 $kernelCfgC.add2(" */")
266
267 #
268 # タスクの最大スタック使用量の計算
269 #
270
271 # 木構造のデータ作成
272 $root_apri = []
273 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id|
274 # 各タスク毎に,その実行時優先度よりも高い起動時優先度をもつタスクのリストを作る
275 # それはプリエンプトされる可能性のあるタスクのリストとなる.
276 @higher_pri_tsklist[id[0]] = []
277 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id2|
278 if @reallocate_etskpri[id[0]] > id2[1]
279 @higher_pri_tsklist[id[0]].push(id2[0])
280 end
281 end
282 end
283
284 # プリエンプトする・される関係を示す木構造の根(root)となるタスクの探索
285 # 対象タスク(id)の起動時優先度(reallocate_atskpri[id]より低い
286 # (値としては大きい)起動時優先度をもつタスクの higher_pri_tsklist に
287 # 対象タスク(id)が含まれなければ,根となる
288 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id|
289 $is_root = true
290 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id2|
291 if $is_root && (@reallocate_atskpri[id[0]] < @reallocate_atskpri[id2[0]])
292 if @higher_pri_tsklist[id2[0]].index(id[0])
293 $is_root = false
294 end
295 end
296 end
297 if $is_root
298 $root_apri.push(id)
299 end
300 end
301
302 #
303 # 出力開始
304 #
305 $kernelCfgC.add("/* \n * Task Stack Size Estimation:")
306
307 # 根となるタスクに対し,その最大タスク使用量を計算し,リストへ追加する
308 $tstksz = 0
309 $stksz_estimated = []
310 $root_apri.each do |id|
311 $stksz_estimated.push(calc_stksz(id[1]))
312 end
313
314 # タスクのスタック使用量の最大値を決定
315 # リスト中の要素の最大値がタスクの最大スタック使用量となる.
316 $tstksz = 0
317 $stksz_estimated.each do |size|
318 if size > $tstksz
319 $tstksz = size
320 end
321 end
322
323 # 確認
324 $kernelCfgC.add2(<<EOS)
325 * List of Estimated Total Stack Sizes of Tasks = #{$stksz_estimated}
326 * Estimated Maximum Total Stack Size of Tasks = #{$tstksz}
327 */
328#define TOPPERS_TSTKSZ (#{$tstksz})
329EOS
330
331 #
332 # 優先度割り当て結果を標準出力へ表示
333 #
334 puts <<~EOS
335 =====================================
336 Task priority configuration result:
337 EOS
338 @reallocate_atskpri.each do |e|
339 puts "\t#{$cfgData[@api][e[0]][:tskid].str}:\tIPRI = #{e[1]}, EXEPRI = #{@reallocate_etskpri[e[0]]}\n"
340 end
341 puts "====================================="
342
343
344 end
345end
346
347#
348# タスク管理に関する情報の生成
349#
350
351$kernelCfgC.comment_header("Task Management Functions")
352if $cfgData[:CRE_TSK].size() == 0
353 error("no task is registered")
354end
355
356TaskObject.new.generate()
357
Note: See TracBrowser for help on using the repository browser.