Simplify/streamline pipes a little bit:
- Allocate only one struct pipe not two (no need to be bidirectional here). - Then use f_flag (FREAD/FWRITE) to figure out what to do in the fileops. - Never wake the other side or acquire long-term (I/O) lock unless needed. - Whenever possible, defer wakeups until after locks have been released. - Do some things locklessly in pipe_ioctl() and pipe_poll(). Some notable results: - -30% latency on a 486DX2/66 doing 1 byte ping-pong within a single process. - 2.5x less lock contention during "make cleandir" of src on a 48 CPU machine. - 1.5x bandwith with 1kB messages on the same 48 CPU machine (8kB: same b/w).
This commit is contained in:
parent
3e9215f785
commit
61757a071b
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: db_command.c,v 1.186 2023/10/07 20:27:20 ad Exp $ */
|
||||
/* $NetBSD: db_command.c,v 1.187 2023/10/13 19:07:08 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996, 1997, 1998, 1999, 2002, 2009, 2019
|
||||
|
@ -61,7 +61,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.186 2023/10/07 20:27:20 ad Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: db_command.c,v 1.187 2023/10/13 19:07:08 ad Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_aio.h"
|
||||
|
@ -301,6 +301,8 @@ static const struct db_command db_show_cmds[] = {
|
|||
0 ,"List all used memory pages.",NULL,NULL) },
|
||||
{ DDB_ADD_CMD("panic", db_show_panic, 0,
|
||||
"Print the current panic string",NULL,NULL) },
|
||||
{ DDB_ADD_CMD("pipe", db_show_pipe,
|
||||
0 ,"Show the contents of a pipe.",NULL,NULL) },
|
||||
{ DDB_ADD_CMD("pool", db_pool_print_cmd, 0,
|
||||
"Print the pool at address.", "[/clp] address",NULL) },
|
||||
/* added from all sub cmds */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: db_interface.h,v 1.41 2023/10/07 20:27:20 ad Exp $ */
|
||||
/* $NetBSD: db_interface.h,v 1.42 2023/10/13 19:07:08 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995, 2023 The NetBSD Foundation, Inc.
|
||||
|
@ -86,6 +86,9 @@ void db_show_sleepq(db_expr_t, bool, db_expr_t, const char *);
|
|||
/* kern/kern_condvar.c */
|
||||
void db_show_condvar(db_expr_t, bool, db_expr_t, const char *);
|
||||
|
||||
/* kern/sys_pipe.c */
|
||||
void db_show_pipe(db_expr_t, bool, db_expr_t, const char *);
|
||||
|
||||
/* kern/sys_select.c */
|
||||
void db_show_selinfo(db_expr_t, bool, db_expr_t, const char *);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: db_xxx.c,v 1.77 2023/10/08 15:03:16 martin Exp $ */
|
||||
/* $NetBSD: db_xxx.c,v 1.78 2023/10/13 19:07:08 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1982, 1986, 1989, 1991, 1993
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.77 2023/10/08 15:03:16 martin Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.78 2023/10/13 19:07:08 ad Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_kgdb.h"
|
||||
|
@ -72,6 +72,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_xxx.c,v 1.77 2023/10/08 15:03:16 martin Exp $");
|
|||
#include <sys/condvar.h>
|
||||
#include <sys/sleepq.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/pipe.h>
|
||||
|
||||
#include <ddb/ddb.h>
|
||||
#include <ddb/db_user.h>
|
||||
|
@ -365,6 +366,51 @@ db_show_sleepq(db_expr_t addr, bool haddr, db_expr_t count, const char *modif)
|
|||
db_printf("\n");
|
||||
}
|
||||
|
||||
void
|
||||
db_show_pipe(db_expr_t addr, bool haddr, db_expr_t count, const char *modif)
|
||||
{
|
||||
struct pipe pipe, *ppipe = (struct pipe *)addr;
|
||||
|
||||
db_read_bytes(addr, sizeof(pipe), (char *)&pipe);
|
||||
|
||||
db_printf("pipe_lock\t\t%p\n", pipe.pipe_lock);
|
||||
|
||||
db_printf("pipe_read\t\t");
|
||||
db_show_condvar((db_addr_t)&ppipe->pipe_read, false, 0, modif);
|
||||
|
||||
db_printf("pipe_write\t\t");
|
||||
db_show_condvar((db_addr_t)&ppipe->pipe_write, false, 0, modif);
|
||||
|
||||
db_printf("pipe_busy\t\t");
|
||||
db_show_condvar((db_addr_t)&ppipe->pipe_busy, false, 0, modif);
|
||||
|
||||
db_printf("pipe_buffer.cnt\t\t%ld\n", (long)pipe.pipe_buffer.cnt);
|
||||
db_printf("pipe_buffer.in\t\t%d\n", pipe.pipe_buffer.in);
|
||||
db_printf("pipe_buffer.out\t\t%d\n", pipe.pipe_buffer.out);
|
||||
db_printf("pipe_buffer.size\t%ld\n", (long)pipe.pipe_buffer.size);
|
||||
db_printf("pipe_buffer.buffer\t%p\n", pipe.pipe_buffer.buffer);
|
||||
|
||||
db_printf("pipe_wrsel\t\t");
|
||||
db_show_selinfo((db_addr_t)&ppipe->pipe_wrsel, false, 0, modif);
|
||||
db_printf("pipe_rdsel\t\t");
|
||||
db_show_selinfo((db_addr_t)&ppipe->pipe_rdsel, false, 0, modif);
|
||||
|
||||
db_printf("pipe_atime\t\t");
|
||||
db_print_timespec(&pipe.pipe_atime);
|
||||
|
||||
db_printf("\npipe_mtime\t\t");
|
||||
db_print_timespec(&pipe.pipe_mtime);
|
||||
|
||||
db_printf("\npipe_btime\t\t");
|
||||
db_print_timespec(&pipe.pipe_btime);
|
||||
|
||||
db_printf("\npipe_kmem\t\t%lx\n", (long)pipe.pipe_kmem);
|
||||
db_printf("pipe_owner\t\t%p\n", pipe.pipe_owner);
|
||||
db_printf("pipe_wrpgid\t\t%d\n", pipe.pipe_wrpgid);
|
||||
db_printf("pipe_rdpgid\t\t%d\n", pipe.pipe_rdpgid);
|
||||
db_printf("pipe_state\t\t%#08x\n", pipe.pipe_state);
|
||||
}
|
||||
|
||||
void
|
||||
db_show_selinfo(db_expr_t addr, bool haddr, db_expr_t count, const char *modif)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pipe.h,v 1.39 2023/10/04 22:19:58 ad Exp $ */
|
||||
/* $NetBSD: pipe.h,v 1.40 2023/10/13 19:07:09 ad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1996 John S. Dyson
|
||||
|
@ -75,34 +75,34 @@ struct pipebuf {
|
|||
/*
|
||||
* Bits in pipe_state.
|
||||
*/
|
||||
#define PIPE_ASYNC 0x001 /* Async I/O */
|
||||
#define PIPE_EOF 0x010 /* Pipe is in EOF condition */
|
||||
#define PIPE_SIGNALR 0x020 /* Do selwakeup() on read(2) */
|
||||
#define PIPE_LOCKFL 0x100 /* Process has exclusive access to
|
||||
pointers/data. */
|
||||
/* unused 0x200 */
|
||||
#define PIPE_RESTART 0x400 /* Return ERESTART to blocked syscalls */
|
||||
#define PIPE_RDASYNC 0x001 /* Async I/O on reader side */
|
||||
#define PIPE_WRASYNC 0x002 /* Async I/O on writer side */
|
||||
#define PIPE_RDOPEN 0x010 /* Reader side open */
|
||||
#define PIPE_WROPEN 0x020 /* Writer side open */
|
||||
#define PIPE_EOF 0x100 /* Pipe is in EOF condition */
|
||||
#define PIPE_SIGNALR 0x200 /* Do selwakeup() on read(2) */
|
||||
#define PIPE_RESIZED 0x400 /* Attempted to resize */
|
||||
|
||||
/*
|
||||
* Per-pipe data structure.
|
||||
* Two of these are linked together to produce bi-directional pipes.
|
||||
*/
|
||||
struct pipe {
|
||||
kmutex_t *pipe_lock; /* pipe mutex */
|
||||
kcondvar_t pipe_rcv; /* cv for readers */
|
||||
kcondvar_t pipe_wcv; /* cv for writers */
|
||||
kcondvar_t pipe_draincv; /* cv for close */
|
||||
kcondvar_t pipe_lkcv; /* locking */
|
||||
struct pipebuf pipe_buffer; /* data storage */
|
||||
struct selinfo pipe_sel; /* for compat with select */
|
||||
struct timespec pipe_atime; /* time of last access */
|
||||
struct timespec pipe_mtime; /* time of last modify */
|
||||
struct timespec pipe_btime; /* time of creation */
|
||||
struct pipe *pipe_peer; /* link with other direction */
|
||||
pid_t pipe_pgid; /* process group for sigio */
|
||||
u_int pipe_state; /* pipe status info */
|
||||
int pipe_busy; /* busy flag, to handle rundown */
|
||||
vaddr_t pipe_kmem; /* preallocated PIPE_SIZE buffer */
|
||||
kmutex_t *pipe_lock; /* pipe mutex */
|
||||
struct lwp *pipe_owner; /* who holds the pipe busy */
|
||||
u_int pipe_state; /* pipe status info */
|
||||
struct pipebuf pipe_buffer; /* data storage */
|
||||
kcondvar_t pipe_read; /* cv for readers */
|
||||
kcondvar_t pipe_write; /* cv for writers */
|
||||
kcondvar_t pipe_busy; /* cv for locking */
|
||||
struct selinfo pipe_wrsel; /* for compat with select */
|
||||
struct selinfo pipe_rdsel; /* for compat with select */
|
||||
struct timespec pipe_atime; /* time of last access */
|
||||
struct timespec pipe_mtime; /* time of last modify */
|
||||
struct timespec pipe_btime; /* time of creation */
|
||||
pid_t pipe_wrpgid; /* process group for sigio */
|
||||
pid_t pipe_rdpgid; /* process group for sigio */
|
||||
vaddr_t pipe_kmem; /* preallocated PIPE_SIZE buffer */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fstat.c,v 1.118 2023/07/10 02:31:55 christos Exp $ */
|
||||
/* $NetBSD: fstat.c,v 1.119 2023/10/13 19:07:09 ad Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1988, 1993
|
||||
|
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1993\
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: fstat.c,v 1.118 2023/07/10 02:31:55 christos Exp $");
|
||||
__RCSID("$NetBSD: fstat.c,v 1.119 2023/10/13 19:07:09 ad Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -1271,6 +1271,7 @@ static void
|
|||
ptrans(struct file *fp, struct pipe *cpipe, int i)
|
||||
{
|
||||
struct pipe cp;
|
||||
int flag;
|
||||
|
||||
PREFIX(i);
|
||||
|
||||
|
@ -1281,12 +1282,12 @@ ptrans(struct file *fp, struct pipe *cpipe, int i)
|
|||
}
|
||||
|
||||
/* pipe descriptor is either read or write, never both */
|
||||
(void)printf("* pipe %p %s %p %s%s%s", cpipe,
|
||||
flag = (fp->f_flag & FWRITE) ? PIPE_WRASYNC : PIPE_RDASYNC;
|
||||
(void)printf("* pipe %p %s %s%s%s", cpipe,
|
||||
(fp->f_flag & FWRITE) ? "->" : "<-",
|
||||
cp.pipe_peer,
|
||||
(fp->f_flag & FWRITE) ? "w" : "r",
|
||||
(fp->f_flag & FNONBLOCK) ? "n" : "",
|
||||
(cp.pipe_state & PIPE_ASYNC) ? "a" : "");
|
||||
(cp.pipe_state & flag) ? "a" : "");
|
||||
oprint(fp, "\n");
|
||||
return;
|
||||
bad:
|
||||
|
|
Loading…
Reference in New Issue