トップ 最新 追記
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|10|12|
2009|02|03|06|07|10|11|12|
2010|01|02|03|04|07|09|10|11|12|
2011|01|03|04|05|06|07|08|10|
2012|01|06|08|09|10|12|
2013|01|02|03|04|07|09|11|12|
2014|01|03|04|05|06|09|
2015|04|
2016|01|08|
ここは旧えびめもです。えびめも2に移行します(2016/12/1)

2010年07月14日

なんか久しぶりです。

シリアルポートのデータ送信完了待ち処理を見てる。Cライブラリだと tcdrain(fd) の部分。Cライブラリのソースコードを追う
__libc_tcdrain (int fd)
{
  if (SINGLE_THREAD_P)
    /* With an argument of 1, TCSBRK for output to be drain.  */
    return INLINE_SYSCALL (ioctl, 3, fd, TCSBRK, 1);
 
  int oldtype = LIBC_CANCEL_ASYNC ();
 
  /* With an argument of 1, TCSBRK for output to be drain.  */
  int result = INLINE_SYSCALL (ioctl, 3, fd, TCSBRK, 1);
 
  LIBC_CANCEL_RESET (oldtype);
 
  return result;
}
TCSBRK ??? strace してみる
ioctl(3, TCSBRK, 0x1)                   = 0
確かに ioctlで TCSBRK してる。manpageを見てみる
manpage TTY_IOCTL
 
TCSBRK        int arg 
 
端末が非同期シリアルデータ転送を使用しており、 arg が 0 の場合、0.25 から 
0.5 秒の間に break (0 のビット列のストリーム) が送信される。端末が非同期
シリアルデータ転送を使用している場合、 break が送信されるか、この関数は何もせずに返る。 
arg が 0 以外の場合、何が起こるか分からない。 
何が起こるか分からない。だと?
SVr4, UnixWare, Solaris, Linux は、 tcsendbreak(fd,arg) の
 arg が 0 以外の場合、 tcdrain(fd) のように扱う。 
あーそうですか。
TCSBRK に隠しコマンドのように実装するんですか。なんとびっくり。

カーネル追っかけ

dirvers/serial/seria_core.c:uart_wait_until_sent() に到着
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
{
 略
	/*
	 * Check whether the transmitter is empty every 'char_time'.
	 * 'timeout' / 'expire' give us the maximum amount of time
	 * we wait.
	 */
	while (!port->ops->tx_empty(port)) {
		msleep_interruptible(jiffies_to_msecs(char_time));
		if (signal_pending(current))
			break;
		if (time_after(jiffies, expire))
			break;
	}
	set_current_state(TASK_RUNNING); /* might not be needed */
dirvers/serial/8250.c:serial8250_tx_empty()で空か調べている
 static unsigned int serial8250_tx_empty(struct uart_port *port)
 {
	struct uart_8250_port *up = (struct uart_8250_port *)port;
	unsigned long flags;
	unsigned int lsr;
 
	spin_lock_irqsave(&up->port.lock, flags);
	lsr = serial_in(up, UART_LSR);
	up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
	spin_unlock_irqrestore(&up->port.lock, flags);
 
	return lsr & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
}
なんだ。msleep() を挟んだポーリングか。 だとすると最悪値の上限は無いな・・・・

2010年07月23日

catboot

2年ぶりくらいにcatbootを改造している。元々catbootはROM上にコードを置いてROM上を走行する形式だったけど、コード全体をRAMにコピーしてRAM上を走行するように変更した。ldscriptの AT コマンドを使って LMA と VMA を区別すれば大丈夫。たいした改造ではなかった。

ところが Linuxを起動しようとするとLinuxがRAMをぶっ壊すのでcatbootも破壊される。すると sh-bios を使った early_printk が死ぬ。

もちろんkernel configure 時に SH-BIOS early printk support を外せばいいのだろうが、既存のコンパイル済み zImage を起動するには sh-bios の対応が必須だ。困ったもんだ。


2010年07月27日

C言語クイズ

問題1:次の結果は match でしょうか、 unmatch でしょうか
int main(void){
        int x;
        char c;
        x = 0xFF;
        c = 0xFF;
 
        if(x==c){
                printf("match\n");
        }else{
                printf("unmatch\n");
        }
        return 0;
}
では問題2は?
int main(void){
        int x;
        char c;
        x = c = 0xFF;      /* ここだけ変えた */
 
        if(x==c){
                printf("match\n");
        }else{
                printf("unmatch\n");
        }
        return 0;
}
では問題3は?
int main(void){
        int x;
        char c;
        c = x =  0xFF;      /* ここだけ変えた */
 
        if(x==c){
                printf("match\n");
        }else{
                printf("unmatch\n");
        }
        return 0;
}
答え unmatch, match, unmatch の順です。