source: rubycfg_ssp/task.trb@ 283

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

ファイルの追加

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