Hi everyone,
Currently, there are some cases in the Windows implementation of the file
I/O that cause the unnecessary creation and acquisitions of the file mutex.
These cases include handling O_APPEND-style writes and the implementation
of the apr_file_buffer_set().
Creating and acquiring the file mutex is only required for files opened
with the APR_FOPEN_XTHREAD flag. Otherwise, concurrent operations
on the same apr_file_t instance should be serialized by the user, and
the mutex is not required.
This patch tweaks the implementation to only create and acquire/release
the mutex for files opened with APR_FOPEN_XTHREAD. The log message
is included in the beginning of the patch file.
Thanks,
Evgeny Kotkov
Win32: Create and use file mutex only for files opened with APR_FOPEN_XTHREAD.
There are some cases in the Windows implementation of the file I/O that
cause the unnecessary creation and acquisitions of the file mutex.
These cases include handling O_APPEND-style writes and the implementation
of the apr_file_buffer_set().
Creating and acquiring the file mutex is only required for files opened
with the APR_FOPEN_XTHREAD flag. Otherwise, concurrent operations on
the same apr_file_t instance should be serialized by the user, and
the mutex is not required.
This patch tweaks the implementation to only create and acquire/release
the mutex for files opened with APR_FOPEN_XTHREAD.
* file_io/win32/open.c
(apr_file_open, apr_os_file_put): Create the file mutex only
with APR_FOPEN_XTHREAD.
* file_io/win32/buffer.c
(apr_file_buffer_set): Use the file mutex only with APR_FOPEN_XTHREAD.
* file_io/win32/readwrite.c
(apr_file_write): Use the file mutex only with APR_FOPEN_XTHREAD.
Patch by: Evgeny Kotkov <evgeny.kotkov {at} visualsvn.com>
Index: file_io/win32/buffer.c
===================================================================
--- file_io/win32/buffer.c (revision 1806645)
+++ file_io/win32/buffer.c (working copy)
@@ -23,7 +23,9 @@ APR_DECLARE(apr_status_t) apr_file_buffer_set(apr_
{
apr_status_t rv;
- apr_thread_mutex_lock(file->mutex);
+ if (file->flags & APR_FOPEN_XTHREAD) {
+ apr_thread_mutex_lock(file->mutex);
+ }
if(file->buffered) {
/* Flush the existing buffer */
@@ -48,7 +50,9 @@ APR_DECLARE(apr_status_t) apr_file_buffer_set(apr_
file->buffered = 0;
}
- apr_thread_mutex_unlock(file->mutex);
+ if (file->flags & APR_FOPEN_XTHREAD) {
+ apr_thread_mutex_unlock(file->mutex);
+ }
return APR_SUCCESS;
}
Index: file_io/win32/open.c
===================================================================
--- file_io/win32/open.c (revision 1806645)
+++ file_io/win32/open.c (working copy)
@@ -452,8 +452,8 @@ APR_DECLARE(apr_status_t) apr_file_open(apr_file_t
(*new)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
(*new)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
}
- /* Need the mutex to handled buffered and O_APPEND style file i/o */
- if ((*new)->buffered || (*new)->append) {
+ /* Need the mutex to share an apr_file_t across multiple threads */
+ if (flag & APR_FOPEN_XTHREAD) {
rv = apr_thread_mutex_create(&(*new)->mutex,
APR_THREAD_MUTEX_DEFAULT, pool);
if (rv) {
@@ -645,8 +645,7 @@ APR_DECLARE(apr_status_t) apr_os_file_put(apr_file
(*file)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
(*file)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
}
-
- if ((*file)->append || (*file)->buffered) {
+ if (flags & APR_FOPEN_XTHREAD) {
apr_status_t rv;
rv = apr_thread_mutex_create(&(*file)->mutex,
APR_THREAD_MUTEX_DEFAULT, pool);
Index: file_io/win32/readwrite.c
===================================================================
--- file_io/win32/readwrite.c (revision 1806645)
+++ file_io/win32/readwrite.c (working copy)
@@ -412,20 +412,26 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_
if (thefile->append) {
apr_off_t offset = 0;
- /* apr_file_lock will mutex the file across processes.
- * The call to apr_thread_mutex_lock is added to avoid
- * a race condition between LockFile and WriteFile
- * that occasionally leads to deadlocked threads.
- */
- apr_thread_mutex_lock(thefile->mutex);
+ if (thefile->flags & APR_FOPEN_XTHREAD) {
+ /* apr_file_lock will mutex the file across processes.
+ * The call to apr_thread_mutex_lock is added to avoid
+ * a race condition between LockFile and WriteFile
+ * that occasionally leads to deadlocked threads.
+ */
+ apr_thread_mutex_lock(thefile->mutex);
+ }
rv = apr_file_lock(thefile, APR_FLOCK_EXCLUSIVE);
if (rv != APR_SUCCESS) {
- apr_thread_mutex_unlock(thefile->mutex);
+ if (thefile->flags & APR_FOPEN_XTHREAD) {
+ apr_thread_mutex_unlock(thefile->mutex);
+ }
return rv;
}
rv = apr_file_seek(thefile, APR_END, &offset);
if (rv != APR_SUCCESS) {
- apr_thread_mutex_unlock(thefile->mutex);
+ if (thefile->flags & APR_FOPEN_XTHREAD) {
+ apr_thread_mutex_unlock(thefile->mutex);
+ }
return rv;
}
}
@@ -440,7 +446,9 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_
}
if (thefile->append) {
apr_file_unlock(thefile);
- apr_thread_mutex_unlock(thefile->mutex);
+ if (thefile->flags & APR_FOPEN_XTHREAD) {
+ apr_thread_mutex_unlock(thefile->mutex);
+ }
}
}
if (rv) {