[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
mlock for the Hurd
From: |
James A Morrison |
Subject: |
mlock for the Hurd |
Date: |
Tue, 25 Mar 2003 23:38:57 -0500 (EST) |
Hey,
I figured I'd post this patch because it seems to work and I've toasted
another filesystem. Which means I'll have some more work to do to get a
decent build environment up again.
I've only done limiting testing on this. That is, I mmaped a few pages,
then mlocked them, the program did not return any errors. I tried to mmap
a gig of anonymous memory and mlock return invalid argument, so I assume the
mmap failed, thus causing mlock to fail. I then malloc'd a gig and tried to
mlock it. This didn't freeze my system, but did cause a kernel panic after
a minute or so. The error was something like panic: alloc pt zone exhausted",
which I assume means the kernel was wiring the memory and ran out.
I'm posting this here because I haven't had a chance to try the read loop.
If the read loop works properly then we can probably only use it.
Anyway, have fun.
James A. Morrison
2003-03-25 James A Morrison <ja2morri@uwaterloo.ca>
* mlock.c (mlock): Check the memory protections for the regions to
be locked and ensure each page is in memory before it is wired by
the kernel.
Index: mlock.c
===================================================================
RCS file: /cvs/glibc/libc/sysdeps/mach/hurd/mlock.c,v
retrieving revision 1.2
diff -u -r1.2 mlock.c
--- mlock.c 6 Jul 2001 04:55:57 -0000 1.2
+++ mlock.c 24 Mar 2003 00:44:41 -0000
@@ -1,5 +1,5 @@
/* mlock -- guarantee pages are resident in memory. Mach/Hurd version.
- Copyright (C) 2001 Free Software Foundation, Inc.
+ Copyright (C) 2001, 03 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -30,17 +30,90 @@
mlock (const void *addr, size_t len)
{
mach_port_t hostpriv;
- vm_address_t page;
+ vm_address_t page, working;
error_t err;
+ size_t remaining, wiring, size;
+ boolean_t shared;
+ vm_prot_t cur_prot, max_prot;
+ mach_port_t obj_name;
+ vm_offset_t offset;
+ vm_inherit_t inherit;
+ volatile char *poke;
+ volatile char ch;
+
+ static size_t touches = 1;
err = __get_privileged_ports (&hostpriv, NULL);
if (err)
return __hurd_fail (EPERM);
- page = trunc_page ((vm_address_t) addr);
- len = round_page ((vm_address_t) addr + len) - page;
- err = __vm_wire (hostpriv, __mach_task_self (), page, len,
- VM_PROT_ALL); /* XXX ? */
+ working = page = trunc_page ((vm_address_t) addr);
+ remaining = len = round_page ((vm_address_t) addr + len) - page;
+
+ do
+ {
+ size_t do_touch;
+ err = __vm_region (__mach_task_self (), &page, &size, &cur_prot,
+ &max_prot, &inherit, &shared, &obj_name, &offset);
+ if (err)
+ goto err_state;
+ else if (page != working)
+ {
+ err = ENOMEM;
+ goto err_state;
+ }
+
+ /* Prune size if it is larger than we need. */
+ size = size > remaining ? remaining : size;
+
+ for (working = page; working < (page + size);
+ working += (size_t)wiring)
+ {
+ do_touch = remaining / vm_page_size;
+ do_touch = do_touch > touches ? touches : do_touch;
+ wiring = do_touch * vm_page_size;
+
+ /* write to the page if we can. */
+ if (cur_prot & VM_PROT_WRITE)
+ for (poke = page; poke < working + wiring; poke += vm_page_size)
+ *poke = *poke;
+ else
+ for (poke = page; poke < working + wiring; poke += vm_page_size)
+ ch = *poke;
+
+ /* Use the current protection because the programmer should have the
+ correct protections in place before trying to do anything. It
+ looks safer this way as well. */
+ err = __vm_wire (hostpriv, __mach_task_self (), working, wiring,
+ cur_prot);
+ if (err)
+ goto err_state;
+
+ remaining -= wiring;
+ }
+
+ }
+ while (remaining);
+
+err_state:
+ if (err)
+ {
+ /* Assume the memory wasn't locked before, so we unlock it all to restore
+ the state it was in. */
+ working = page;
+ remaining = len - remaining;
+ while (remaining)
+ {
+ err = __vm_region (__mach_task_self (), &working, &size, &cur_prot,
+ &max_prot, &inherit, &shared, &obj_name, &offset);
+ size = size > remaining ? remaining : size;
+ err = __vm_wire (hostpriv, __mach_task_self (), working, wiring,
+ VM_PROT_NONE);
+
+ remaining -= size;
+ }
+ }
+
__mach_port_deallocate (__mach_task_self (), hostpriv);
return err ? __hurd_fail (err) : 0;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- mlock for the Hurd,
James A Morrison <=