annotate manager-task.tex @ 7:bd8574dedd1b

*** empty log message ***
author gongo
date Tue, 25 Mar 2008 15:51:53 +0900
parents
children b70a62630a57
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
7
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
1 \subsection{Task}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
2 Task の定義は以下のようになる。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
3
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
4 {\small
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
5 \begin{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
6
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
7 class Task {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
8 public:
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
9 int command; // 実行するタスクID
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
10 int size; // in_addr で取得するデータのバイト数
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
11 unsigned int in_addr; // 入力データ元アドレス
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
12 unsigned int out_addr; // 出力データ先アドレス
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
13
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
14 TaskQueue *wait_me;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
15 TaskQueue *wait_i;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
16
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
17 CPU_TYPE cpu_type; // PPE or SPE
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
18
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
19 void spawn(void);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
20 void set_depend(Task*);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
21 void set_cpu(Task*);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
22 };
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
23
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
24 \end{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
25 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
26
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
27 command, size, in\_addr, out\_addr は
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
28 create\_task() で引数で登録する。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
29
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
30 \subsection{Dependency} \label{sec:task}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
31 「Task1 は Task2, Task3 が終わるまで実行されてはいけない」といった、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
32 Task 同士での依存関係を指定するには、API の set\_depend() を使う。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
33
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
34 {\small
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
35 \begin{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
36
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
37 // task2 は task1 が終了してから開始する
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
38 task2->set_depend(task1);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
39
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
40 \end{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
41 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
42
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
43 set\_depend の実装を以下に示す。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
44
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
45 {\small
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
46 \begin{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
47
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
48 void
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
49 Task::set_depend(Task* master)
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
50 {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
51 Task *slave = this;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
52
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
53 master->wait_me
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
54 = append_queue(master_wait_me, slave)
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
55 slave->wait_i
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
56 = append_queue(slave_wait_i, master);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
57 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
58
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
59 \end{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
60 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
61
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
62 各 Task が持つ wait\_me は、「自分を待っている Task」のキューで、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
63 wait\_i は、「自分が待っている Task 」のキューとなる。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
64
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
65 Task が spawn された時、wait\_i が空であれば 実行 Queue へ、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
66 あれば WaitQueue へ追加される。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
67
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
68 Task が終わる毎に、SPE から Task が終了したことを PPE に知らせる。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
69 PPE は、Task が終了したことを、WaitQueue にある Task に知らせる。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
70 WaitQueue の Task は、終了した Task が、自分が待っている Task であれば
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
71 自分の wait\_i からその Task を削除していく。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
72 自分の wait\_i が空になれば、Task 依存を満たしたので ActiveQueue に追加される。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
73 以上の記述を以下に示す。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
74
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
75 {\small
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
76 \begin{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
77
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
78 /**
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
79 * master : 終了した Task
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
80 * list : master->wait_me
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
81 */
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
82 void
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
83 notify_waitQueue(Task *master,TaskQueue *list)
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
84 {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
85 Task* slave;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
86
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
87 while (list) {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
88 slave = list->task;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
89 slave->wait_i
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
90 = remove_taskQueue(slave->wait_i, master);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
91 if (slave->wait_i == NULL) {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
92 append_activeTask(slave);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
93 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
94 list = list->next;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
95 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
96 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
97
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
98 \end{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
99 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
100
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
101 \subsection{Mail}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
102 \ref{sec:task} で述べたように、SPE から Task の終了を
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
103 PPE に伝える必要があるが、その際の待ち合わせは避けるべきである。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
104
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
105 Cell では、PPE と SPE 間のメッセージのやりとりには
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
106 Mail box という FIFO メッセージキューを用いる。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
107 メッセージ交換なので待ち合わせを避けることが可能である。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
108
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
109 SPE $\rightarrow$ PPE だけでなく、PPE Kernel 内部でも
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
110 Mailbox と同じ方式でメッセージ交換をしている。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
111 Task は SPE だけでなく、PPE でも実行されているためである。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
112
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
113 メールチェックをする関数 mail\_check() を以下に示す。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
114 この関数は、現在 PPE 側の ActiveQueue にある Task が
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
115 全て終わった後、次の ActiveQueue を取得する前に呼ばれる。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
116
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
117 {\small
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
118 \begin{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
119
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
120 MailQueuePtr
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
121 SpeTaskManager::mail_check(MailQueue *mail_list)
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
122 {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
123 MailQueue *list;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
124 unsigned int data;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
125
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
126 // mail_list には、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
127 // 「PPE側」で終了した Task に関するメールがある
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
128 // list には、次の Task に関するメールがある
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
129 list = ppeTaskManager->mail_check(mail_list);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
130
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
131 do {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
132 for (id = 0; id < SPE_NUM; id++) {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
133 while (1) {
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
134 // data には、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
135 // 「SPE側」で終了した Task がある。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
136 // data がマイナスの場合、Mail box は空
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
137 data = speThreads->get_mail(id);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
138 if (data < 0) break;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
139 check_task_finish(data);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
140 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
141 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
142 } while (list == NULL && waitTaskQueue
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
143 && !activeTaskQueue);
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
144
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
145 return list;
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
146 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
147
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
148 \end{verbatim}
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
149 }
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
150
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
151 PPE が SPE からメールを受け取る場合、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
152 spe\_out\_mbox\_read() という、SPE Runtime Management Library \cite{libspe2} を
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
153 用いる。しかし、spe\_out\_mbox\_read() は Non-blocking function のため、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
154 busy-wait なメールの待ち方は避けるべきである。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
155 今回は、PPE 側でメールチェックを行う際に、SPE からのメールをチェックする。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
156
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
157 PPE と SPE のメールチェックを分離させたい場合、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
158 メールをチェックする Blocking Function を作る必要がある。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
159
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
160 もしくは SPE Event Handling を用いる手法もある。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
161 これは、メールが来たら event を起こすことを Event Handler に登録する。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
162 この場合、通常の Mailbox ではない、割り込み用の interrupting Mailbox を
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
163 使用しなくてはならない。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
164 interrupting Mailbox を使用する spe\_out\_intr\_mbox\_read() は、
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
165 Event が起きたときに呼ばれるため Blocking Function である。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
166 SPE のどれかからメッセージが来たらポーリングによってメールチェックを行う。
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
167
bd8574dedd1b *** empty log message ***
gongo
parents:
diff changeset
168 今回は、PPE と SPE のメールチェックは分離しない実装をした。