Given the feedback from the list, I've come up with two alternatives. (Well, one of them was actually Mechiel's brainchild).
Idea #1 (From Mechiel) Instead of doing typed allocations, give every user an allocation pool, from which all kernel allocations will take place. To extend on this, the size of the pool is somewhat dynamic -- as new users log in, all users' ability to consume kernel resources goes down by a fair percentage. (Except for eve.) As users log out, all users gain the percentage of resources back. The number is based on a 90% resource allocation -- i.e. the kernel may keep 10% of its initial resources for things it needs to do all by itself, without users interfering. When a malloc occurs with up, that size is stored in a counter. The proc also holds per-proc information, so that a username change can intelligently move only the resources from that proc over to the new user, instead of everything from the old user (which is clearly wrong). This implementation has one magic number: 0.9. The fair share is percentage based from that, but I'm not experience in fair share algorithms, so maybe there's a better way to do that. Also, the security of this implementation is provable. Downside is that this implementation is somewhat intrusive: introducing 9/port/kreslimit.c and touching 9/port/portdat.h, 9/port/portfns.h, 9/port/alloc.c, 9/port/proc.c, and 9/port/devcap.c I only have one question about implementation: where in process creation is the process username set? In newproc(), I see p->user set to "*nouser"; I can only assume this is `fixed' later, but I don't know where. I ask, because for natively started processes (i.e. not a user logging in from drawterm, that's handled through devcap), I need to incref on the proc structure that holds the user's pool info. I know I need to do this in e.g. #c/user, and devcap. But when a user starts a new process after logging in, it needs to add a ref. Where in proc.c (or elsewhere) is it finally determined who the user is? (Is that in renameuser()? I wasn't sure). Idea #2 Implement a similar thing as mult.bsd.lv. This would be implemented as a device and would give you a `blank' Plan 9 system: echo {cpushare} {maxmem} {newroot} > /dev/virtual/new I haven't thought a whole lot about how this would work, but I'm guessing at least the maxmem would be implemented similarly, by creating a new pool. I'd have to learn more about the scheduler to do the CPU limiting, and newroot would be as easy as a bind(). This would also be somewhat intrusive (but maybe not more so than Kreslimit), but has hard values, and provable security. (And the advantage of being able to spawn `new' Plan 9 instances from Plan 9.) More like jail(8) in FreeBSD (but much cleaner, due to its provability), less like vkernel(8) in DragonFly BSD. --dho