C99に対応した標準Cライブラリの実装レポートを行っていきます。

プロフィール 

Author:高木信尚

ホームページ
ブログ

最近の記事 

最近のコメント 

最近のトラックバック 

月別アーカイブ 

カテゴリー 

ブロとも申請フォーム 

この人とブロともになる

ホーム 全記事一覧 << 前の記事 次の記事 >>

 

2008/10/07 11:49|

 

前回は、シグナル処理ルーチンの方針について書きました。今回と次回は、その方針に基づいて、実際にsignal関数とraise関数を実装することにします。

今回の関数は、初めてOSに依存したコードになります。といっても、簡単な排他制御だけですので、普通に割り込みを禁止してもよいのですが、他のターゲットへの移植性を考慮して、μITRONの機能を使うことにします。

それでは、実装を見てみましょう。

#include <signal.h>
#include <errno.h>

#define SIGMAX  6
static void (*signal_handler_table[SIGMAX])(int);

void (* signal(int sig, void (*func)(int)) )(int)
{
  if (sig < 1 || SIGMAX < sig || func == SIG_ERR) {
    errno = EDOM;
    return SIG_ERR;
  }

  BOOL f = sns_loc();
  loc_cpu();
  void (*result)(int) = signal_handler_table[sig-1];
  signal_handler_table[sig-1] = func;
  if (!f) unl_cpu();

  return result;
}

前半部は引数のチェックを行っています。sigで指定したシグナル番号の範囲と、念のためfuncにSIG_ERRを誤って指定していないかどうかだけのチェックにとどめています。funcに空ポインタを指定した場合、SIG_DFLとの区別が付きませんので、特に何もしていません。

エラーを検出した場合、SIG_ERRを返すとともに、errnoに正の値を設定しなければならないため、ここではEDOMを設定しています。他のエラー番号を設けてもよいのですが、今回はそこまでする必要もないと判断しました。

シグナル処理ルーチンは、signal_handler_table配列に格納されます。静的な配列ですので、その内容は空ポインタ(=SIG_DFL)で初期化されることが期待できます。また、raise関数も同じ翻訳単位に収めることにすれば、この配列は内部結合となり、外部から参照されるおそれがなくなります。

signal_handler_table配列の操作は、排他制御が必要ですので、sns_loc、loc_cpu、およびunl_cpuというサービスコールを使用しています。これらはCPUロック状態の制御を行うもので、すごく乱暴に言ってしまえば、割り込み禁止の制御を行っています。

signal関数は、非タスクコンテキストで呼ばれることを想定していません。そのため、sns_ctxでコンテキストの状態を調べてることなく、(iloc_cpuやiunl_cpuではなく)loc_cpuやunl_cpuを問答無用で呼び出しています。非タスクコンテキストに対応するするには、SIL*1を使った方が便利かと思います。


*1 ITRONデバイスドライバ設計ガイドラインの一部分として検討されているシステムインタフェースレイヤのこと。TOPPERS/JSPカーネルは、そのサブセットをサポートしています。
2006/05/16 00:07|シグナル処理TB:0CM:0

コメント
コメントの投稿

管理者にだけ表示を許可する


トラックバック
トラックバックURLはこちら
http://libc.blog47.fc2.com/tb.php/54-45e79bf1

ホーム 全記事一覧 << 前の記事 次の記事 >>

ブログ内検索 

お勧め書籍 

RSSフィード 

リンク 

このブログをリンクに追加する

Powered By FC2ブログ 

Powered By FC2ブログ
ブログやるならFC2ブログ

Copyright(C) 2006 TAKAGI Nobuhisa All rights reserved.
Powered by FC2ブログ. 無料ホームページ アフィリエイト レンタルサーバー FC2ブログ 一戸建て template designed by 遥かなるわらしべ長者への挑戦.