*
* from: @(#)pmap.c 7.7 (Berkeley) 5/12/91
* $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $
- * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.32 2004/03/01 06:33:16 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/pmap.c,v 1.33 2004/04/01 17:58:00 dillon Exp $
*/
/*
* note that in order for the mapping to take effect -- you
* should do a invltlb after doing the pmap_kenter...
*/
-PMAP_INLINE void
+void
pmap_kenter(vm_offset_t va, vm_paddr_t pa)
{
unsigned *pte;
pmap_inval_flush(&info);
}
+void
+pmap_kenter_quick(vm_offset_t va, vm_paddr_t pa)
+{
+ unsigned *pte;
+ unsigned npte;
+
+ npte = pa | PG_RW | PG_V | pgeflag;
+ pte = (unsigned *)vtopte(va);
+ *pte = npte;
+ cpu_invlpg((void *)va);
+}
+
+void
+pmap_kenter_sync(vm_offset_t va)
+{
+ pmap_inval_info info;
+
+ pmap_inval_init(&info);
+ pmap_inval_add(&info, kernel_pmap, va);
+ pmap_inval_flush(&info);
+}
+
+void
+pmap_kenter_sync_quick(vm_offset_t va)
+{
+ cpu_invlpg((void *)va);
+}
+
/*
* remove a page from the kernel pagetables
*/
-PMAP_INLINE void
+void
pmap_kremove(vm_offset_t va)
{
unsigned *pte;
pmap_inval_flush(&info);
}
+void
+pmap_kremove_quick(vm_offset_t va)
+{
+ unsigned *pte;
+ pte = (unsigned *)vtopte(va);
+ *pte = 0;
+ cpu_invlpg((void *)va);
+}
+
/*
* Used to map a range of physical addresses into kernel
* virtual address space.
panic("pmap_swapout_proc: upage already missing???");
vm_page_dirty(m);
vm_page_unwire(m, 0);
- pmap_kremove( (vm_offset_t) p->p_addr + PAGE_SIZE * i);
+ pmap_kremove((vm_offset_t)p->p_addr + (PAGE_SIZE * i));
}
#endif
}
m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
- pmap_kenter(((vm_offset_t) p->p_addr) + i * PAGE_SIZE,
+ pmap_kenter((vm_offset_t)p->p_addr + (i * PAGE_SIZE),
VM_PAGE_TO_PHYS(m));
if (m->valid != VM_PAGE_BITS_ALL) {
{
pmap->pm_pdir =
(pd_entry_t *)kmem_alloc_pageable(kernel_map, PAGE_SIZE);
- pmap_kenter((vm_offset_t) pmap->pm_pdir, (vm_offset_t) IdlePTD);
+ pmap_kenter((vm_offset_t)pmap->pm_pdir, (vm_offset_t) IdlePTD);
pmap->pm_count = 1;
pmap->pm_active = 0;
pmap->pm_ptphint = NULL;
vm_page_flag_clear(ptdpg, PG_MAPPED | PG_BUSY); /* not usually mapped*/
ptdpg->valid = VM_PAGE_BITS_ALL;
- pmap_kenter((vm_offset_t) pmap->pm_pdir, VM_PAGE_TO_PHYS(ptdpg));
+ pmap_kenter((vm_offset_t)pmap->pm_pdir, VM_PAGE_TO_PHYS(ptdpg));
if ((ptdpg->flags & PG_ZERO) == 0)
bzero(pmap->pm_pdir, PAGE_SIZE);
bzero(pde + KPTDI, nkpt * PTESIZE);
pde[MPPTDI] = 0;
pde[APTDPTDI] = 0;
- pmap_kremove((vm_offset_t) pmap->pm_pdir);
+ pmap_kremove((vm_offset_t)pmap->pm_pdir);
}
if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex))
*
* @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
* $FreeBSD: src/sys/i386/i386/uio_machdep.c,v 1.1 2004/03/21 20:28:36 alc Exp $
- * $DragonFly: src/sys/i386/i386/Attic/uio_machdep.c,v 1.2 2004/03/29 15:46:15 dillon Exp $
+ * $DragonFly: src/sys/i386/i386/Attic/uio_machdep.c,v 1.3 2004/04/01 17:58:00 dillon Exp $
*/
#include <sys/param.h>
page_offset = offset & PAGE_MASK;
cnt = min(cnt, PAGE_SIZE - page_offset);
m = ma[offset >> PAGE_SHIFT];
- sf = sf_buf_alloc(m);
+ sf = sf_buf_alloc(m, SFBA_QUICK);
cp = (char *)sf_buf_kva(sf) + page_offset;
switch (uio->uio_segflg) {
case UIO_USERSPACE:
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/kern_sfbuf.c,v 1.2 2004/03/29 15:46:18 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_sfbuf.c,v 1.3 2004/04/01 17:58:02 dillon Exp $
*/
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/sfbuf.h>
+#include <sys/globaldata.h>
+#include <sys/thread.h>
+#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/vm_kern.h>
#include <vm/vm_page.h>
#include <vm/pmap.h>
+#include <sys/thread2.h>
static void sf_buf_init(void *arg);
SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL)
static vm_offset_t sf_base;
static struct sf_buf *sf_bufs;
+static int sfbuf_quick = 1;
+SYSCTL_INT(_debug, OID_AUTO, sfbuf_quick, CTLFLAG_RW, &sfbuf_quick, 0, "");
+
/*
* Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-))
*/
M_NOWAIT | M_ZERO);
for (i = 0; i < nsfbufs; i++) {
sf_bufs[i].kva = sf_base + i * PAGE_SIZE;
+ sf_bufs[i].flags |= SFBA_ONFREEQ;
TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry);
}
}
* Get an sf_buf from the freelist. Will block if none are available.
*/
struct sf_buf *
-sf_buf_alloc(struct vm_page *m)
+sf_buf_alloc(struct vm_page *m, int flags)
{
struct sf_buf_list *hash_chain;
struct sf_buf *sf;
- int s;
+ globaldata_t gd;
int error;
+ int pflags;
- s = splimp();
+ gd = mycpu;
+ crit_enter();
hash_chain = &sf_buf_hashtable[SF_BUF_HASH(m)];
LIST_FOREACH(sf, hash_chain, list_entry) {
if (sf->m == m) {
- if (sf->refcnt == 0) {
- /* reclaim cached entry off freelist */
- TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
- }
+ /*
+ * cache hit
+ *
+ * We must invalidate the TLB entry based on whether
+ * it need only be valid on the local cpu (SFBA_QUICK),
+ * or on all cpus. This is conditionalized and in
+ * most cases no system-wide invalidation should be
+ * needed.
+ *
+ * Note: we do not remove the entry from the freelist
+ * on the 0->1 transition.
+ */
++sf->refcnt;
+ if ((flags & SFBA_QUICK) && sfbuf_quick) {
+ if ((sf->cpumask & gd->gd_cpumask) == 0) {
+ pmap_kenter_sync_quick(sf->kva);
+ sf->cpumask |= gd->gd_cpumask;
+ }
+ } else {
+ if (sf->cpumask != (cpumask_t)-1) {
+ pmap_kenter_sync(sf->kva);
+ sf->cpumask = (cpumask_t)-1;
+ }
+ }
goto done; /* found existing mapping */
}
}
/*
- * Didn't find old mapping. Get a buffer off the freelist.
+ * Didn't find old mapping. Get a buffer off the freelist. We
+ * may have to remove and skip buffers with non-zero ref counts
+ * that were lazily allocated.
*/
- while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) {
- ++sf_buf_alloc_want;
- error = tsleep(&sf_buf_freelist, PCATCH, "sfbufa", 0);
- --sf_buf_alloc_want;
-
- /* If we got a signal, don't risk going back to sleep. */
- if (error)
- goto done;
+ for (;;) {
+ if ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) {
+ pflags = (flags & SFBA_PCATCH) ? PCATCH : 0;
+ ++sf_buf_alloc_want;
+ error = tsleep(&sf_buf_freelist, pflags, "sfbufa", 0);
+ --sf_buf_alloc_want;
+ if (error)
+ goto done;
+ } else {
+ /*
+ * We may have to do delayed removals for referenced
+ * sf_buf's here in addition to locating a sf_buf
+ * to reuse. The sf_bufs must be removed.
+ *
+ * We are finished when we find an sf_buf with a
+ * refcnt of 0. We theoretically do not have to
+ * remove it from the freelist but it's a good idea
+ * to do so to preserve LRU operation for the
+ * (1) never before seen before case and (2)
+ * accidently recycled due to prior cached uses not
+ * removing the buffer case.
+ */
+ KKASSERT(sf->flags & SFBA_ONFREEQ);
+ TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
+ sf->flags &= ~SFBA_ONFREEQ;
+ if (sf->refcnt == 0)
+ break;
+ }
}
- TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
-
if (sf->m != NULL) /* remove previous mapping from hash table */
LIST_REMOVE(sf, list_entry);
LIST_INSERT_HEAD(hash_chain, sf, list_entry);
sf->refcnt = 1;
sf->m = m;
- pmap_qenter(sf->kva, &sf->m, 1);
+ if ((flags & SFBA_QUICK) && sfbuf_quick) {
+ pmap_kenter_quick(sf->kva, sf->m->phys_addr);
+ sf->cpumask = gd->gd_cpumask;
+ } else {
+ pmap_kenter(sf->kva, sf->m->phys_addr);
+ sf->cpumask = (cpumask_t)-1;
+ }
done:
- splx(s);
+ crit_exit();
return (sf);
}
/*
* Lose a reference to an sf_buf. When none left, detach mapped page
- * and release resources back to the system.
+ * and release resources back to the system. Note that the sfbuf's
+ * removal from the freelist is delayed, so it may in fact already be
+ * on the free list. This is the optimal (and most likely) scenario.
*
* Must be called at splimp.
*/
if (sf->refcnt == 0)
panic("sf_buf_free: freeing free sf_buf");
sf->refcnt--;
- if (sf->refcnt == 0) {
+ if (sf->refcnt == 0 && (sf->flags & SFBA_ONFREEQ) == 0) {
KKASSERT(sf->aux1 == 0 && sf->aux2 == 0);
TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry);
+ sf->flags |= SFBA_ONFREEQ;
if (sf_buf_alloc_want > 0)
wakeup_one(&sf_buf_freelist);
}
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/kern/kern_xio.c,v 1.2 2004/03/31 22:08:32 dillon Exp $
+ * $DragonFly: src/sys/kern/kern_xio.c,v 1.3 2004/04/01 17:58:02 dillon Exp $
*/
/*
* Kernel XIO interface. An initialized XIO is basically a collection of
error = 0;
for (i = xio->xio_offset >> PAGE_SHIFT; i < xio->xio_npages; ++i) {
m = xio->xio_pages[i];
- sf = sf_buf_alloc(m);
+ sf = sf_buf_alloc(m, SFBA_QUICK);
error = copyout((char *)sf_buf_kva(sf) + offset, uptr, n);
sf_buf_free(sf);
if (error)
error = 0;
for (i = xio->xio_offset >> PAGE_SHIFT; i < xio->xio_npages; ++i) {
m = xio->xio_pages[i];
- sf = sf_buf_alloc(m);
+ sf = sf_buf_alloc(m, SFBA_QUICK);
bcopy((char *)sf_buf_kva(sf) + offset, kptr, n);
sf_buf_free(sf);
bytes -= n;
* are met.
*
* $FreeBSD: src/sys/kern/sys_pipe.c,v 1.60.2.13 2002/08/05 15:05:15 des Exp $
- * $DragonFly: src/sys/kern/sys_pipe.c,v 1.16 2004/03/30 19:14:11 dillon Exp $
+ * $DragonFly: src/sys/kern/sys_pipe.c,v 1.17 2004/04/01 17:58:02 dillon Exp $
*/
/*
static __inline void pipeselwakeup (struct pipe *cpipe);
#ifndef PIPE_NODIRECT
static int pipe_build_write_buffer (struct pipe *wpipe, struct uio *uio);
-static void pipe_destroy_write_buffer (struct pipe *wpipe);
static int pipe_direct_write (struct pipe *wpipe, struct uio *uio);
static void pipe_clone_write_buffer (struct pipe *wpipe);
#endif
nread += size;
#ifndef PIPE_NODIRECT
/*
- * Direct copy, bypassing a kernel buffer.
+ * Direct copy, bypassing a kernel buffer. We cannot mess
+ * with the direct-write buffer until PIPE_DIRECTIP is
+ * cleared. In order to prevent the pipe_write code from
+ * racing itself in direct_write, we set DIRECTIP when we
+ * clear DIRECTW after we have exhausted the buffer.
*/
- } else if ((size = rpipe->pipe_map.cnt) &&
- (rpipe->pipe_state & PIPE_DIRECTW)) {
- if (size > (u_int) uio->uio_resid)
- size = (u_int) uio->uio_resid;
- error = uiomove_fromphys(rpipe->pipe_map.ms,
- rpipe->pipe_map.pos, size, uio);
+ } else if (rpipe->pipe_map.xio_bytes &&
+ (rpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) == PIPE_DIRECTW) {
+ error = xio_uio_copy(&rpipe->pipe_map, uio, &size);
if (error)
break;
nread += size;
- rpipe->pipe_map.pos += size;
- rpipe->pipe_map.cnt -= size;
- if (rpipe->pipe_map.cnt == 0) {
+ if (rpipe->pipe_map.xio_bytes == 0) {
+ rpipe->pipe_state |= PIPE_DIRECTIP;
rpipe->pipe_state &= ~PIPE_DIRECTW;
wakeup(rpipe);
}
struct pipe *wpipe;
struct uio *uio;
{
+ int error;
u_int size;
- int i;
- vm_offset_t addr, endaddr;
- vm_paddr_t paddr;
size = (u_int) uio->uio_iov->iov_len;
if (size > wpipe->pipe_buffer.size)
size = wpipe->pipe_buffer.size;
+ if (size > XIO_INTERNAL_SIZE)
+ size = XIO_INTERNAL_SIZE;
- endaddr = round_page((vm_offset_t)uio->uio_iov->iov_base + size);
- addr = trunc_page((vm_offset_t)uio->uio_iov->iov_base);
- for (i = 0; addr < endaddr; addr += PAGE_SIZE, i++) {
- vm_page_t m;
-
- if (vm_fault_quick((caddr_t)addr, VM_PROT_READ) < 0 ||
- (paddr = pmap_kextract(addr)) == 0) {
- int j;
-
- for (j = 0; j < i; j++)
- vm_page_unhold(wpipe->pipe_map.ms[j]);
- return (EFAULT);
- }
-
- m = PHYS_TO_VM_PAGE(paddr);
- vm_page_hold(m);
- wpipe->pipe_map.ms[i] = m;
- }
-
- /*
- * set up the control block
- */
- wpipe->pipe_map.npages = i;
- wpipe->pipe_map.pos =
- ((vm_offset_t) uio->uio_iov->iov_base) & PAGE_MASK;
- wpipe->pipe_map.cnt = size;
+ error = xio_init_ubuf(&wpipe->pipe_map, uio->uio_iov->iov_base,
+ size, XIOF_READ);
+ if (error)
+ return(error);
/*
* and update the uio data
}
/*
- * unmap and unwire the process buffer
- */
-static void
-pipe_destroy_write_buffer(wpipe)
- struct pipe *wpipe;
-{
- int i;
-
- for (i = 0; i < wpipe->pipe_map.npages; i++) {
- vm_page_unhold(wpipe->pipe_map.ms[i]);
- wpipe->pipe_map.ms[i] = NULL; /* sanity */
- }
- wpipe->pipe_map.npages = 0;
-}
-
-/*
* In the case of a signal, the writing process might go away. This
* code copies the data into the circular buffer so that the source
* pages can be freed without loss of data.
pipe_clone_write_buffer(wpipe)
struct pipe *wpipe;
{
- struct uio uio;
- struct iovec iov;
int size;
- int pos;
- size = wpipe->pipe_map.cnt;
- pos = wpipe->pipe_map.pos;
+ size = wpipe->pipe_map.xio_bytes;
wpipe->pipe_buffer.in = size;
wpipe->pipe_buffer.out = 0;
wpipe->pipe_buffer.cnt = size;
- wpipe->pipe_state &= ~PIPE_DIRECTW;
-
- iov.iov_base = wpipe->pipe_buffer.buffer;
- iov.iov_len = size;
- uio.uio_iov = &iov;
- uio.uio_iovcnt = 1;
- uio.uio_offset = 0;
- uio.uio_resid = size;
- uio.uio_segflg = UIO_SYSSPACE;
- uio.uio_rw = UIO_READ;
- uio.uio_td = curthread;
- uiomove_fromphys(wpipe->pipe_map.ms, pos, size, &uio);
-
- pipe_destroy_write_buffer(wpipe);
+ wpipe->pipe_state &= ~(PIPE_DIRECTW | PIPE_DIRECTIP);
+
+ xio_copy_xtok(&wpipe->pipe_map, wpipe->pipe_buffer.buffer, size);
+ xio_release(&wpipe->pipe_map);
}
/*
int error;
retry:
- while (wpipe->pipe_state & PIPE_DIRECTW) {
+ while (wpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) {
if (wpipe->pipe_state & PIPE_WANTR) {
wpipe->pipe_state &= ~PIPE_WANTR;
wakeup(wpipe);
wpipe->pipe_state |= PIPE_WANTW;
error = tsleep(wpipe, PCATCH, "pipdww", 0);
if (error)
- goto error1;
+ goto error2;
if (wpipe->pipe_state & PIPE_EOF) {
error = EPIPE;
- goto error1;
+ goto error2;
}
}
- wpipe->pipe_map.cnt = 0; /* transfer not ready yet */
+ KKASSERT(wpipe->pipe_map.xio_bytes == 0);
if (wpipe->pipe_buffer.cnt > 0) {
if (wpipe->pipe_state & PIPE_WANTR) {
wpipe->pipe_state &= ~PIPE_WANTR;
wpipe->pipe_state |= PIPE_WANTW;
error = tsleep(wpipe, PCATCH, "pipdwc", 0);
if (error)
- goto error1;
+ goto error2;
if (wpipe->pipe_state & PIPE_EOF) {
error = EPIPE;
- goto error1;
+ goto error2;
}
goto retry;
}
/*
* Build our direct-write buffer
*/
- wpipe->pipe_state |= PIPE_DIRECTW;
+ wpipe->pipe_state |= PIPE_DIRECTW | PIPE_DIRECTIP;
error = pipe_build_write_buffer(wpipe, uio);
- if (error) {
- wpipe->pipe_state &= ~PIPE_DIRECTW;
+ if (error)
goto error1;
- }
+ wpipe->pipe_state &= ~PIPE_DIRECTIP;
/*
* Wait until the receiver has snarfed the data. Since we are likely
while (!error && (wpipe->pipe_state & PIPE_DIRECTW)) {
if (wpipe->pipe_state & PIPE_EOF) {
pipelock(wpipe, 0);
- pipe_destroy_write_buffer(wpipe);
+ xio_release(&wpipe->pipe_map);
pipeunlock(wpipe);
pipeselwakeup(wpipe);
error = EPIPE;
pipeselwakeup(wpipe);
error = tsleep(wpipe, PCATCH|PNORESCHED, "pipdwt", 0);
}
-
pipelock(wpipe,0);
if (wpipe->pipe_state & PIPE_DIRECTW) {
/*
* the process that might be going away.
*/
pipe_clone_write_buffer(wpipe);
+ KKASSERT((wpipe->pipe_state & PIPE_DIRECTIP) == 0);
} else {
- pipe_destroy_write_buffer(wpipe);
+ KKASSERT(wpipe->pipe_state & PIPE_DIRECTIP);
+ xio_release(&wpipe->pipe_map);
+ wpipe->pipe_state &= ~PIPE_DIRECTIP;
}
pipeunlock(wpipe);
return (error);
+ /*
+ * Direct-write error, clear the direct write flags.
+ */
error1:
+ wpipe->pipe_state &= ~(PIPE_DIRECTW | PIPE_DIRECTIP);
+ /* fallthrough */
+
+ /*
+ * General error, wakeup the other side if it happens to be sleeping.
+ */
+error2:
wakeup(wpipe);
return (error);
}
*/
if ((uio->uio_resid > PIPE_SIZE) &&
(pipe_nbig < pipe_maxbig) &&
- (wpipe->pipe_state & PIPE_DIRECTW) == 0 &&
+ (wpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) == 0 &&
(wpipe->pipe_buffer.size <= PIPE_SIZE) &&
(wpipe->pipe_buffer.cnt == 0)) {
* reader goes away.
*/
retrywrite:
- while (wpipe->pipe_state & PIPE_DIRECTW) {
+ while (wpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) {
if (wpipe->pipe_state & PIPE_WANTR) {
wpipe->pipe_state &= ~PIPE_WANTR;
wakeup(wpipe);
* It is possible for a direct write to
* slip in on us... handle it here...
*/
- if (wpipe->pipe_state & PIPE_DIRECTW) {
+ if (wpipe->pipe_state & (PIPE_DIRECTW|PIPE_DIRECTIP)) {
pipeunlock(wpipe);
goto retrywrite;
}
return (0);
case FIONREAD:
- if (mpipe->pipe_state & PIPE_DIRECTW)
- *(int *)data = mpipe->pipe_map.cnt;
- else
+ if (mpipe->pipe_state & PIPE_DIRECTW) {
+ *(int *)data = mpipe->pipe_map.xio_bytes;
+ } else {
*(int *)data = mpipe->pipe_buffer.cnt;
+ }
return (0);
case FIOSETOWN:
cpipe->pipe_buffer.object = NULL;
}
#ifndef PIPE_NODIRECT
- cpipe->pipe_map.cnt = 0;
- cpipe->pipe_map.pos = 0;
- cpipe->pipe_map.npages = 0;
+ KKASSERT(cpipe->pipe_map.xio_bytes == 0 &&
+ cpipe->pipe_map.xio_offset == 0 &&
+ cpipe->pipe_map.xio_npages == 0);
#endif
}
pipe_free_kmem(cpipe);
free(cpipe, M_PIPE);
} else {
- KKASSERT(cpipe->pipe_map.npages == 0);
-
+ KKASSERT(cpipe->pipe_map.xio_npages == 0 &&
+ cpipe->pipe_map.xio_bytes == 0 &&
+ cpipe->pipe_map.xio_offset == 0);
cpipe->pipe_state = 0;
cpipe->pipe_busy = 0;
- cpipe->pipe_map.cnt = 0;
- cpipe->pipe_map.pos = 0;
cpipe->pipe_peer = gd->gd_pipeq;
gd->gd_pipeq = cpipe;
++gd->gd_pipeqcount;
kn->kn_data = rpipe->pipe_buffer.cnt;
if ((kn->kn_data == 0) && (rpipe->pipe_state & PIPE_DIRECTW))
- kn->kn_data = rpipe->pipe_map.cnt;
+ kn->kn_data = rpipe->pipe_map.xio_bytes;
if ((rpipe->pipe_state & PIPE_EOF) ||
(wpipe == NULL) || (wpipe->pipe_state & PIPE_EOF)) {
*
* @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
* $FreeBSD: src/sys/kern/uipc_syscalls.c,v 1.65.2.17 2003/04/04 17:11:16 tegge Exp $
- * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.29 2004/03/29 15:46:18 dillon Exp $
+ * $DragonFly: src/sys/kern/uipc_syscalls.c,v 1.30 2004/04/01 17:58:02 dillon Exp $
*/
#include "opt_ktrace.h"
* Get a sendfile buf. We usually wait as long as necessary,
* but this wait can be interrupted.
*/
- if ((sf = sf_buf_alloc(pg)) == NULL) {
+ if ((sf = sf_buf_alloc(pg, SFBA_PCATCH)) == NULL) {
s = splvm();
vm_page_unwire(pg, 0);
if (pg->wire_count == 0 && pg->object == NULL)
*
* from: @(#)pmap.c 7.7 (Berkeley) 5/12/91
* $FreeBSD: src/sys/i386/i386/pmap.c,v 1.250.2.18 2002/03/06 22:48:53 silby Exp $
- * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.32 2004/03/01 06:33:16 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/pmap.c,v 1.33 2004/04/01 17:58:00 dillon Exp $
*/
/*
* note that in order for the mapping to take effect -- you
* should do a invltlb after doing the pmap_kenter...
*/
-PMAP_INLINE void
+void
pmap_kenter(vm_offset_t va, vm_paddr_t pa)
{
unsigned *pte;
pmap_inval_flush(&info);
}
+void
+pmap_kenter_quick(vm_offset_t va, vm_paddr_t pa)
+{
+ unsigned *pte;
+ unsigned npte;
+
+ npte = pa | PG_RW | PG_V | pgeflag;
+ pte = (unsigned *)vtopte(va);
+ *pte = npte;
+ cpu_invlpg((void *)va);
+}
+
+void
+pmap_kenter_sync(vm_offset_t va)
+{
+ pmap_inval_info info;
+
+ pmap_inval_init(&info);
+ pmap_inval_add(&info, kernel_pmap, va);
+ pmap_inval_flush(&info);
+}
+
+void
+pmap_kenter_sync_quick(vm_offset_t va)
+{
+ cpu_invlpg((void *)va);
+}
+
/*
* remove a page from the kernel pagetables
*/
-PMAP_INLINE void
+void
pmap_kremove(vm_offset_t va)
{
unsigned *pte;
pmap_inval_flush(&info);
}
+void
+pmap_kremove_quick(vm_offset_t va)
+{
+ unsigned *pte;
+ pte = (unsigned *)vtopte(va);
+ *pte = 0;
+ cpu_invlpg((void *)va);
+}
+
/*
* Used to map a range of physical addresses into kernel
* virtual address space.
panic("pmap_swapout_proc: upage already missing???");
vm_page_dirty(m);
vm_page_unwire(m, 0);
- pmap_kremove( (vm_offset_t) p->p_addr + PAGE_SIZE * i);
+ pmap_kremove((vm_offset_t)p->p_addr + (PAGE_SIZE * i));
}
#endif
}
m = vm_page_grab(upobj, i, VM_ALLOC_NORMAL | VM_ALLOC_RETRY);
- pmap_kenter(((vm_offset_t) p->p_addr) + i * PAGE_SIZE,
+ pmap_kenter((vm_offset_t)p->p_addr + (i * PAGE_SIZE),
VM_PAGE_TO_PHYS(m));
if (m->valid != VM_PAGE_BITS_ALL) {
{
pmap->pm_pdir =
(pd_entry_t *)kmem_alloc_pageable(kernel_map, PAGE_SIZE);
- pmap_kenter((vm_offset_t) pmap->pm_pdir, (vm_offset_t) IdlePTD);
+ pmap_kenter((vm_offset_t)pmap->pm_pdir, (vm_offset_t) IdlePTD);
pmap->pm_count = 1;
pmap->pm_active = 0;
pmap->pm_ptphint = NULL;
vm_page_flag_clear(ptdpg, PG_MAPPED | PG_BUSY); /* not usually mapped*/
ptdpg->valid = VM_PAGE_BITS_ALL;
- pmap_kenter((vm_offset_t) pmap->pm_pdir, VM_PAGE_TO_PHYS(ptdpg));
+ pmap_kenter((vm_offset_t)pmap->pm_pdir, VM_PAGE_TO_PHYS(ptdpg));
if ((ptdpg->flags & PG_ZERO) == 0)
bzero(pmap->pm_pdir, PAGE_SIZE);
bzero(pde + KPTDI, nkpt * PTESIZE);
pde[MPPTDI] = 0;
pde[APTDPTDI] = 0;
- pmap_kremove((vm_offset_t) pmap->pm_pdir);
+ pmap_kremove((vm_offset_t)pmap->pm_pdir);
}
if (pmap->pm_ptphint && (pmap->pm_ptphint->pindex == p->pindex))
*
* @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
* $FreeBSD: src/sys/i386/i386/uio_machdep.c,v 1.1 2004/03/21 20:28:36 alc Exp $
- * $DragonFly: src/sys/platform/pc32/i386/Attic/uio_machdep.c,v 1.2 2004/03/29 15:46:15 dillon Exp $
+ * $DragonFly: src/sys/platform/pc32/i386/Attic/uio_machdep.c,v 1.3 2004/04/01 17:58:00 dillon Exp $
*/
#include <sys/param.h>
page_offset = offset & PAGE_MASK;
cnt = min(cnt, PAGE_SIZE - page_offset);
m = ma[offset >> PAGE_SHIFT];
- sf = sf_buf_alloc(m);
+ sf = sf_buf_alloc(m, SFBA_QUICK);
cp = (char *)sf_buf_kva(sf) + page_offset;
switch (uio->uio_segflg) {
case UIO_USERSPACE:
* are met.
*
* $FreeBSD: src/sys/sys/pipe.h,v 1.16 1999/12/29 04:24:45 peter Exp $
- * $DragonFly: src/sys/sys/pipe.h,v 1.4 2004/03/28 08:25:46 dillon Exp $
+ * $DragonFly: src/sys/sys/pipe.h,v 1.5 2004/04/01 17:58:06 dillon Exp $
*/
#ifndef _SYS_PIPE_H_
#ifndef _KERNEL
#include <sys/time.h> /* for struct timespec */
#include <sys/select.h> /* for struct selinfo */
-#include <vm/vm.h> /* for vm_page_t */
#include <machine/param.h> /* for PAGE_SIZE */
#endif
+#if !defined(_SYS_XIO_H_)
+#include <sys/xio.h> /* for struct xio */
+#endif
+
/*
* Pipe buffer size, keep moderate in value, pipes take kva space.
*/
#define PIPE_MINDIRECT 8192
#endif
-#define PIPENPAGES (BIG_PIPE_SIZE / PAGE_SIZE + 1)
-
/*
* Pipe buffer information.
* Separate in, out, cnt are used to simplify calculations.
};
/*
- * Information to support direct transfers between processes for pipes.
- */
-struct pipemapping {
- vm_size_t cnt; /* number of chars in buffer */
- vm_size_t pos; /* current position of transfer */
- int npages; /* number of pages */
- vm_page_t ms[PIPENPAGES]; /* pages in source process */
-};
-
-/*
* Bits in pipe_state.
*/
-#define PIPE_ASYNC 0x004 /* Async? I/O. */
-#define PIPE_WANTR 0x008 /* Reader wants some characters. */
-#define PIPE_WANTW 0x010 /* Writer wants space to put characters. */
-#define PIPE_WANT 0x020 /* Pipe is wanted to be run-down. */
-#define PIPE_SEL 0x040 /* Pipe has a select active. */
-#define PIPE_EOF 0x080 /* Pipe is in EOF condition. */
-#define PIPE_LOCK 0x100 /* Process has exclusive access to pointers/data. */
-#define PIPE_LWANT 0x200 /* Process wants exclusive access to pointers/data. */
-#define PIPE_DIRECTW 0x400 /* Pipe direct write active. */
-#define PIPE_DIRECTOK 0x800 /* Direct mode ok. */
+#define PIPE_ASYNC 0x0004 /* Async? I/O. */
+#define PIPE_WANTR 0x0008 /* Reader wants some characters. */
+#define PIPE_WANTW 0x0010 /* Writer wants space to put characters. */
+#define PIPE_WANT 0x0020 /* Pipe is wanted to be run-down. */
+#define PIPE_SEL 0x0040 /* Pipe has a select active. */
+#define PIPE_EOF 0x0080 /* Pipe is in EOF condition. */
+#define PIPE_LOCK 0x0100 /* Process has exclusive access to pointers/data. */
+#define PIPE_LWANT 0x0200 /* Process wants exclusive access to pointers/data. */
+#define PIPE_DIRECTW 0x0400 /* Pipe direct write active. */
+#define PIPE_DIRECTOK 0x0800 /* Direct mode ok. */
+#define PIPE_DIRECTIP 0x1000 /* Direct write buffer build in progress */
/*
* Per-pipe data structure.
*/
struct pipe {
struct pipebuf pipe_buffer; /* data storage */
- struct pipemapping pipe_map; /* pipe mapping for direct I/O */
+ struct xio pipe_map; /* mapping for direct I/O */
struct selinfo pipe_sel; /* for compat with select */
struct timespec pipe_atime; /* time of last access */
struct timespec pipe_mtime; /* time of last modify */
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $DragonFly: src/sys/sys/sfbuf.h,v 1.3 2004/03/29 15:46:21 dillon Exp $
+ * $DragonFly: src/sys/sys/sfbuf.h,v 1.4 2004/04/01 17:58:06 dillon Exp $
*/
#ifndef _SFBUF_H_
struct vm_page *m; /* currently mapped page */
vm_offset_t kva; /* va of mapping */
int refcnt; /* usage of this mapping */
+ int flags; /* global SFBA flags */
+ cpumask_t cpumask; /* cpu mapping synchronization */
int aux1; /* auxillary counter TEMPORARY HACK */
int aux2; /* auxillary counter TEMPORARY HACK */
};
+/*
+ * sf_buf_alloc() flags (not all are stored in sf->flags)
+ */
+#define SFBA_QUICK 0x0001 /* sync mapping to current cpu only */
+#define SFBA_ONFREEQ 0x0002 /* on the free queue (lazy move) */
+#define SFBA_PCATCH 0x0004 /* allow interruption */
+
static __inline vm_offset_t
sf_buf_kva(struct sf_buf *sf)
{
extern int nsfbufs;
-struct sf_buf *sf_buf_alloc(struct vm_page *);
+struct sf_buf *sf_buf_alloc(struct vm_page *, int flags);
void sf_buf_free(struct sf_buf *);
void sf_buf_ref(struct sf_buf *);
struct sf_buf *sf_buf_tosf(caddr_t addr);
* rights to redistribute these changes.
*
* $FreeBSD: src/sys/vm/pmap.h,v 1.33.2.4 2002/03/06 22:44:24 silby Exp $
- * $DragonFly: src/sys/vm/pmap.h,v 1.9 2004/01/18 12:29:50 dillon Exp $
+ * $DragonFly: src/sys/vm/pmap.h,v 1.10 2004/04/01 17:58:08 dillon Exp $
*/
/*
void pmap_init (vm_paddr_t, vm_paddr_t);
boolean_t pmap_is_modified (vm_page_t m);
boolean_t pmap_ts_referenced (vm_page_t m);
-void pmap_kenter (vm_offset_t va, vm_paddr_t pa);
-void pmap_kremove (vm_offset_t);
vm_offset_t pmap_map (vm_offset_t, vm_paddr_t, vm_paddr_t, int);
void pmap_object_init_pt (pmap_t pmap, vm_offset_t addr,
vm_object_t object, vm_pindex_t pindex, vm_offset_t size,
vm_prot_t);
void pmap_qenter (vm_offset_t, vm_page_t *, int);
void pmap_qremove (vm_offset_t, int);
+void pmap_kenter (vm_offset_t, vm_paddr_t);
+void pmap_kenter_quick (vm_offset_t, vm_paddr_t);
+void pmap_kenter_sync (vm_offset_t);
+void pmap_kenter_sync_quick (vm_offset_t);
+void pmap_kremove (vm_offset_t);
+void pmap_kremove_quick (vm_offset_t);
void pmap_reference (pmap_t);
void pmap_release (pmap_t);
void pmap_remove (pmap_t, vm_offset_t, vm_offset_t);