/* 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.
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);
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,
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)
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;
/* 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;
}
newp->next_prio = NULL;
+ last = NULL;
}
if (running == yes)
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'. */
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;
}
}
}
{
/* Something went wrong. */
__aio_free_request (newp);
+ aiocbp->aiocb.__error_code = result;
+ __set_errno (result);
newp = NULL;
}
static void *
-__attribute__ ((noreturn))
handle_fildes_io (void *arg)
{
pthread_t self = pthread_self ();
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,
}
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,
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;
}
while (runp != NULL);
- pthread_exit (NULL);
+ return NULL;
}