spu_run - SPU
コンテキストを実行する
#include <sys/spu.h>
int spu_run(int fd, unsigned int *npc, unsigned int *event);
注:
このシステムコールには
glibc
のラッパー関数は存在しない。「注意」の節を参照。
spu_run()
システムコールは、Cell
Broadband Engine
アーキテクチャーを実装した
PowerPC マシンで Synergistic Processor Units (SPU)
にアクセスするために
使用される。
fd
引数は、
spu_create(2)
が返すファイルディスクリプターで、
特定の SPU
コンテキストを参照する。
そのコンテキストが物理
SPU
に割り当てられると、
npc
で渡された命令ポインター
(instruction pointer)
から実行が開始される。
SPU
コードの実行は同期的
(synchronously)
に行われる、つまり SPU
が実行中は
spu_run()
は停止 (block) する。 SPU
コードの実行をメイン
CPU や他の SPU
と並行して行う必要がある場合は、
最初に、その SPU
コードを実行する新しいスレッドを、(例えば
pthread_create(3) などを使って)
生成しなければならない。
spu_run()
が返るときには、SPU
のプログラムカウンターの現在値が
npc に書き込まれる。
これにより、連続する
spu_run()
の呼び出しで同じ
npc
ポインターを使うことができる。
event
引数には、拡張ステータスコード用のバッファーを指定する。
SPU_CREATE_EVENTS_ENABLED
フラグ付きで SPU
コンテキストが作成されると、
spu_run() が返る前に Linux
カーネルによりこのバッファーに
拡張ステータスコードが格納される。
ステータスコードには以下の定数が一つ以上入る。
- SPE_EVENT_DMA_ALIGNMENT
- DMA (direct memory access)
のアライメントエラーが発生した。
- SPE_EVENT_INVALID_DMA
- 無効な MFC (Memory Flow Controller) DMA
コマンドを行おうとした。
- SPE_EVENT_SPE_DATA_STORAGE
- DMA
ストレージエラーが発生した。
- SPE_EVENT_SPE_ERROR
- 不正な命令が実行された。
NULL は
event
引数として有効な値である。
この場合、イベントは呼び出し元のプロセスに報告されない。
成功すると、
spu_run() は
spu_status
レジスターの値を返す。
エラーの場合、-1
を返し、
errno
を下記のエラーコードのいずれかに設定する。
spu_status
レジスターの値は、ステータスコードと
SPU の
stop-and-signal 命令が返す
14 ビットのコードの
ビットマスクで構成される。
後者の 14
ビットのコードはオプションである。
ステータスコードのビットマスクは下記の通りである。
- 0x02
- SPU が stop-and-signal
命令で停止した。
- 0x04
- SPU が halt (停止)
命令で止まった。
- 0x08
- SPU
はチャンネルのウェイト中である。
- 0x10
- SPU
はシングルステップモードであった。
- 0x20
- SPU
が不正な命令を実行しようとした。
- 0x40
- SPU
が不正なチャンネルにアクセスしようとした。
- 0x3fff0000
- この値のマスクを適用して得られたビット値には、
stop-and-signal
命令から返されたコードが入っている。
これらのビットは 0x02
ビットがセットされている場合にのみ有効である。
spu_run()
がエラーを返さなかった場合、下位
8 ビットのうち 1
つ以上は
常にセットされる。
- EBADF
-
fd
が有効なファイルディスクリプターでない。
- EFAULT
-
npc
が有効なポインターでない。または
event が NULL
以外で、しかも無効なポインターである。
- EINTR
-
spu_run()
の実行中にシグナルが発生した。
signal(7) 参照。
必要であれば、 npc
の値は新しいプログラムカウンターの値に更新される。
- EINVAL
-
fd が spu_create(2)
が返した有効なファイルディスクリプターでない。
- ENOMEM
- Memory Flow Controller (MFC) DMA
により発生したページフォールトを
処理するのに必要なメモリーがなかった。
- ENOSYS
- 機能が動作中のシステムで提供されていない。理由は、
ハードウェアで SPU
が提供されていないか、
spufs
モジュールがロードされていないか、のどちらかである。
spu_run()
システムコールはカーネル
2.6.16 で Linux に追加された。
このシステムコールは
Linux 固有であり、 PowerPC
アーキテクチャーでのみ実装されている。
このシステムコールを使ったプログラムは移植性がない。
glibc
はこのシステムコールに対するラッパー関数を提供していない。
syscall(2)
を使うこと。ただし、
spu_run() は
より抽象度の高い SPU
へのインターフェースを実装するライブラリから
利用されることを意図したものであり、通常のアプリケーションから
使用は意図されていない。推奨のライブラリについては
http://www.bsc.es/projects/deepcomputing/linuxoncell/
を参照のこと。
以下は、簡単な 1
命令の SPU プログラムを
spu_run()
システムコールを使って実行させる例である。
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
int main(void)
{
int context, fd, spu_status;
uint32_t instruction, npc;
context = spu_create("/spu/example-context", 0, 0755);
if (context == -1)
handle_error("spu_create");
/* write a 'stop 0x1234' instruction to the SPU's
* local store memory
*/
instruction = 0x00001234;
fd = open("/spu/example-context/mem", O_RDWR);
if (fd == -1)
handle_error("open");
write(fd, &instruction, sizeof(instruction));
/* set npc to the starting instruction address of the
* SPU program. Since we wrote the instruction at the
* start of the mem file, the entry point will be 0x0
*/
npc = 0;
spu_status = spu_run(context, &npc, NULL);
if (spu_status == -1)
handle_error("open");
/* we should see a status code of 0x1234002:
* 0x00000002 (spu was stopped due to stop-and-signal)
* | 0x12340000 (the stop-and-signal code)
*/
printf("SPU Status: %#08x\n", spu_status);
exit(EXIT_SUCCESS);
}
close(2),
spu_create(2),
capabilities(7),
spufs(7)
この man ページは Linux
man-pages
プロジェクトのリリース
5.10
の一部である。プロジェクトの説明とバグ報告に関する情報は
https://www.kernel.org/doc/man-pages/
に書かれている。