0
votes

I want to implement a IPC in linux kernel. The idea is that:

  1. a producer process can write to a physical page

  2. a consumer process only can read this page

  3. a consumer process can't read this page until producer process fix this page (e.g. set the page to FIXSTATE)

My implementation is: when consumer process read this page, it will invoke a pagefualt.

The page fault handler will let the consumer pte (page table entry) point to the physical page, then suspend the consumer process. When producer process sets this page to FIXSTATE, producer will find the wait queue and wake up consumer process.

My question is:

According to my research, I can't call schedule() in page fault handler to suspend consumer process because it's in interrupt context. So I set the consumer process state to TASK_UNINTERRUPTIBLE, then call resched_task(current) to indicate current (consumer) process needs reschedule when return from pagefault handler. But resched_task is a static function in kernel/sched.c, it can't be called outside this file.

Is there some method to suspend/sleep the current process (the process invoke pagefault) in page fault handler?

thanks in advance for any answers!

2

2 Answers

2
votes

I think your premise is wrong. I don't understand every detail, but I think you should not be in interrupt context in the page fault handler. Since you've entered kernel mode via an exception, interrupts will be masked off (disabled) on entry. But you will have just come from user mode (well, ordinarily; sometimes a page fault can also occur from kernel mode but in "task context") so you will not be in an interrupt. Indeed, if you get a page fault from an interrupt handler, I can't see when that would not constitute a kernel bug.

An ordinary page fault (e.g. if your process needs to allocate a new page due to copy-on-write or to extend the stack or something) will eventually invoke handle_mm_fault. The first thing it does is set the state to TASK_RUNNING. Then it can either allocate a new page immediately, fix up PTEs, etc. (satisfying the page fault) and return to user-mode leaving state as TASK_RUNNING. Or it can block the process until memory is available which, somewhere along the way, will result in a call to schedule(), allowing other processes to run while it's blocked.

Sounds like you want to do essentially the same thing. So just look at what handle_mm_fault is doing.

(All that being said, I don't understand why you don't simply have the consuming process make a system call to "enter the consuming mode" which could block until the producer has finished "fixing" the page. The performance difference would seem to be so small as to be nearly unmeasurable. Indeed, the driver model already supports a file_operations table entry point to facilitate this sort of thing. If you go this direction, the core kernel will handle PTEs and other such details for you. See file_operations => mmap together with vm_operations_struct => fault)

0
votes

I have not completely read your question. But I know a generic way to suspend a process.

Create a wait queue .Remove the process from run queue and add to the wait queue, waiting for some event. When you want to awaken the process just send the event.