Use kinfo_getfile to implement fdwalk on FreeBSD.

Message ID 20181130212331.59989-1-jhb@FreeBSD.org
State New, archived
Headers

Commit Message

John Baldwin Nov. 30, 2018, 9:23 p.m. UTC
  kinfo_getfile() requires a couple of system calls to fetch the list of
open file descriptors.  This can be much cheaper than invoking fstat
on all of the values from 0 to the open file resource limit maximum.

gdb/ChangeLog:

	* common/filestuff.c [HAVE_KINFO_GETFILE]: Include headers.
	(fdwalk) [HAVE_KINFO_GETFILE]: Use kinfo_getfile.
---
 gdb/ChangeLog          |  5 +++++
 gdb/common/filestuff.c | 26 ++++++++++++++++++++++++++
 2 files changed, 31 insertions(+)
  

Comments

Tom Tromey Nov. 30, 2018, 10:15 p.m. UTC | #1
>>>>> "John" == John Baldwin <jhb@FreeBSD.org> writes:

John> kinfo_getfile() requires a couple of system calls to fetch the list of
John> open file descriptors.  This can be much cheaper than invoking fstat
John> on all of the values from 0 to the open file resource limit maximum.

John> gdb/ChangeLog:

John> 	* common/filestuff.c [HAVE_KINFO_GETFILE]: Include headers.
John> 	(fdwalk) [HAVE_KINFO_GETFILE]: Use kinfo_getfile.

Thanks.

John> +#ifdef HAVE_KINFO_GETFILE
John> +  gdb::unique_xmalloc_ptr<struct kinfo_file> fdtbl;
John> +  int nfd;
John> +  fdtbl.reset (kinfo_getfile (getpid (), &nfd));

I think this should be combined with the declaration; no need to call
reset.

This is ok with that change.

Tom
  
Pedro Alves Nov. 30, 2018, 10:39 p.m. UTC | #2
On 11/30/2018 10:15 PM, Tom Tromey wrote:

> John> +#ifdef HAVE_KINFO_GETFILE
> John> +  gdb::unique_xmalloc_ptr<struct kinfo_file> fdtbl;
> John> +  int nfd;
> John> +  fdtbl.reset (kinfo_getfile (getpid (), &nfd));
> 
> I think this should be combined with the declaration; no need to call
> reset.
If you want, you can also use the array-version of unique_ptr
and eliminate some variables:

  int nfd;
  gdb::unique_xmalloc_ptr<struct kinfo_file[]> fdtbl
   (kinfo_getfile (getpid (), &nfd));
  if (fdtbl != NULL)
    {
      for (int i = 0; i < nfd; i++)
	{
	  if (fdtbl[i]->kf_fd >= 0)
	    {
	      int result = func (arg, fdtbl[i]->kf_fd);
	      if (result != 0)
		return result;
            }
        }
      return 0;
    }

Thanks,
Pedro Alves
  
John Baldwin Nov. 30, 2018, 11:15 p.m. UTC | #3
On 11/30/18 2:39 PM, Pedro Alves wrote:
> On 11/30/2018 10:15 PM, Tom Tromey wrote:
> 
>> John> +#ifdef HAVE_KINFO_GETFILE
>> John> +  gdb::unique_xmalloc_ptr<struct kinfo_file> fdtbl;
>> John> +  int nfd;
>> John> +  fdtbl.reset (kinfo_getfile (getpid (), &nfd));
>>
>> I think this should be combined with the declaration; no need to call
>> reset.
> If you want, you can also use the array-version of unique_ptr
> and eliminate some variables:
> 
>   int nfd;
>   gdb::unique_xmalloc_ptr<struct kinfo_file[]> fdtbl
>    (kinfo_getfile (getpid (), &nfd));
>   if (fdtbl != NULL)
>     {
>       for (int i = 0; i < nfd; i++)
> 	{
> 	  if (fdtbl[i]->kf_fd >= 0)
> 	    {
> 	      int result = func (arg, fdtbl[i]->kf_fd);
> 	      if (result != 0)
> 		return result;
>             }
>         }
>       return 0;
>     }

Thanks.  This is what I pushed (modulo using fdtbl[i]. rather than
fdtbl[i]->).
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 348eb65ec7..f88cc16b4d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@ 
+2018-11-30  John Baldwin  <jhb@FreeBSD.org>
+
+	* common/filestuff.c [HAVE_KINFO_GETFILE]: Include headers.
+	(fdwalk) [HAVE_KINFO_GETFILE]: Use kinfo_getfile.
+
 2018-11-30  John Baldwin  <jhb@FreeBSD.org>
 
 	* fbsd-nat.c [__FreeBSD_version >= 700009] (USE_SIGINFO): Macro
diff --git a/gdb/common/filestuff.c b/gdb/common/filestuff.c
index 0db5c6936b..48b0487f54 100644
--- a/gdb/common/filestuff.c
+++ b/gdb/common/filestuff.c
@@ -36,6 +36,11 @@ 
 #define HAVE_SOCKETS 1
 #endif
 
+#ifdef HAVE_KINFO_GETFILE
+#include <sys/user.h>
+#include <libutil.h>
+#endif
+
 #ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #endif /* HAVE_SYS_RESOURCE_H */
@@ -108,6 +113,27 @@  fdwalk (int (*func) (void *, int), void *arg)
     }
   /* We may fall through to the next case.  */
 #endif
+#ifdef HAVE_KINFO_GETFILE
+  gdb::unique_xmalloc_ptr<struct kinfo_file> fdtbl;
+  int nfd;
+  fdtbl.reset (kinfo_getfile (getpid (), &nfd));
+  if (fdtbl != NULL)
+    {
+      int result = 0;
+      struct kinfo_file *kf = fdtbl.get ();
+      for (int i = 0; i < nfd; i++, kf++)
+	{
+	  if (kf->kf_fd >= 0)
+	    {
+	      result = func (arg, kf->kf_fd);
+	      if (result != 0)
+		break;
+	    }
+	}
+      return result;
+    }
+  /* We may fall through to the next case.  */
+#endif
 
   {
     int max, fd;