source: rubycfg_ssp/trunk/task.trb@ 289

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

tsk_apri_list変数を使わないようにtask.trbを変更

  • 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 if $cfgData[:DEF_EPR][params[:tskid].val]
153 # exepri は TMIN_TPRI 以上 かつ TMAX_TPRI 以下(E_PAR)
154 exepri = $cfgData[:DEF_EPR][params[:tskid].val][:exepri]
155 if $TMIN_TPRI > exepri || $TMAX_TPRI < exepri
156 $defepr_success = false
157 error_illegal_id("E_PAR", params, :exepri, :tskid)
158 end
159
160 # exepri は atskpri 以下の値をもつ(優先度が高い) (E_ILUSE)
161 if exepri > params[:atskpri]
162 $defepr_success = false
163 error_illegal_id("E_ILUSE", params, :exepri, :tskid)
164 end
165 end
166
167 # stkszがターゲット定義の最小値(TARGET_MIN_STKSZ,未定義の場合は1)
168 # よりも小さい場合
169 if params[:stksz] < $TARGET_MIN_STKSZ
170 error_ercd("E_PAR", params, "stksz is too small.")
171 end
172
173 # スタックの先頭番地(stk)
174 # 全ての処理単位のスタックは共有される.
175 # そのため,スタックサイズに関するチェックは
176 # 共有スタック設定のところでまとめて行う.
177 if params[:stk] != "NULL"
178 error_ercd("E_PAR", params, "stk must be NULL.")
179 end
180 end
181 end
182
183 # データ構造の生成
184 def generateData()
185
186 # 事前準備(エラーチェック,メモリ領域の生成)
187 prepare()
188
189 #
190 # オブジェクト初期化ブロックの生成
191 #
192 init_rdypmap = 0
193
194 # タスク属性(tskatr)
195 $kernelCfgC.append("const ATR\t_kernel_tinib_tskatr[TNUM_TSKID] = {")
196 @reallocate_atskpri.each_key.with_index do |id, index|
197 tskatr = $cfgData[@api][id][:tskatr]
198 $kernelCfgC.append(",") if index > 0
199 $kernelCfgC.append("(#{tskatr.str})")
200 if tskatr & $TA_ACT != 0
201 init_rdypmap = init_rdypmap + (1 << index)
202 end
203 end
204 $kernelCfgC.add("};")
205
206 $kernelCfgC.add("const uint_t\t_kernel_init_rdypmap = #{init_rdypmap}U;")
207
208 # 拡張情報(exinf)
209 $kernelCfgC.append("const intptr_t\t_kernel_tinib_exinf[TNUM_TSKID] = {")
210 @reallocate_atskpri.each_key.with_index do |id, index|
211 exinf = $cfgData[@api][id][:exinf]
212 $kernelCfgC.append(",") if index > 0
213 $kernelCfgC.append("(intptr_t)(#{exinf})")
214 end
215 $kernelCfgC.add("};")
216
217 # 起動番地(task)
218 $kernelCfgC.append("const TASK\t_kernel_tinib_task[TNUM_TSKID] = {")
219 @reallocate_atskpri.each_key.with_index do |id, index|
220 task = $cfgData[@api][id][:task]
221 $kernelCfgC.append(",") if index > 0
222 $kernelCfgC.append("(#{task})")
223 end
224 $kernelCfgC.add("};")
225
226 # 実行時優先度(etskpri)
227 $kernelCfgC.append("const uint_t\t_kernel_tinib_epriority[TNUM_TSKID] = {")
228 @reallocate_atskpri.each_key.with_index do |id, index|
229 begin
230 # 実行時優先度がDEF_EPR で定義されていない場合,起動優先度の設定値を使う
231 defepr_entry = $cfgData[:DEF_EPR].find {|i| i[1][:tskid].val == $cfgData[@api][id][:tskid].val}
232 if defepr_entry
233 epri = defepr_entry[1][:exepri].val
234 else
235 epri = $cfgData[@api][id][:atskpri].val
236 end
237
238 @reallocate_atskpri.each_key do |id2|
239 if epri <= $cfgData[@api][id2][:atskpri]
240 $kernelCfgC.append(",") if index > 0
241 $kernelCfgC.append("INT_PRIORITY(#{@reallocate_atskpri[id2]})")
242 @reallocate_etskpri[id] = @reallocate_atskpri[id2]
243 break
244 end
245 end
246 raise "the exepri of #{$cfgData[@api][id][:tskid].str} is invalid." if !@reallocate_etskpri[id]
247 rescue => e
248 error_exit(e.message + " Abort.")
249 end
250 end
251 $kernelCfgC.add("};")
252
253 #
254 # 優先度割り当て結果を出力
255 #
256 $kernelCfgC.add("/*")
257 $kernelCfgC.add(" * Configuration result of task priority:")
258 @reallocate_atskpri.each_key do |id|
259 $kernelCfgC.append(" * \t#{$cfgData[@api][id][:tskid]}:\tIPRI = #{@reallocate_atskpri[id]}")
260 $kernelCfgC.add(", EXEPRI = #{@reallocate_etskpri[id]}")
261 end
262 $kernelCfgC.add2(" */")
263
264 #
265 # タスクの最大スタック使用量の計算
266 #
267
268 # 木構造のデータ作成
269 $root_apri = []
270 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id|
271 # 各タスク毎に,その実行時優先度よりも高い起動時優先度をもつタスクのリストを作る
272 # それはプリエンプトされる可能性のあるタスクのリストとなる.
273 @higher_pri_tsklist[id[0]] = []
274 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id2|
275 if @reallocate_etskpri[id[0]] > id2[1]
276 @higher_pri_tsklist[id[0]].push(id2[0])
277 end
278 end
279 end
280
281 # プリエンプトする・される関係を示す木構造の根(root)となるタスクの探索
282 # 対象タスク(id)の起動時優先度(reallocate_atskpri[id]より低い
283 # (値としては大きい)起動時優先度をもつタスクの higher_pri_tsklist に
284 # 対象タスク(id)が含まれなければ,根となる
285 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id|
286 $is_root = true
287 (@reallocate_atskpri.sort_by {|id| id[1]}).reverse_each do |id2|
288 if $is_root && (@reallocate_atskpri[id[0]] < @reallocate_atskpri[id2[0]])
289 if @higher_pri_tsklist[id2[0]].index(id[0])
290 $is_root = false
291 end
292 end
293 end
294 if $is_root
295 $root_apri.push(id)
296 end
297 end
298
299 #
300 # 出力開始
301 #
302 $kernelCfgC.add("/* \n * Task Stack Size Estimation:")
303
304 # 根となるタスクに対し,その最大タスク使用量を計算し,リストへ追加する
305 $tstksz = 0
306 $stksz_estimated = []
307 $root_apri.each do |id|
308 $stksz_estimated.push(calc_stksz(id[1]))
309 end
310
311 # タスクのスタック使用量の最大値を決定
312 # リスト中の要素の最大値がタスクの最大スタック使用量となる.
313 $tstksz = 0
314 $stksz_estimated.each do |size|
315 if size > $tstksz
316 $tstksz = size
317 end
318 end
319
320 # 確認
321 $kernelCfgC.add2(<<EOS)
322 * List of Estimated Total Stack Sizes of Tasks = #{$stksz_estimated}
323 * Estimated Maximum Total Stack Size of Tasks = #{$tstksz}
324 */
325#define TOPPERS_TSTKSZ (#{$tstksz})
326EOS
327
328 #
329 # 優先度割り当て結果を標準出力へ表示
330 #
331 puts <<~EOS
332 =====================================
333 Task priority configuration result:
334 EOS
335 @reallocate_atskpri.each do |e|
336 puts "\t#{$cfgData[@api][e[0]][:tskid].str}:\tIPRI = #{e[1]}, EXEPRI = #{@reallocate_etskpri[e[0]]}\n"
337 end
338 puts "====================================="
339
340
341 end
342end
343
344#
345# タスク管理に関する情報の生成
346#
347
348# 実行時優先度のコンフィギュレーションに成功したかどうか
349$defepr_success = true
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.