ソース探検 > 01


※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

  • 先生:
    • 「それでは、今日の宿題はpauseコマンドです。Infernoがはじめてのみなさんにも簡単に読めるソースですので、忘れずにやってきてくださいね。」
  • デーモソ君:
    • 「は~い!」
どうやら中学校ではじめての宿題となったのはpauseコマンドのようです。デーモソ君は無事に宿題をこなすことができるでしょうか。
家に帰ったデーモソ君はさっそくノートPCを開きました。
  • デーモソ君:
    • 「まずはソースがどこにあるかだよね。manページに書いてあるかな?えいっ」
; man pause
SLEEP(1)

NAME
    sleep, pause - suspend execution for an interval

SYNOPSIS
    sleep n

    pause

DESCRIPTION
    Sleep suspends its own execution for n seconds before
    returning.

    Pause never returns, and is typically used to stop a command
    interpreter reading any more from the standard input.

SOURCE
    /appl/cmd/sleep.b
    /appl/cmd/pause.b

SEE ALSO
    sys-sleep(2)

                        Inferno Manual

デーモソ君の狙いどおり、SOURCEセクションにソースの場所が書かれていました。デーモソ君はつづけてソースを開きます。

implement Pause;
#
# init program to do nothing but pause
#

include "sys.m";
include "draw.m";

Pause: module
{
init: fn(nil: ref Draw->Context, nil: list of string);
};

init(nil: ref Draw->Context, nil: list of string)
{
<-chan of int;
}

  • デーモソ君:
    • 「うわっ、見たことない言語で書かれてるよ!えーん、えーん、パパー!」
  • パパ:
    • 「どうしたんだ?デソ。」
  • デーモソ君:
    • 「Infernoは、C言語じゃないんだ!」
  • パパ:
    • 「そりゃそうだ。Cは小学校までだ。これからはLimboだよ。」
  • デーモソ君:
    • 「Limbo?」
  • パパ:
    • 「そう。Infernoはそれ自体はCで書かれているけど、Inferno上で動くアプリケーションはLimboで書かれてる。分散アプリケーションを書くのに優れた言語だよ。」
  • デーモソ君:
    • 「そうなんだ。C言語とはどう違うの?」
  • パパ:
    • 「それは簡単には説明できないな。ちゃんとマニュアル *1 があるんだから読んでごらん。で、宿題は…pauseコマンドか。initがCのmainみたいなものだから、とりあえずそこから読んでみるといい。」

デーモソ君はあらためてinit関数を見てみました。

init(nil: ref Draw->Context, nil: list of string)
{
<-chan of int;
}

  • デーモソ君:
    • 「ここだけみても、やっぱりよくわからないんだ。どうして「<-chan of int;」だけでプロセスがブロックするの?」
  • パパ:
    • 「まず、"<-"はチャネルオペレータだね。Infernoはチャネルという機構でプロセス間通信を実現してるんだよ。Unixでいうパイプやソケットみたいなものだね。でもここでは送信元も送信先も明示していないね。」
  • デーモソ君:
    • 「そんな記述ができるんだ。でもこれだけじゃやっぱり何をやっているのかわかんないや。」
  • パパ:
    • 「『目に見えるものだけが真実ではない』と偉い人は言ってるだろう。Limboのソースだけでわからなければダンプしてみればいい。」

そう言ってパパはpause.disをダンプして見せてくれました。

; disdump /dis/pause.dis
newcw , $0, 44(fp)
recv 44(fp), 40(fp)
movp 0(mp), 44(fp)
ret
;

  • デーモソ君:
    • 「あのソースがたったこれだけなんだ。」
  • パパ:
    • 「これはInfernoの仮想マシンの命令だから、命令の意味はDisのマニュアル *2 を見てごらん。」

デーモソ君は各命令の意味を調べました。

newcx - Allocate channel

   Syntax:		newcw	dst
   		newcb	dst
   		newcl	dst
   		newcf	dst
   		newcp	dst
   		newcm	src, dst
   		newcmp	src, dst
   Function:	dst = new(Channel)

The newc instruction allocates a new channel of the specified type and stores a reference to the channel in dst. For the newcm instruction the source specifies the number of bytes of memory used by values sent on the channel (see the movm instruction above). For the newcmp instruction the first operand specifies a type descriptor giving the length of the structure and the location of pointers within the structure (see the movmp instruction above).

recv - Receive from channel

   Syntax:		recv	src, dst
   Function:	dst = <-src

The recv instruction receives a value from some other thread on the channel specified by the src operand. Communication is synchronous, so the calling thread will block until a corresponding send or alt is performed on the channel. The type of the received value is determined by the channel type and the dst operand specifies where to place the received value.

movp - Move pointer

   Syntax:		movp	src, dst
   Function:	destroy(dst)
   		dst = src
   		incref(src)

The movp instruction copies a pointer adjusting the reference counts to reflect the new pointers.

  • デーモソ君:
    • 「newcwはチャネルの生成、recvはチャネルからの受信、movpはポインタのコピーだね。」
  • パパ:
    • 「それだけ分かれば十分だ。大事なのは、チャネルの受信側はInfernoのスケジューラによって待ち状態にされる。次に実行状態になるのはチャネルから受信があった時、という事だ。」

パパはInferno上のプロセスの状態遷移図を描いてくれました。
(TODO:図の挿入)

  • パパ:
    • 「でもpauseコマンドの場合は、チャネルの送信側のプロセスもpauseコマンド自身だ。すでに待ち状態になってるプロセスがチャネルへデータの送信なんて出来ない。」
  • デーモソ君:
    • 「そうか。pauseコマンドは来るはずのないデータをずっと待ってる状態なんだね。」
  • パパ:
    • 「そのとおり。pauseコマンドはチャネルのしくみをうまく利用した例だな。」
  • デーモソ君:
    • 「でも先生は簡単に読めるって言ってたのに、ずいぶん難しかったなぁ。」
  • パパ:
    • 「読むことと理解することは違うってことさ。」
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。