Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/sys_pipe.c
Show First 20 Lines • Show All 712 Lines • ▼ Show 20 Lines | if ((rpipe->pipe_state & PIPE_DIRECTW) == 0 && | ||||
rpipe->pipe_buffer.size > SMALL_PIPE_SIZE && | rpipe->pipe_buffer.size > SMALL_PIPE_SIZE && | ||||
rpipe->pipe_buffer.cnt <= SMALL_PIPE_SIZE && | rpipe->pipe_buffer.cnt <= SMALL_PIPE_SIZE && | ||||
piperesizeallowed == 1) { | piperesizeallowed == 1) { | ||||
PIPE_UNLOCK(rpipe); | PIPE_UNLOCK(rpipe); | ||||
pipespace(rpipe, SMALL_PIPE_SIZE); | pipespace(rpipe, SMALL_PIPE_SIZE); | ||||
PIPE_LOCK(rpipe); | PIPE_LOCK(rpipe); | ||||
} | } | ||||
} | } | ||||
arichardson: Maybe the increment should happen after the initial error checks since the manpage says… | |||||
Done Inline ActionsFor better or worse, I've largely reproduced the existing structure as found in sockets, etc. I've now updated the patch to move both message counts to points where we are committed to sending or receiving a message, since we can provide stronger semantics at no real cost. Thanks! rwatson: For better or worse, I've largely reproduced the existing structure as found in sockets, etc. | |||||
while (uio->uio_resid) { | while (uio->uio_resid) { | ||||
/* | /* | ||||
* normal pipe buffer receive | * normal pipe buffer receive | ||||
*/ | */ | ||||
if (rpipe->pipe_buffer.cnt > 0) { | if (rpipe->pipe_buffer.cnt > 0) { | ||||
size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out; | size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out; | ||||
if (size > rpipe->pipe_buffer.cnt) | if (size > rpipe->pipe_buffer.cnt) | ||||
size = rpipe->pipe_buffer.cnt; | size = rpipe->pipe_buffer.cnt; | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | #endif | ||||
PRIBIO | PCATCH, | PRIBIO | PCATCH, | ||||
"piperd", 0)) == 0) | "piperd", 0)) == 0) | ||||
error = pipelock(rpipe, 1); | error = pipelock(rpipe, 1); | ||||
} | } | ||||
if (error) | if (error) | ||||
goto unlocked_error; | goto unlocked_error; | ||||
} | } | ||||
} | } | ||||
#ifdef MAC | #ifdef MAC | ||||
Not Done Inline ActionsOr maybe even down here? arichardson: Or maybe even down here? | |||||
locked_error: | locked_error: | ||||
#endif | #endif | ||||
pipeunlock(rpipe); | pipeunlock(rpipe); | ||||
/* XXX: should probably do this before getting any locks. */ | /* XXX: should probably do this before getting any locks. */ | ||||
if (error == 0) | if (error == 0) | ||||
pipe_timestamp(&rpipe->pipe_atime); | pipe_timestamp(&rpipe->pipe_atime); | ||||
unlocked_error: | unlocked_error: | ||||
Show All 19 Lines | unlocked_error: | ||||
* Only wake up writers if there was actually something read. | * Only wake up writers if there was actually something read. | ||||
* Otherwise, when calling read(2) at EOF, a spurious wakeup occurs. | * Otherwise, when calling read(2) at EOF, a spurious wakeup occurs. | ||||
*/ | */ | ||||
if (nread > 0 && | if (nread > 0 && | ||||
rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt >= PIPE_BUF) | rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt >= PIPE_BUF) | ||||
pipeselwakeup(rpipe); | pipeselwakeup(rpipe); | ||||
PIPE_UNLOCK(rpipe); | PIPE_UNLOCK(rpipe); | ||||
if (nread > 0) | |||||
td->td_ru.ru_msgrcv++; | |||||
return (error); | return (error); | ||||
} | } | ||||
#ifndef PIPE_NODIRECT | #ifndef PIPE_NODIRECT | ||||
/* | /* | ||||
* Map the sending processes' buffer into kernel space and wire it. | * Map the sending processes' buffer into kernel space and wire it. | ||||
* This is similar to a physical write operation. | * This is similar to a physical write operation. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 190 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
pipe_write(struct file *fp, struct uio *uio, struct ucred *active_cred, | pipe_write(struct file *fp, struct uio *uio, struct ucred *active_cred, | ||||
int flags, struct thread *td) | int flags, struct thread *td) | ||||
{ | { | ||||
struct pipe *wpipe, *rpipe; | struct pipe *wpipe, *rpipe; | ||||
ssize_t orig_resid; | ssize_t orig_resid; | ||||
int desiredsize, error; | int desiredsize, error; | ||||
rpipe = fp->f_data; | rpipe = fp->f_data; | ||||
Not Done Inline ActionsSame here (the number of IPC messages sent). Not sure whether that should be attempts or completed sends. arichardson: Same here (`the number of IPC messages sent`). Not sure whether that should be attempts or… | |||||
wpipe = PIPE_PEER(rpipe); | wpipe = PIPE_PEER(rpipe); | ||||
PIPE_LOCK(rpipe); | PIPE_LOCK(rpipe); | ||||
error = pipelock(wpipe, 1); | error = pipelock(wpipe, 1); | ||||
if (error) { | if (error) { | ||||
PIPE_UNLOCK(rpipe); | PIPE_UNLOCK(rpipe); | ||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 234 Lines • ▼ Show 20 Lines | #endif | ||||
* We have something to offer, | * We have something to offer, | ||||
* wake up select/poll. | * wake up select/poll. | ||||
*/ | */ | ||||
if (wpipe->pipe_buffer.cnt) | if (wpipe->pipe_buffer.cnt) | ||||
pipeselwakeup(wpipe); | pipeselwakeup(wpipe); | ||||
pipeunlock(wpipe); | pipeunlock(wpipe); | ||||
PIPE_UNLOCK(rpipe); | PIPE_UNLOCK(rpipe); | ||||
if (uio->uio_resid != orig_resid) | |||||
td->td_ru.ru_msgsnd++; | |||||
return (error); | return (error); | ||||
} | } | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static int | static int | ||||
pipe_truncate(struct file *fp, off_t length, struct ucred *active_cred, | pipe_truncate(struct file *fp, off_t length, struct ucred *active_cred, | ||||
struct thread *td) | struct thread *td) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 487 Lines • Show Last 20 Lines |
Maybe the increment should happen after the initial error checks since the manpage says ru_msgrcv = the number of IPC messages received.