今日もへろへろ頭でがんばってみる

いい加減休んだ方がいいだろ、と自分でも思うのですが。
read とか write が微妙なのは十分承知なので追い掛けてみる事に。まず read から。

static ssize_t yamanetoshi_read(struct file *file, char __user *buf, size_t size, loff_t *offset)
{
	int i;

	if(NULL == write_task)
		return EOF;

i とか微妙だな。このあたりは現時点ではスルーとして次の if は書き込みなプロセスが fifo デバイスを開いてるかどうか、の判断。ちなみに EOF は無理矢理 (-1) で define してるのですがここが微妙なのかなぁ。一応テキストには EOF 戻せ、とあるな。
とりあえず動かないコトはないと見て次。

        for(i = 0; i < size; i++) {
                if(EOF == dequeue(&buf[i])) {
                        read_sleep = 1;
                        interruptible_sleep_on(&queue);
                }
        }

むーん。ココっぽい。sleep_on に渡す queue がナニ。ちなみに定義は以下。

static wait_queue_head_t queue;

これ、静的な領域に定義された変数なんで (しかも static で外部に対して隠蔽)、基本 NULL で初期化されるはず。sleep_on に NULL ポインタ渡して勝手に領域取って先頭ポインタをナニしてくれるのか、というあたりは微妙です。

あらら

sleep_on の定義を find|grep で探してみたら以下なカンジ

#define	SLEEP_ON_VAR					\
	unsigned long flags;				\
	wait_queue_t wait;				\
	init_waitqueue_entry(&wait, current);

#define SLEEP_ON_HEAD					\
	spin_lock_irqsave(&q->lock,flags);		\
	__add_wait_queue(q, &wait);			\
	spin_unlock(&q->lock);

#define	SLEEP_ON_TAIL					\
	spin_lock_irq(&q->lock);			\
	__remove_wait_queue(q, &wait);			\
	spin_unlock_irqrestore(&q->lock, flags);

void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
{
	SLEEP_ON_VAR

	current->state = TASK_INTERRUPTIBLE;

	SLEEP_ON_HEAD
	schedule();
	SLEEP_ON_TAIL
}
EXPORT_SYMBOL(interruptible_sleep_on);

これ、queue が NULL だと駄目だな。色々調べてみようとググッたら自分のエントリがあったりして凄くヘコむ。で、適当にソースツリーにあるソレを確認してたら以下の記述を発見

static DECLARE_WAIT_QUEUE_HEAD(ps2esdi_int);

わはは。これこれ。gtags で掘ってみると include/linux/wait.h にて以下

#define DECLARE_WAIT_QUEUE_HEAD(name) \
	wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)

__WAIT_QUEUE_HEAD_INITIALIZER は直上にて定義

#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {				\
	.lock		= __SPIN_LOCK_UNLOCKED(name.lock),		\
	.task_list	= { &(name).task_list, &(name).task_list } }

成程。ここが足らんかったのかな。とりあえず sleep_on する人は DECLARE_WAIT_QUEUE_HEAD マクロを使って queue のてっぺん定義しとけ、という事で。
最後のあたりも再度確認。

        if(!write_sleep) {
                write_sleep = 0;
                wake_up_process(write_task);
        }

        return size;

!write_sleep はダウト。でもそれ以前に buf (引数) が指す領域に dequeue で取り出したソレをコピーしてない (鬱
あ、違うな。dequeue が微妙なんだ。

        buf[0] = array[top];

ではなくて memcpy_tofs しないと駄目ですか。これは enqueue も同様ですねぇ。(memcpy_fromfs だったか)

実装は別途

と言いつつヤッてしまうかもしれませんが、とりあえずエントリ投入。