am a2e5d98b: am 2a8c929a: Merge "Implement __fsetlocking."

* commit 'a2e5d98b641bef4c5611f6aba5defff74abcad93':
  Implement __fsetlocking.
This commit is contained in:
Elliott Hughes 2015-01-22 00:13:10 +00:00 committed by Android Git Automerger
commit 0edffb85fa
5 changed files with 41 additions and 18 deletions

View File

@ -17,6 +17,7 @@
#include "benchmark.h" #include "benchmark.h"
#include <stdio.h> #include <stdio.h>
#include <stdio_ext.h>
#define KB 1024 #define KB 1024
#define MB 1024*KB #define MB 1024*KB
@ -29,6 +30,7 @@ template <typename Fn>
static void ReadWriteTest(int iters, int chunk_size, Fn f, bool buffered) { static void ReadWriteTest(int iters, int chunk_size, Fn f, bool buffered) {
StopBenchmarkTiming(); StopBenchmarkTiming();
FILE* fp = fopen("/dev/zero", "rw"); FILE* fp = fopen("/dev/zero", "rw");
__fsetlocking(fp, FSETLOCKING_BYCALLER);
char* buf = new char[chunk_size]; char* buf = new char[chunk_size];
StartBenchmarkTiming(); StartBenchmarkTiming();
@ -66,12 +68,22 @@ static void BM_stdio_fwrite_unbuffered(int iters, int chunk_size) {
} }
BENCHMARK(BM_stdio_fwrite_unbuffered)->AT_COMMON_SIZES; BENCHMARK(BM_stdio_fwrite_unbuffered)->AT_COMMON_SIZES;
static void BM_stdio_fopen_fgets_fclose(int iters) { static void FopenFgetsFclose(int iters, bool no_locking) {
char buf[1024]; char buf[1024];
for (int i = 0; i < iters; ++i) { for (int i = 0; i < iters; ++i) {
FILE* fp = fopen("/proc/version", "re"); FILE* fp = fopen("/proc/version", "re");
if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
fgets(buf, sizeof(buf), fp); fgets(buf, sizeof(buf), fp);
fclose(fp); fclose(fp);
} }
} }
BENCHMARK(BM_stdio_fopen_fgets_fclose);
static void BM_stdio_fopen_fgets_fclose_locking(int iters) {
FopenFgetsFclose(iters, false);
}
BENCHMARK(BM_stdio_fopen_fgets_fclose_locking);
static void BM_stdio_fopen_fgets_fclose_no_locking(int iters) {
FopenFgetsFclose(iters, true);
}
BENCHMARK(BM_stdio_fopen_fgets_fclose_no_locking);

View File

@ -33,6 +33,7 @@
#define _FILEEXT_H_ #define _FILEEXT_H_
#include <pthread.h> #include <pthread.h>
#include <stdbool.h>
__BEGIN_DECLS __BEGIN_DECLS
@ -43,6 +44,7 @@ struct __sfileext {
struct __sbuf _ub; /* ungetc buffer */ struct __sbuf _ub; /* ungetc buffer */
struct wchar_io_data _wcio; /* wide char io status */ struct wchar_io_data _wcio; /* wide char io status */
pthread_mutex_t _lock; /* file lock */ pthread_mutex_t _lock; /* file lock */
bool _stdio_handles_locking; /* __fsetlocking support */
}; };
#define _EXT(fp) ((struct __sfileext *)((fp)->_ext._base)) #define _EXT(fp) ((struct __sfileext *)((fp)->_ext._base))
@ -55,6 +57,7 @@ do { \
_UB(fp)._size = 0; \ _UB(fp)._size = 0; \
WCIO_INIT(fp); \ WCIO_INIT(fp); \
_FLOCK(fp).value = __PTHREAD_RECURSIVE_MUTEX_INIT_VALUE; \ _FLOCK(fp).value = __PTHREAD_RECURSIVE_MUTEX_INIT_VALUE; \
_EXT(fp)->_stdio_handles_locking = true; \
} while (0) } while (0)
#define _FILEEXT_SETUP(f, fext) \ #define _FILEEXT_SETUP(f, fext) \

View File

@ -111,8 +111,8 @@ extern void __atexit_register_cleanup(void (*)(void));
(fp)->_lb._base = NULL; \ (fp)->_lb._base = NULL; \
} }
#define FLOCKFILE(fp) flockfile(fp) #define FLOCKFILE(fp) if (_EXT(fp)->_stdio_handles_locking) flockfile(fp)
#define FUNLOCKFILE(fp) funlockfile(fp) #define FUNLOCKFILE(fp) if (_EXT(fp)->_stdio_handles_locking) funlockfile(fp)
#define FLOATING_POINT #define FLOATING_POINT
#define PRINTF_WIDE_CHAR #define PRINTF_WIDE_CHAR

View File

@ -27,13 +27,10 @@
*/ */
#include <stdio_ext.h> #include <stdio_ext.h>
#include <stdlib.h>
#include <stdio.h>
#include "local.h" #include "local.h"
#include "private/libc_logging.h"
#define FSETLOCKING_QUERY 0
#define FSETLOCKING_INTERNAL 1
#define FSETLOCKING_BYCALLER 2
size_t __fbufsize(FILE* fp) { size_t __fbufsize(FILE* fp) {
return fp->_bf._size; return fp->_bf._size;
@ -76,11 +73,19 @@ void _flushlbf() {
fflush(NULL); fflush(NULL);
} }
int __fsetlocking(FILE*, int) { int __fsetlocking(FILE* fp, int type) {
// We don't currently have an implementation that would obey this, int old_state = _EXT(fp)->_stdio_handles_locking ? FSETLOCKING_INTERNAL : FSETLOCKING_BYCALLER;
// so make setting the state a no-op and always return "we handle locking for you". if (type == FSETLOCKING_QUERY) {
// http://b/17154740 suggests ways we could fix this. return old_state;
return FSETLOCKING_INTERNAL; }
if (type != FSETLOCKING_INTERNAL && type != FSETLOCKING_BYCALLER) {
// The API doesn't let us report an error, so blow up.
__libc_fatal("Bad type (%d) passed to __fsetlocking", type);
}
_EXT(fp)->_stdio_handles_locking = (type == FSETLOCKING_INTERNAL);
return old_state;
} }
void clearerr_unlocked(FILE* fp) { void clearerr_unlocked(FILE* fp) {

View File

@ -133,7 +133,10 @@ TEST(stdio_ext, __freadable__fwritable) {
TEST(stdio_ext, __fsetlocking) { TEST(stdio_ext, __fsetlocking) {
FILE* fp = fopen("/proc/version", "r"); FILE* fp = fopen("/proc/version", "r");
// Android doesn't actually support the other modes. ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_BYCALLER));
ASSERT_EQ(FSETLOCKING_BYCALLER, __fsetlocking(fp, FSETLOCKING_QUERY));
ASSERT_EQ(FSETLOCKING_BYCALLER, __fsetlocking(fp, FSETLOCKING_INTERNAL));
ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY)); ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
fclose(fp); fclose(fp);
} }