Free Software programmer
Subscribe to a syndicated
feed of my weblog, brought to you by the wonders of
This blog existed before my current employment, and obviously
reflects my own opinions and not theirs.
This work is licensed under a Creative Commons Attribution 2.1 Australia License.
Categories of this blog:
All 2008 posts
All 2007 posts
All 2006 posts
All 2005 posts
All 2004 posts
Tue, 24 Oct 2006
The Linux kernel is one of the nicer pieces of complex code I've
worked on, but it's not without ugliness. Consider this function from
int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, int len, int write, int force,
struct page **pages, struct vm_area_struct **vmas);
This function get references to a number of user pages from address
"start". Features are as follows:
[/tech] permanent link
- The "mm" arg is always "tsk->mm" in the caller, in fact, it
doesn't make sense for them to be different. (Actually, it's not
clear that fs/aio.c does this correctly).
The "tsk" arg is always "current", the (global)
macro identifying the current task. AFAICT it will work with other
tasks, so it's not a fundamental constraint. [This is crap:
DaveM points out that ptrace is the obvious case where tsk != current.
See mm/memory.c's access_process_vm().]
- It returns the number of pages it got, or -EFAULT, or -ENOMEM.
This makes for some interesting error handling in the caller: if we
run out of memory or hit a bad address after getting N pages, we
return N. The caller presumably notes that not all the pages were
retrieved, and unmaps the first N pages.
- "len", unlike the name suggests, is actually the number of pages,
not the length in bytes. This one bit me.
- write and force are booleans, but the kernel doesn't use "bool".
I've come to like bool for its documentation value.
- Naturally, there's no documentation on this function.