libdrawとlibthread

rioが実際にマウス(/dev/mouse)を読んで(read)いるところを追っていくと,libdrawというライブラリに行き着いた.libdrawはグラフィック関係のライブラリだ.rioは,libdrawが提供するreadmouse(2)関数を呼び出してマウスのデータを取得している.
libdrawではマウスやキーボードにアクセスするために_ioprocというプロセス(スレッド?)が存在して,libdraw関数を呼び出した(アプリケーション)プロセスとメッセージパッシングでデータの授受を行なっている.メッセージパッシングに使われるsend/recvはlibthreadによって提供されている.

readmouse関数の肝は,recv関数で,その第一引数はチャネル,第二引数は受信メッセージのバッファである.このチャネル(mc->c)を介してrioと_ioprocは通信する.

   33: int
   34: readmouse(Mousectl *mc)
   35: {
   36:         if(mc->image)
   37:                 flushimage(mc->image->display, 1);
   38:         if(recv(mc->c, &mc->Mouse) < 0){
   39:                 fprint(2, "readmouse: %r\n");
   40:                 return -1;
   41:         }
   42:         return 0;
   43: }

一方,_ioprocでは,61行目のreadでマウスからデータを読み込み(mc->mfdは/dev/mouseのファイル記述子である),Mouse構造体にパッキングして,sendしている.

libdraw/mouse.c
   45: static
   46: void
   47: _ioproc(void *arg)
   48: {

   51:         Mouse m;
   52:         Mousectl *mc;

   60:         for(;;){
   61:                 n = read(mc->mfd, buf, sizeof buf);

   70:                 switch(buf[0]){

   74:                 case 'm':
   75:                         m.xy.x = atoi(buf+1+0*12);
   76:                         m.xy.y = atoi(buf+1+1*12);
   77:                         m.buttons = atoi(buf+1+2*12);
   78:                         m.msec = atoi(buf+1+3*12);
   79:                         send(mc->c, &m);

おまけにlibdrawのマウス初期化関数も見ておこう.

libdraw/mouse.c
   91: Mousectl*
   92: initmouse(char *file, Image *i)
   93: {
   94:         Mousectl *mc;

  101:         mc->mfd = open(file, ORDWR|OCEXEC);

  120:         mc->c = chancreate(sizeof(Mouse), 0);

  122:         proccreate(_ioproc, mc, 4096);
  123:         return mc;
  124: }