]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/pthread/aio_misc.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / pthread / aio_misc.c
index 78cf764837f9f8ede25c3468b8cdfebdfa81043e..9b7227d689e1ab254aa9deac9b11aea081ac6fe1 100644 (file)
@@ -1,5 +1,5 @@
 /* Handle general operations.
-   Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1997-2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -14,9 +14,8 @@
    Lesser General Public License for more details.
 
    You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
 #include <aio.h>
 #include <assert.h>
 #include <pthread.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <sys/param.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <aio_misc.h>
 
-#include "aio_misc.h"
+#ifndef aio_create_helper_thread
+# define aio_create_helper_thread __aio_create_helper_thread
+
+extern inline int
+__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), void *arg)
+{
+  pthread_attr_t attr;
+
+  /* Make sure the thread is created detached.  */
+  pthread_attr_init (&attr);
+  pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+
+  int ret = pthread_create (threadp, &attr, tf, arg);
+
+  (void) pthread_attr_destroy (&attr);
+  return ret;
+}
+#endif
 
 static void add_request_to_runlist (struct requestlist *newrequest);
 
@@ -68,7 +86,7 @@ static int idle_thread_count;
 static struct aioinit optim =
 {
   20,  /* int aio_threads;     Maximal number of threads.  */
-  64,  /* int aio_num;         Number of expected simultanious requests. */
+  64,  /* int aio_num;         Number of expected simultaneous requests. */
   0,
   0,
   0,
@@ -263,9 +281,10 @@ __aio_init (const struct aioinit *init)
   if (pool == NULL)
     {
       optim.aio_threads = init->aio_threads < 1 ? 1 : init->aio_threads;
+      assert (powerof2 (ENTRIES_PER_ROW));
       optim.aio_num = (init->aio_num < ENTRIES_PER_ROW
                       ? ENTRIES_PER_ROW
-                      : init->aio_num & ~ENTRIES_PER_ROW);
+                      : init->aio_num & ~(ENTRIES_PER_ROW - 1));
     }
 
   if (init->aio_idle_time != 0)
@@ -328,8 +347,10 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
       return NULL;
     }
   newp->aiocbp = aiocbp;
+#ifdef BROKEN_THREAD_SIGNALS
   newp->caller_pid = (aiocbp->aiocb.aio_sigevent.sigev_notify == SIGEV_SIGNAL
                      ? getpid () : 0);
+#endif
   newp->waiting = NULL;
 
   aiocbp->aiocb.__abs_prio = prio;
@@ -351,9 +372,13 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
 
       /* Simply enqueue it after the running one according to the
         priority.  */
+      last = NULL;
       while (runp->next_prio != NULL
             && runp->next_prio->aiocbp->aiocb.__abs_prio >= prio)
-       runp = runp->next_prio;
+       {
+         last = runp;
+         runp = runp->next_prio;
+       }
 
       newp->next_prio = runp->next_prio;
       runp->next_prio = newp;
@@ -382,6 +407,7 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
        }
 
       newp->next_prio = NULL;
+      last = NULL;
     }
 
   if (running == yes)
@@ -398,16 +424,12 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
       if (nthreads < optim.aio_threads && idle_thread_count == 0)
        {
          pthread_t thid;
-         pthread_attr_t attr;
-
-         /* Make sure the thread is created detached.  */
-         pthread_attr_init (&attr);
-         pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
 
          running = newp->running = allocated;
 
          /* Now try to start a thread.  */
-         if (pthread_create (&thid, &attr, handle_fildes_io, newp) == 0)
+         result = aio_create_helper_thread (&thid, handle_fildes_io, newp);
+         if (result == 0)
            /* We managed to enqueue the request.  All errors which can
               happen now can be recognized by calls to `aio_return' and
               `aio_error'.  */
@@ -418,10 +440,14 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
              running = newp->running = yes;
 
              if (nthreads == 0)
-               /* We cannot create a thread in the moment and there is
-                  also no thread running.  This is a problem.  `errno' is
-                  set to EAGAIN if this is only a temporary problem.  */
-               result = -1;
+               {
+                 /* We cannot create a thread in the moment and there is
+                    also no thread running.  This is a problem.  `errno' is
+                    set to EAGAIN if this is only a temporary problem.  */
+                 __aio_remove_request (last, newp, 0);
+               }
+             else
+               result = 0;
            }
        }
     }
@@ -443,6 +469,8 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
     {
       /* Something went wrong.  */
       __aio_free_request (newp);
+      aiocbp->aiocb.__error_code = result;
+      __set_errno (result);
       newp = NULL;
     }
 
@@ -454,7 +482,6 @@ __aio_enqueue_request (aiocb_union *aiocbp, int operation)
 
 
 static void *
-__attribute__ ((noreturn))
 handle_fildes_io (void *arg)
 {
   pthread_t self = pthread_self ();
@@ -497,7 +524,8 @@ handle_fildes_io (void *arg)
             by signals.  */
          if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_READ)
            {
-             if (aiocbp->aiocb.aio_lio_opcode & 128)
+             if (sizeof (off_t) != sizeof (off64_t)
+                 && aiocbp->aiocb.aio_lio_opcode & 128)
                aiocbp->aiocb.__return_value =
                  TEMP_FAILURE_RETRY (__pread64 (fildes, (void *)
                                                 aiocbp->aiocb64.aio_buf,
@@ -522,7 +550,8 @@ handle_fildes_io (void *arg)
            }
          else if ((aiocbp->aiocb.aio_lio_opcode & 127) == LIO_WRITE)
            {
-             if (aiocbp->aiocb.aio_lio_opcode & 128)
+             if (sizeof (off_t) != sizeof (off64_t)
+                 && aiocbp->aiocb.aio_lio_opcode & 128)
                aiocbp->aiocb.__return_value =
                  TEMP_FAILURE_RETRY (__pwrite64 (fildes, (const void *)
                                                  aiocbp->aiocb64.aio_buf,
@@ -602,10 +631,10 @@ handle_fildes_io (void *arg)
          struct timespec wakeup_time;
 
          ++idle_thread_count;
-         gettimeofday (&now, NULL);
+         __gettimeofday (&now, NULL);
          wakeup_time.tv_sec = now.tv_sec + optim.aio_idle_time;
          wakeup_time.tv_nsec = now.tv_usec * 1000;
-         if (wakeup_time.tv_nsec > 1000000000)
+         if (wakeup_time.tv_nsec >= 1000000000)
            {
              wakeup_time.tv_nsec -= 1000000000;
              ++wakeup_time.tv_sec;
@@ -660,7 +689,7 @@ handle_fildes_io (void *arg)
     }
   while (runp != NULL);
 
-  pthread_exit (NULL);
+  return NULL;
 }