109
|
1 #include <stdlib.h>
|
76
|
2 #include "types.h"
|
65
|
3 #include "SpeThreads.h"
|
|
4
|
|
5 SpeThreads::SpeThreads(int num) : spe_num(num) {}
|
|
6
|
76
|
7 SpeThreads::~SpeThreads(void)
|
|
8 {
|
|
9 unsigned int mail = MY_SPE_COMMAND_EXIT;
|
|
10 int ret;
|
|
11
|
|
12 for (int i = 0; i < spe_num; i++) {
|
244
|
13 send_mail(i, 1, &mail);
|
76
|
14 }
|
|
15
|
|
16 for (int i = 0; i < spe_num; i++) {
|
|
17 pthread_join(threads[i], NULL);
|
|
18 ret = spe_context_destroy(spe_ctx[i]);
|
|
19 if (ret) {
|
|
20 perror("[~SpeThreads] spe_context_destroy");
|
|
21 }
|
|
22 }
|
|
23
|
|
24 spe_image_close(spe_handle);
|
|
25
|
|
26 delete [] spe_ctx;
|
|
27 delete [] threads;
|
|
28 delete [] args;
|
|
29 }
|
|
30
|
65
|
31 void*
|
|
32 SpeThreads::spe_thread_run(void *arg)
|
|
33 {
|
|
34 unsigned int entry = SPE_DEFAULT_ENTRY;
|
109
|
35 //spe_context_ptr_t ctx = (spe_context_ptr_t)arg;
|
|
36 thread_arg_t *arg_t = (thread_arg_t *)arg;
|
|
37
|
|
38 spe_stop_info_t stop_info;
|
|
39 unsigned long long status;
|
|
40
|
|
41 spe_context_run(arg_t->ctx, &entry, 0, (void*)arg_t->speid, NULL, &stop_info);
|
65
|
42
|
109
|
43 status = ((stop_info.result.spe_exit_code & 0xff) << 8)
|
|
44 | (stop_info.result.spe_signal_code & 0xff);
|
|
45
|
|
46 switch(stop_info.stop_reason) {
|
|
47 case SPE_EXIT:
|
194
|
48 //printf("SPE_EXIT stop_info.result.stop_exit_code=0x%x\n", stop_info.result.spe_exit_code);
|
109
|
49 break;
|
|
50 case SPE_STOP_AND_SIGNAL:
|
194
|
51 printf("[SPE %d] SPE_STOP_AND_SIGNAL stop_info.result.stop_signal_code=%d\n", arg_t->speid, stop_info.result.spe_signal_code);
|
109
|
52 break;
|
|
53 case SPE_RUNTIME_ERROR:
|
194
|
54 printf("[SPE %d] SPE_RUNTIME_ERROR stop_info.result.spe_runtime_error=%d\n", arg_t->speid, stop_info.result.spe_runtime_error);
|
109
|
55 break;
|
|
56 case SPE_RUNTIME_EXCEPTION:
|
194
|
57 printf("[SPE %d] SPE_RUNTIME_EXCEPTION stop_info.result.spe_runtime_exception=%d\n", arg_t->speid, stop_info.result.spe_runtime_exception);
|
109
|
58 break;
|
|
59 }
|
65
|
60
|
|
61 pthread_exit(NULL);
|
|
62 }
|
|
63
|
|
64 void*
|
|
65 SpeThreads::frontend_thread_run(void *arg)
|
|
66 {
|
|
67 pthread_t thread;
|
|
68 thread_arg_t *arg_t = (thread_arg_t *)arg;
|
|
69
|
|
70 pthread_create(&thread, NULL, &spe_thread_run, (void*)arg_t->ctx);
|
|
71
|
76
|
72 // mail read の blocking ができれば
|
|
73 // ここで呼んだ方が早い。
|
|
74
|
65
|
75 pthread_exit(NULL);
|
|
76 }
|
|
77
|
|
78 void
|
|
79 SpeThreads::init(void)
|
|
80 {
|
109
|
81 spe_handle = spe_image_open(SPE_ELF);
|
65
|
82
|
109
|
83 if (spe_handle == NULL) {
|
|
84 perror("spe_image_open");
|
|
85 exit(EXIT_FAILURE);
|
|
86 }
|
65
|
87
|
|
88 spe_ctx = new spe_context_ptr_t[spe_num];
|
|
89 threads = new pthread_t[spe_num];
|
|
90 args = new thread_arg_t[spe_num];
|
|
91
|
109
|
92 for (int i = 0; i < spe_num; i++) {
|
65
|
93 args[i].speid = i;
|
|
94 spe_ctx[i] = spe_context_create(0, NULL);
|
|
95 spe_program_load(spe_ctx[i], spe_handle);
|
|
96 args[i].ctx = spe_ctx[i];
|
|
97 }
|
|
98
|
109
|
99 for (int i = 0; i < spe_num; i++) {
|
|
100 #if 0
|
65
|
101 pthread_create(&threads[i], NULL,
|
|
102 &frontend_thread_run, (void*)&args[i]);
|
109
|
103 #else
|
|
104 pthread_create(&threads[i], NULL,
|
|
105 &spe_thread_run, (void*)&args[i]);
|
|
106 #endif
|
65
|
107 }
|
|
108 }
|
|
109
|
244
|
110
|
109
|
111 /**
|
|
112 * SPE からのメールを受信する。
|
|
113 *
|
|
114 * @param [speid] SPE ID
|
|
115 *
|
|
116 * @return Received 32-bit mailbox messages
|
|
117 * if ([ret] < 0) no data read
|
|
118 */
|
65
|
119 int
|
244
|
120 SpeThreads::get_mail(int speid, int count, unsigned int* ret)
|
|
121 {
|
|
122 while(spe_out_mbox_status(spe_ctx[speid]) < count);
|
|
123 return spe_out_mbox_read(spe_ctx[speid], ret, count);
|
|
124 }
|
|
125
|
|
126 int
|
|
127 SpeThreads::check_mail(int speid, int count, unsigned int* ret)
|
65
|
128 {
|
244
|
129 if (spe_out_mbox_status(spe_ctx[speid]) >= count) {
|
|
130 return spe_out_mbox_read(spe_ctx[speid], ret, count);
|
|
131 } else {
|
|
132 return 0;
|
|
133 }
|
65
|
134 }
|
66
|
135
|
109
|
136 /**
|
|
137 * Inbound Mailbox
|
|
138 * メール送信 PPE -> SPE
|
|
139 *
|
|
140 * なるべく NONBLOCKING なんだけど、
|
|
141 * Inbound Mailbox キューに空きがないと送信できないので
|
161
|
142 * 送信する数だけ空いているか確認してから送る。空いて無い場合は待つ。
|
|
143 *
|
|
144 * 結局待つんだよな。しかも ALL_BLOCKING って実は busy wait だったりするし
|
109
|
145 *
|
|
146 * @param [speid] SPE ID
|
|
147 * @param [data] Send 32-bit mailbox messages
|
|
148 * @param [num] The number of messages
|
|
149 */
|
66
|
150 void
|
244
|
151 SpeThreads::send_mail(int speid, int num, unsigned int *data)
|
|
152 {
|
|
153 spe_in_mbox_write(spe_ctx[speid], data, num, SPE_MBOX_ALL_BLOCKING);
|
|
154 }
|
|
155
|
|
156 void
|
|
157 SpeThreads::add_output_tasklist(int command, void *buff, int alloc_size)
|
66
|
158 {
|
244
|
159 /*
|
|
160 * output TaskList が無ければ新しく作る
|
|
161 * あれば TaskList に allocate した Task を追加
|
|
162 * command に対応した Task の初期化を実行する
|
|
163 * SPE に data が書き出し終わった後に PPE 側で初期化
|
|
164 */
|
|
165
|
66
|
166 }
|