/* Handle general operations.
Copyright (C) 1997-2014 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
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, see
<http://www.gnu.org/licenses/>. */
#include <aio.h>
#include <assert.h>
#include <errno.h>
#include <limits.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>
#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);
/* Pool of request list entries. */
static struct requestlist **pool;
/* Number of total and allocated pool entries. */
static size_t pool_max_size;
static size_t pool_size;
/* We implement a two dimensional array but allocate each row separately.
The macro below determines how many entries should be used per row.
It should better be a power of two. */
#define ENTRIES_PER_ROW 32
/* How many rows we allocate at once. */
#define ROWS_STEP 8
/* List of available entries. */
static struct requestlist *freelist;
/* List of request waiting to be processed. */
static struct requestlist *runlist;
/* Structure list of all currently processed requests. */
static struct requestlist *requests;
/* Number of threads currently running. */
static int nthreads;
/* Number of threads waiting for work to arrive. */
static int idle_thread_count;
/* These are the values used to optimize the use of AIO. The user can
overwrite them by using the `aio_init' function. */
static struct aioinit optim =
{
20, /* int aio_threads; Maximal number of threads. */
64, /* int aio_num; Number of expected simultaneous requests. */
0,
0,
0,
0,
1,
0
};
/* Since the list is global we need a mutex protecting it. */
pthread_mutex_t __aio_requests_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
/* When you add a request to the list and there are idle threads present,
you signal this condition variable. When a thread finishes work, it waits
on this condition variable for a time before it actually exits. */
pthread_cond_t __aio_new_request_notification = PTHREAD_COND_INITIALIZER;
/* Functions to handle request list pool. */
static struct requestlist *
get_elem (void)
{
struct requestlist *result;
if (freelist == NULL)
{
struct requestlist *new_row;
int cnt;
assert (sizeof (struct aiocb) == sizeof (struct aiocb64));
if (pool_size + 1 >= pool_max_size)
{
size_t