stdio: provide _unlocked variants of fflush, fputc, fputs, fread, fwrite

fflush_unlocked is currently desired in ports by sysutils/metalog, and
redefined as the locked fflush.

fputc_unlocked, fputs_unlocked, fread_unlocked, and fwrite_unlocked are
currently desired in ports by devel/elfutils, and redefined as the locked
fputs, fread, and fwrite respectively.

Reviewed by:	kib
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D23336
This commit is contained in:
Kyle Evans 2020-01-30 03:31:16 +00:00
parent f2c462994d
commit 12fe218f0b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=357284
12 changed files with 109 additions and 17 deletions

View file

@ -346,7 +346,12 @@ int putchar_unlocked(int);
void clearerr_unlocked(FILE *);
int feof_unlocked(FILE *);
int ferror_unlocked(FILE *);
int fflush_unlocked(FILE *);
int fileno_unlocked(FILE *);
int fputs_unlocked(const char * __restrict, FILE * __restrict);
size_t fread_unlocked(void * __restrict, size_t, size_t, FILE * __restrict);
size_t fwrite_unlocked(const void * __restrict, size_t, size_t,
FILE * __restrict);
#endif
#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500
@ -507,10 +512,11 @@ extern int __isthreaded;
* See ISO/IEC 9945-1 ANSI/IEEE Std 1003.1 Second Edition 1996-07-12
* B.8.2.7 for the rationale behind the *_unlocked() macros.
*/
#define clearerr_unlocked(p) __sclearerr(p)
#define feof_unlocked(p) __sfeof(p)
#define ferror_unlocked(p) __sferror(p)
#define clearerr_unlocked(p) __sclearerr(p)
#define fileno_unlocked(p) __sfileno(p)
#define fputc_unlocked(s, p) __sputc(s, p)
#endif
#if __POSIX_VISIBLE >= 199506
#define getc_unlocked(fp) __sgetc(fp)

View file

@ -48,13 +48,17 @@ MLINKS+=ferror.3 ferror_unlocked.3 \
ferror.3 clearerr.3 ferror.3 clearerr_unlocked.3 \
ferror.3 feof.3 ferror.3 feof_unlocked.3 \
ferror.3 fileno.3 ferror.3 fileno_unlocked.3
MLINKS+=fflush.3 fpurge.3
MLINKS+=fflush.3 fflush_unlocked.3 \
fflush.3 fpurge.3
MLINKS+=fgets.3 gets.3
MLINKS+=fgets.3 gets_s.3
MLINKS+=flockfile.3 ftrylockfile.3 flockfile.3 funlockfile.3
MLINKS+=fopen.3 fdopen.3 fopen.3 freopen.3 fopen.3 fmemopen.3
MLINKS+=fputs.3 puts.3
MLINKS+=fread.3 fwrite.3
MLINKS+=fputs.3 fputs_unlocked.3 \
fputs.3 puts.3
MLINKS+=fread.3 fread_unlocked.3 \
fread.3 fwrite.3 \
fread.3 fwrite_unlocked.3
MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko.3 fseek.3 fsetpos.3 fseek.3 ftell.3 \
fseek.3 ftello.3 fseek.3 rewind.3
MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3

View file

@ -172,6 +172,10 @@ FBSD_1.5 {
};
FBSD_1.6 {
fflush_unlocked;
fputs_unlocked;
fread_unlocked;
fwrite_unlocked;
mkostempsat;
};

View file

@ -32,11 +32,12 @@
.\" @(#)fflush.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd December 25, 2017
.Dd January 23, 2020
.Dt FFLUSH 3
.Os
.Sh NAME
.Nm fflush ,
.Nm fflush_unlocked ,
.Nm fpurge
.Nd flush a stream
.Sh LIBRARY
@ -46,6 +47,8 @@
.Ft int
.Fn fflush "FILE *stream"
.Ft int
.Fn fflush_unlocked "FILE *stream"
.Ft int
.Fn fpurge "FILE *stream"
.Sh DESCRIPTION
The function
@ -64,6 +67,16 @@ flushes
.Em all
open output streams.
.Pp
The
.Fn fflush_unlocked
function is equivalent to
.Fn fflush ,
except that the caller is responsible for locking the stream with
.Xr flockfile 3
before calling it.
This function may be used to avoid the overhead of locking the stream and to
prevent races when multiple threads are operating on the same stream.
.Pp
The function
.Fn fpurge
erases any input or output buffered in the given

View file

@ -100,6 +100,8 @@ __fflush(FILE *fp)
return (retval);
}
__weak_reference(__fflush, fflush_unlocked);
int
__sflush(FILE *fp)
{

View file

@ -44,6 +44,8 @@ __FBSDID("$FreeBSD$");
#include "local.h"
#include "libc_private.h"
#undef fputc_unlocked
int
fputc(int c, FILE *fp)
{

View file

@ -32,11 +32,12 @@
.\" @(#)fputs.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd June 4, 1993
.Dd January 23, 2020
.Dt FPUTS 3
.Os
.Sh NAME
.Nm fputs ,
.Nm fputs_unlocked ,
.Nm puts
.Nd output a line to a stream
.Sh LIBRARY
@ -46,6 +47,8 @@
.Ft int
.Fn fputs "const char *str" "FILE *stream"
.Ft int
.Fn fputs_unlocked "const char *str" "FILE *stream"
.Ft int
.Fn puts "const char *str"
.Sh DESCRIPTION
The function
@ -58,6 +61,16 @@ to the stream pointed to by
.\" .Dv NUL
.\" character is not written.
.Pp
The
.Fn fputs_unlocked
function is equivalent to
.Fn fputs ,
except that the caller is responsible for locking the stream with
.Xr flockfile 3
before calling it.
This function may be used to avoid the overhead of locking the stream and to
prevent races when multiple threads are operating on the same stream.
.Pp
The function
.Fn puts
writes the string

View file

@ -51,7 +51,7 @@ __FBSDID("$FreeBSD$");
* Write the given string to the given file.
*/
int
fputs(const char * __restrict s, FILE * __restrict fp)
fputs_unlocked(const char * __restrict s, FILE * __restrict fp)
{
int retval;
struct __suio uio;
@ -61,11 +61,20 @@ fputs(const char * __restrict s, FILE * __restrict fp)
uio.uio_resid = iov.iov_len = strlen(s);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, -1);
retval = __sfvwrite(fp, &uio);
FUNLOCKFILE_CANCELSAFE();
if (retval == 0)
return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len);
return (retval);
}
int
fputs(const char * __restrict s, FILE * __restrict fp)
{
int retval;
FLOCKFILE_CANCELSAFE(fp);
retval = fputs_unlocked(s, fp);
FUNLOCKFILE_CANCELSAFE();
return (retval);
}

View file

@ -32,12 +32,14 @@
.\" @(#)fread.3 8.2 (Berkeley) 3/8/94
.\" $FreeBSD$
.\"
.Dd March 8, 1994
.Dd January 23, 2020
.Dt FREAD 3
.Os
.Sh NAME
.Nm fread ,
.Nm fwrite
.Nm fread_unlocked ,
.Nm fwrite ,
.Nm fwrite_unlocked
.Nd binary stream input/output
.Sh LIBRARY
.Lb libc
@ -46,7 +48,11 @@
.Ft size_t
.Fn fread "void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
.Ft size_t
.Fn fread_unlocked "void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
.Ft size_t
.Fn fwrite "const void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
.Ft size_t
.Fn fwrite_unlocked "const void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
.Sh DESCRIPTION
The function
.Fn fread
@ -69,6 +75,21 @@ bytes long, to the stream pointed to by
.Fa stream ,
obtaining them from the location given by
.Fa ptr .
.Pp
The
.Fn fread_unlocked
and
.Fn fwrite_unlocked
functions are equivalent to
.Fn fread
and
.Fn fwrite
respectively, except that the caller is responsible for locking the stream
with
.Xr flockfile 3
before calling them.
These functions may be used to avoid the overhead of locking the stream
and to prevent races when multiple threads are operating on the same stream.
.Sh RETURN VALUES
The functions
.Fn fread

View file

@ -115,3 +115,5 @@ __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
fp->_p += resid;
return (count);
}
__weak_reference(__fread, fread_unlocked);

View file

@ -52,7 +52,8 @@ __FBSDID("$FreeBSD$");
* Return the number of whole objects written.
*/
size_t
fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
fwrite_unlocked(const void * __restrict buf, size_t size, size_t count,
FILE * __restrict fp)
{
size_t n;
struct __suio uio;
@ -84,7 +85,6 @@ fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, -1);
/*
* The usual case is success (__sfvwrite returns 0);
@ -93,6 +93,17 @@ fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict
*/
if (__sfvwrite(fp, &uio) != 0)
count = (n - uio.uio_resid) / size;
FUNLOCKFILE_CANCELSAFE();
return (count);
}
size_t
fwrite(const void * __restrict buf, size_t size, size_t count,
FILE * __restrict fp)
{
size_t n;
FLOCKFILE_CANCELSAFE(fp);
n = fwrite_unlocked(buf, size, count, fp);
FUNLOCKFILE_CANCELSAFE();
return (n);
}

View file

@ -32,11 +32,12 @@
.\" @(#)putc.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
.Dd January 10, 2003
.Dd January 23, 2020
.Dt PUTC 3
.Os
.Sh NAME
.Nm fputc ,
.Nm fputc_unlocked ,
.Nm putc ,
.Nm putc_unlocked ,
.Nm putchar ,
@ -50,6 +51,8 @@
.Ft int
.Fn fputc "int c" "FILE *stream"
.Ft int
.Fn fputc_unlocked "int c" "FILE *stream"
.Ft int
.Fn putc "int c" "FILE *stream"
.Ft int
.Fn putc_unlocked "int c" "FILE *stream"
@ -97,11 +100,13 @@ to the named output
.Fa stream .
.Pp
The
.Fn putc_unlocked
.Fn fputc_unlocked ,
.Fn putc_unlocked ,
and
.Fn putchar_unlocked
functions are equivalent to
.Fn putc
.Fn fputc ,
.Fn putc ,
and
.Fn putchar
respectively,