source: rubycfg_ssp/trunk/task.trb@ 285

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

Tracのソース閲覧時に文字化けするためmimetypewo

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