about summary refs log tree commit diff
path: root/rt/aio_cancel.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2021-06-22 09:50:27 +0200
committerFlorian Weimer <fweimer@redhat.com>2021-06-22 09:50:45 +0200
commitdaa3fc9bff55c1f8368a464ec802ab620901344e (patch)
tree14c3a5a951a84aeff9d554ab5a77c13a4ec29521 /rt/aio_cancel.c
parentae830b2d9f5238e1bee9820cd4d4df7f7b13ecff (diff)
downloadglibc-daa3fc9bff55c1f8368a464ec802ab620901344e.tar.gz
glibc-daa3fc9bff55c1f8368a464ec802ab620901344e.tar.xz
glibc-daa3fc9bff55c1f8368a464ec802ab620901344e.zip
rt: Move generic implementation from sysdeps/pthread to rt
The pthread-based implementation is the generic one.  Replacing
the stubs makes it clear that they do not have to be adjusted for
the libpthread move.

Result of:

    git mv -f sysdeps/pthread/aio_misc.h sysdeps/generic/
    git mv sysdeps/pthread/timer_routines.c sysdeps/htl/
    git mv -f sysdeps/pthread/{aio,lio,timer}_*.c rt/

Followed by manual adjustment of the #include paths in
sysdeps/unix/sysv/linux/wordsize-64, and a move of the version
definitions formerly in sysdeps/pthread/Versions.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Diffstat (limited to 'rt/aio_cancel.c')
-rw-r--r--rt/aio_cancel.c129
1 files changed, 122 insertions, 7 deletions
diff --git a/rt/aio_cancel.c b/rt/aio_cancel.c
index dba1e45044..63fd88f36c 100644
--- a/rt/aio_cancel.c
+++ b/rt/aio_cancel.c
@@ -1,6 +1,7 @@
-/* Cancel requests associated with given file descriptor.  Stub version.
-   Copyright (C) 2001-2021 Free Software Foundation, Inc.
+/* Cancel requests associated with given file descriptor.
+   Copyright (C) 1997-2021 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
@@ -22,21 +23,135 @@
    we want to avoid code duplication by using aliases.  But gcc sees
    the different parameter lists and prints a warning.  We define here
    a function so that aio_cancel64 has no prototype.  */
+#ifndef aio_cancel
 #define aio_cancel64 XXX
 #include <aio.h>
 /* And undo the hack.  */
 #undef aio_cancel64
+#endif
 
+#include <assert.h>
 #include <errno.h>
+#include <fcntl.h>
+
+#include <aio_misc.h>
+
 
 int
 aio_cancel (int fildes, struct aiocb *aiocbp)
 {
-  __set_errno (ENOSYS);
-  return -1;
+  struct requestlist *req = NULL;
+  int result = AIO_ALLDONE;
+
+  /* If fildes is invalid, error. */
+  if (fcntl (fildes, F_GETFL) < 0)
+    {
+      __set_errno (EBADF);
+      return -1;
+    }
+
+  /* Request the mutex.  */
+  pthread_mutex_lock (&__aio_requests_mutex);
+
+  /* We are asked to cancel a specific AIO request.  */
+  if (aiocbp != NULL)
+    {
+      /* If the AIO request is not for this descriptor it has no value
+	 to look for the request block.  */
+      if (aiocbp->aio_fildes != fildes)
+	{
+	  pthread_mutex_unlock (&__aio_requests_mutex);
+	  __set_errno (EINVAL);
+	  return -1;
+	}
+      else if (aiocbp->__error_code == EINPROGRESS)
+	{
+	  struct requestlist *last = NULL;
+
+	  req = __aio_find_req_fd (fildes);
+
+	  if (req == NULL)
+	    {
+	    not_found:
+	      pthread_mutex_unlock (&__aio_requests_mutex);
+	      __set_errno (EINVAL);
+	      return -1;
+	    }
+
+	  while (req->aiocbp != (aiocb_union *) aiocbp)
+	    {
+	      last = req;
+	      req = req->next_prio;
+	      if (req == NULL)
+		goto not_found;
+	    }
+
+	  /* Don't remove the entry if a thread is already working on it.  */
+	  if (req->running == allocated)
+	    {
+	      result = AIO_NOTCANCELED;
+	      req = NULL;
+	    }
+	  else
+	    {
+	      /* We can remove the entry.  */
+	      __aio_remove_request (last, req, 0);
+
+	      result = AIO_CANCELED;
+
+	      req->next_prio = NULL;
+	    }
+	}
+    }
+  else
+    {
+      /* Find the beginning of the list of all requests for this
+	 desriptor.  */
+      req = __aio_find_req_fd (fildes);
+
+      /* If any request is worked on by a thread it must be the first.
+	 So either we can delete all requests or all but the first.  */
+      if (req != NULL)
+	{
+	  if (req->running == allocated)
+	    {
+	      struct requestlist *old = req;
+	      req = req->next_prio;
+	      old->next_prio = NULL;
+
+	      result = AIO_NOTCANCELED;
+
+	      if (req != NULL)
+		__aio_remove_request (old, req, 1);
+	    }
+	  else
+	    {
+	      result = AIO_CANCELED;
+
+	      /* We can remove the entry.  */
+	      __aio_remove_request (NULL, req, 1);
+	    }
+	}
+    }
+
+  /* Mark requests as canceled and send signal.  */
+  while (req != NULL)
+    {
+      struct requestlist *old = req;
+      assert (req->running == yes || req->running == queued);
+      req->aiocbp->aiocb.__error_code = ECANCELED;
+      req->aiocbp->aiocb.__return_value = -1;
+      __aio_notify (req);
+      req = req->next_prio;
+      __aio_free_request (old);
+    }
+
+  /* Release the mutex.  */
+  pthread_mutex_unlock (&__aio_requests_mutex);
+
+  return result;
 }
 
+#ifndef aio_cancel
 weak_alias (aio_cancel, aio_cancel64)
-
-stub_warning (aio_cancel)
-stub_warning (aio_cancel64)
+#endif