aboutsummaryrefslogtreecommitdiff
path: root/libpager/lock-object.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpager/lock-object.c')
-rw-r--r--libpager/lock-object.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/libpager/lock-object.c b/libpager/lock-object.c
new file mode 100644
index 00000000..5182eff8
--- /dev/null
+++ b/libpager/lock-object.c
@@ -0,0 +1,105 @@
+/* Synchronous wrapper for memory_object_lock_request
+ Copyright (C) 1993, 1994, 1996, 1997 Free Software Foundation
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "priv.h"
+
+/* Request a lock from the kernel on pager P. Parameters OFFSET,
+ SIZE, SHOULD_RETURN, SHOULD_FLUSH, and LOCK_VALUE are as for
+ memory_object_lock_request. If SYNC is set, then wait for the
+ operation to fully complete before returning. */
+void
+_pager_lock_object (struct pager *p,
+ vm_offset_t offset,
+ vm_size_t size,
+ int should_return,
+ int should_flush,
+ vm_prot_t lock_value,
+ int sync)
+{
+ int i;
+ struct lock_request *lr = 0;
+
+ mutex_lock (&p->interlock);
+ if (p->pager_state != NORMAL)
+ {
+ mutex_unlock (&p->interlock);
+ return;
+ }
+
+ if (sync)
+ {
+ for (lr = p->lock_requests; lr; lr = lr->next)
+ if (lr->start == offset && lr->end == offset + size)
+ {
+ lr->locks_pending++;
+ lr->threads_waiting++;
+ break;
+ }
+ if (!lr)
+ {
+ lr = malloc (sizeof (struct lock_request));
+ lr->start = offset;
+ lr->end = offset + size;
+ lr->pending_writes = 0;
+ lr->locks_pending = 1;
+ lr->threads_waiting = 1;
+ lr->next = p->lock_requests;
+ if (lr->next)
+ lr->next->prevp = &lr->next;
+ lr->prevp = &p->lock_requests;
+ p->lock_requests = lr;
+ }
+ }
+
+ memory_object_lock_request (p->memobjcntl, offset, size, should_return,
+ should_flush, lock_value,
+ sync ? p->port.port_right : MACH_PORT_NULL);
+
+ if (sync)
+ {
+ while (lr->locks_pending || lr->pending_writes)
+ condition_wait (&p->wakeup, &p->interlock);
+
+ if (! --lr->threads_waiting)
+ {
+ *lr->prevp = lr->next;
+ if (lr->next)
+ lr->next->prevp = lr->prevp;
+ free (lr);
+ }
+
+ if (should_flush)
+ {
+ vm_offset_t pm_offs = offset / __vm_page_size;
+
+ _pager_pagemap_resize (p, offset + size);
+ if (p->pagemapsize > pm_offs)
+ {
+ char *pm_entries = &p->pagemap[pm_offs];
+ vm_offset_t bound = size / vm_page_size;
+
+ if (bound > p->pagemapsize)
+ bound = p->pagemapsize;
+
+ for (i = 0; i < bound; i++)
+ pm_entries[i] &= ~PM_INCORE;
+ }
+ }
+ }
+
+ mutex_unlock (&p->interlock);
+}