Back to index

glibc  2.9
Classes | Defines | Functions
aio_suspend.c File Reference
#include <aio.h>
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/time.h>
#include <bits/libc-lock.h>
#include <aio_misc.h>

Go to the source code of this file.

Classes

struct  clparam

Defines

#define aio_suspend64   XXX

Functions

static void cleanup (void *arg)
int aio_suspend (list, int nent, const struct timespec *timeout) const

Class Documentation

struct clparam

Definition at line 42 of file aio_suspend.c.

Collaboration diagram for clparam:
Class Members
pthread_cond_t * cond
struct aiocb *const * list
int nent
struct requestlist ** requestlist
struct waitlist * waitlist

Define Documentation

#define aio_suspend64   XXX

Definition at line 27 of file aio_suspend.c.


Function Documentation

int aio_suspend ( list  ,
int  nent,
const struct timespec timeout 
) const

Definition at line 97 of file aio_suspend.c.

{
  if (__builtin_expect (nent < 0, 0))
    {
      __set_errno (EINVAL);
      return -1;
    }

  struct waitlist waitlist[nent];
  struct requestlist *requestlist[nent];
#ifndef DONT_NEED_AIO_MISC_COND
  pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
#endif
  int cnt;
  bool any = false;
  int result = 0;
  int cntr = 1;

  /* Request the mutex.  */
  pthread_mutex_lock (&__aio_requests_mutex);

  /* There is not yet a finished request.  Signal the request that
     we are working for it.  */
  for (cnt = 0; cnt < nent; ++cnt)
    if (list[cnt] != NULL)
      {
       if (list[cnt]->__error_code == EINPROGRESS)
         {
           requestlist[cnt] = __aio_find_req ((aiocb_union *) list[cnt]);

           if (requestlist[cnt] != NULL)
             {
#ifndef DONT_NEED_AIO_MISC_COND
              waitlist[cnt].cond = &cond;
#endif
              waitlist[cnt].result = NULL;
              waitlist[cnt].next = requestlist[cnt]->waiting;
              waitlist[cnt].counterp = &cntr;
              waitlist[cnt].sigevp = NULL;
#ifdef BROKEN_THREAD_SIGNALS
              waitlist[cnt].caller_pid = 0;      /* Not needed.  */
#endif
              requestlist[cnt]->waiting = &waitlist[cnt];
              any = true;
             }
           else
             /* We will never suspend.  */
             break;
         }
       else
         /* We will never suspend.  */
         break;
      }


  /* Only if none of the entries is NULL or finished to be wait.  */
  if (cnt == nent && any)
    {
      struct clparam clparam =
       {
         .list = list,
         .waitlist = waitlist,
         .requestlist = requestlist,
#ifndef DONT_NEED_AIO_MISC_COND
         .cond = &cond,
#endif
         .nent = nent
       };

      pthread_cleanup_push (cleanup, &clparam);

#ifdef DONT_NEED_AIO_MISC_COND
      AIO_MISC_WAIT (result, cntr, timeout, 1);
#else
      if (timeout == NULL)
       result = pthread_cond_wait (&cond, &__aio_requests_mutex);
      else
       {
         /* We have to convert the relative timeout value into an
            absolute time value with pthread_cond_timedwait expects.  */
         struct timeval now;
         struct timespec abstime;

         __gettimeofday (&now, NULL);
         abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000;
         abstime.tv_sec = timeout->tv_sec + now.tv_sec;
         if (abstime.tv_nsec >= 1000000000)
           {
             abstime.tv_nsec -= 1000000000;
             abstime.tv_sec += 1;
           }

         result = pthread_cond_timedwait (&cond, &__aio_requests_mutex,
                                      &abstime);
       }
#endif

      pthread_cleanup_pop (0);
    }

  /* Now remove the entry in the waiting list for all requests
     which didn't terminate.  */
  while (cnt-- > 0)
    if (list[cnt] != NULL && list[cnt]->__error_code == EINPROGRESS)
      {
       struct waitlist **listp;

       assert (requestlist[cnt] != NULL);

       /* There is the chance that we cannot find our entry anymore. This
          could happen if the request terminated and restarted again.  */
       listp = &requestlist[cnt]->waiting;
       while (*listp != NULL && *listp != &waitlist[cnt])
         listp = &(*listp)->next;

       if (*listp != NULL)
         *listp = (*listp)->next;
      }

#ifndef DONT_NEED_AIO_MISC_COND
  /* Release the conditional variable.  */
  if (__builtin_expect (pthread_cond_destroy (&cond) != 0, 0))
    /* This must never happen.  */
    abort ();
#endif

  if (result != 0)
    {
#ifndef DONT_NEED_AIO_MISC_COND
      /* An error occurred.  Possibly it's ETIMEDOUT.  We have to translate
        the timeout error report of `pthread_cond_timedwait' to the
        form expected from `aio_suspend'.  */
      if (result == ETIMEDOUT)
       __set_errno (EAGAIN);
      else
#endif
       __set_errno (result);

      result = -1;
    }

  /* Release the mutex.  */
  pthread_mutex_unlock (&__aio_requests_mutex);

  return result;
}

Here is the call graph for this function:

static void cleanup ( void *  arg) [static]

Definition at line 55 of file aio_suspend.c.

{
#ifdef DONT_NEED_AIO_MISC_COND
  /* Acquire the mutex.  If pthread_cond_*wait is used this would
     happen implicitly.  */
  pthread_mutex_lock (&__aio_requests_mutex);
#endif

  const struct clparam *param = (const struct clparam *) arg;

  /* Now remove the entry in the waiting list for all requests
     which didn't terminate.  */
  int cnt = param->nent;
  while (cnt-- > 0)
    if (param->list[cnt] != NULL
       && param->list[cnt]->__error_code == EINPROGRESS)
      {
       struct waitlist **listp;

       assert (param->requestlist[cnt] != NULL);

       /* There is the chance that we cannot find our entry anymore. This
          could happen if the request terminated and restarted again.  */
       listp = &param->requestlist[cnt]->waiting;
       while (*listp != NULL && *listp != &param->waitlist[cnt])
         listp = &(*listp)->next;

       if (*listp != NULL)
         *listp = (*listp)->next;
      }

#ifndef DONT_NEED_AIO_MISC_COND
  /* Release the conditional variable.  */
  (void) pthread_cond_destroy (param->cond);
#endif

  /* Release the mutex.  */
  pthread_mutex_unlock (&__aio_requests_mutex);
}

Here is the call graph for this function: