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) {

Reply via email to