public inbox for cygwin-patches@cygwin.com
 help / color / mirror / Atom feed
* [PATCH] Add pthread_getname_np, pthread_setname_np
@ 2012-02-24  3:38 Yaakov (Cygwin/X)
  2012-02-24  9:38 ` Corinna Vinschen
  0 siblings, 1 reply; 5+ messages in thread
From: Yaakov (Cygwin/X) @ 2012-02-24  3:38 UTC (permalink / raw)
  To: cygwin-patches

[-- Attachment #1: Type: text/plain, Size: 1069 bytes --]

This patchset adds pthread_getname_np and pthread_setname_np.  These
were added to glibc in 2.12[1] and are also present in some form on
NetBSD and several UNIXes.  IIUC recent versions of GDB can benefit from
this support.

The code is based on NetBSD's implementation with changes to better
match Linux behaviour.  It does differ from Linux in two points:

* The thread name is not affected by changing __progname (or
program_invocation_short_name on Linux).  I used the latter because it
is cheaper than the pinfo->progname dance (e.g. in
format_process_stat()).

* pthread_setname_np(thr, NULL) segfaults on Linux (and NetBSD), but our
snprintf is apparently more robust and treats it as an empty string.

I'll leave it up to you to decide if either of these matter.

I implemented this via class pthread_attr to make it easier to add
pthread_attr_[gs]etname_np (present in NetBSD and some UNIXes) should it
ever be added to Linux (or we decide we want it anyway).

Patches and test code attached.


Yaakov

[1] http://sourceware.org/git/?p=glibc.git;a=blob;f=NEWS

[-- Attachment #2: cygwin-pthread_getname_np.patch --]
[-- Type: text/x-patch, Size: 6313 bytes --]

2012-02-??  Yaakov Selkowitz  <yselkowitz@...>

	* cygwin.din (pthread_getname_np): Export.
	(pthread_setname_np): Export.
	* posix.sgml (std-gnu): Add pthread_getname_np and pthread_setname_np.
	* thread.cc (pthread_attr::pthread_attr): Initialize name element.
	(pthread_getname_np): New function.
	(pthread_setname_np): New function.
	* thread.h (class pthread_attr): Add name element.
	* include/pthread.h (pthread_getname_np): Declare.
	(pthread_setname_np): Declare.
	* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump.

Index: cygwin.din
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/cygwin.din,v
retrieving revision 1.254
diff -u -p -r1.254 cygwin.din
--- cygwin.din	22 Feb 2012 01:58:24 -0000	1.254
+++ cygwin.din	23 Feb 2012 06:27:21 -0000
@@ -1226,6 +1226,7 @@ pthread_exit SIGFE
 pthread_getattr_np SIGFE
 pthread_getconcurrency SIGFE
 pthread_getcpuclockid SIGFE
+pthread_getname_np SIGFE
 pthread_getschedparam SIGFE
 pthread_getsequence_np SIGFE
 pthread_getspecific SIGFE
@@ -1266,6 +1267,7 @@ pthread_self SIGFE
 pthread_setcancelstate SIGFE
 pthread_setcanceltype SIGFE
 pthread_setconcurrency SIGFE
+pthread_setname_np SIGFE
 pthread_setschedparam SIGFE
 pthread_setschedprio SIGFE
 pthread_setspecific SIGFE
Index: posix.sgml
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/posix.sgml,v
retrieving revision 1.76
diff -u -p -r1.76 posix.sgml
--- posix.sgml	22 Feb 2012 01:58:24 -0000	1.76
+++ posix.sgml	23 Feb 2012 06:27:21 -0000
@@ -1133,6 +1133,8 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008)
     pow10f
     ppoll
     pthread_getattr_np
+    pthread_getname_np
+    pthread_setname_np
     pthread_sigqueue
     ptsname_r
     removexattr
Index: thread.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/thread.cc,v
retrieving revision 1.256
diff -u -p -r1.256 thread.cc
--- thread.cc	14 Feb 2012 09:45:21 -0000	1.256
+++ thread.cc	23 Feb 2012 06:27:22 -0000
@@ -27,6 +27,7 @@ details. */
 #include "miscfuncs.h"
 #include "path.h"
 #include <stdlib.h>
+#include <stdio.h>
 #include "sigproc.h"
 #include "fhandler.h"
 #include "dtable.h"
@@ -1124,7 +1125,8 @@ pthread::resume ()
 pthread_attr::pthread_attr ():verifyable_object (PTHREAD_ATTR_MAGIC),
 joinable (PTHREAD_CREATE_JOINABLE), contentionscope (PTHREAD_SCOPE_PROCESS),
 inheritsched (PTHREAD_INHERIT_SCHED), stackaddr (NULL),
-stacksize (PTHREAD_DEFAULT_STACKSIZE), guardsize (PTHREAD_DEFAULT_GUARDSIZE)
+stacksize (PTHREAD_DEFAULT_STACKSIZE), guardsize (PTHREAD_DEFAULT_GUARDSIZE),
+name (NULL)
 {
   schedparam.sched_priority = 0;
 }
@@ -2547,6 +2549,55 @@ pthread_getattr_np (pthread_t thread, pt
   return 0;
 }
 
+#define NAMELEN 16
+
+extern "C" int
+pthread_getname_np (pthread_t thread, char *buf, size_t buflen)
+{
+  if (!pthread::is_good_object (&thread))
+    return ESRCH;
+  if (buflen < NAMELEN)
+    return ERANGE;
+
+  myfault efault;
+  if (efault.faulted ())
+    return EFAULT;
+
+  if (!thread->attr.name)
+    strlcpy (buf, program_invocation_short_name, NAMELEN);
+  else
+    strlcpy (buf, thread->attr.name, NAMELEN);
+  return 0;
+}
+
+extern "C" int
+pthread_setname_np (pthread_t thread, const char *name)
+{
+  int namelen;
+  char *oldname, *cp, newname[NAMELEN];
+
+  if (!pthread::is_good_object (&thread))
+    return ESRCH;
+
+  namelen = snprintf(newname, NAMELEN, name);
+  if (namelen >= NAMELEN)
+    return ERANGE;
+
+  cp = strdup(newname);
+  if (!cp)
+    return ENOMEM;
+
+  oldname = thread->attr.name;
+  thread->attr.name = cp;
+
+  if (oldname)
+    free(oldname);
+
+  return 0;
+}
+
+#undef NAMELEN
+
 /* provided for source level compatability.
    See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
 */
Index: thread.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/thread.h,v
retrieving revision 1.127
diff -u -p -r1.127 thread.h
--- thread.h	13 Feb 2012 13:12:37 -0000	1.127
+++ thread.h	23 Feb 2012 06:27:22 -0000
@@ -261,6 +261,7 @@ public:
   void *stackaddr;
   size_t stacksize;
   size_t guardsize;
+  char *name;
 
   pthread_attr ();
   ~pthread_attr ();
Index: include/pthread.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/include/pthread.h,v
retrieving revision 1.36
diff -u -p -r1.36 pthread.h
--- include/pthread.h	13 Feb 2012 01:46:46 -0000	1.36
+++ include/pthread.h	23 Feb 2012 06:27:22 -0000
@@ -203,6 +199,8 @@ void pthread_testcancel (void);
 /* Non posix calls */
 
 int pthread_getattr_np (pthread_t, pthread_attr_t *);
+int pthread_getname_np (pthread_t, char *, size_t) __attribute__((nonnull(2)));
+int pthread_setname_np (pthread_t, const char *) __attribute__((nonnull(2)));
 int pthread_sigqueue (pthread_t *, int, const union sigval);
 int pthread_suspend (pthread_t);
 int pthread_continue (pthread_t);
Index: include/cygwin/version.h
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/include/cygwin/version.h,v
retrieving revision 1.364
diff -u -p -r1.364 version.h
--- include/cygwin/version.h	22 Feb 2012 01:58:24 -0000	1.364
+++ include/cygwin/version.h	23 Feb 2012 06:27:22 -0000
@@ -429,12 +429,13 @@ details. */
       258: Export get_current_dir_name.
       259: Export pthread_sigqueue.
       260: Export scandirat.
+      261: Export pthread_getname_np, pthread_setname_np.
      */
 
      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 260
+#define CYGWIN_VERSION_API_MINOR 261
 
      /* There is also a compatibity version number associated with the
 	shared memory regions.  It is incremented when incompatible
Index: release/1.7.11
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/release/1.7.11,v
retrieving revision 1.3
diff -u -p -r1.3 1.7.11
--- release/1.7.11	22 Feb 2012 02:07:07 -0000	1.3
+++ release/1.7.11	24 Feb 2012 03:10:38 -0000
@@ -1,7 +1,7 @@
 What's new:
 -----------
 
-- New API: scandirat.
+- New API: pthread_getname_np, pthread_setname_np, scandirat.
 
 
 What changed:

[-- Attachment #3: doc-pthread_getname_np.patch --]
[-- Type: text/x-patch, Size: 640 bytes --]

2012-02-??  Yaakov Selkowitz  <yselkowitz@...>

	* new-features.sgml (ov-new1.7.11): Document pthread_getname_np
	and pthread_setname_np.

Index: new-features.sgml
===================================================================
RCS file: /cvs/src/src/winsup/doc/new-features.sgml,v
retrieving revision 1.102
diff -u -p -r1.102 new-features.sgml
--- new-features.sgml	22 Feb 2012 02:06:15 -0000	1.102
+++ new-features.sgml	24 Feb 2012 03:18:05 -0000
@@ -5,7 +5,7 @@
 <itemizedlist mark="bullet">
 
 <listitem><para>
-New API: scandirat.
+New API: pthread_getname_np, pthread_setname_np, scandirat.
 </para></listitem>
 
 </itemizedlist>

[-- Attachment #4: pthread-getname-test.c --]
[-- Type: text/x-csrc, Size: 3511 bytes --]

/*
 * The _np isn't a joke, this really isn't portable:
 * IBM i, MKS: both functions take two arguments
 * NetBSD, Tru64, VMS: both functions take three arguments
 * QNX, Linux: getname takes three arguments, setname takes two
 *
 * Obviously I could only test with Linux and NetBSD, and my patch
 * tries to follow Linux behaviour:
 * - default thread name: empty on NetBSD, exe name on Linux/Cygwin
 * - program_invocation_short_name and __progname have no effect on NetBSD
 *   or Linux, but does on Cygwin
 * - max name length: 32 on NetBSD (EINVAL), 16 on Linux/Cygwin (ERANGE)
 * - getname with NULL buffer: SEGV on NetBSD, EFAULT on Linux/Cygwin.
 * - setname with NULL string: SEGV on NetBSD/Linux, "" on Cygwin.
 *
 * cc -pthread -o pthread-getname-test pthread-getname-test.c
 */

#define _GNU_SOURCE
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __CYGWIN__
#include <dlfcn.h>
#include <cygwin/version.h>
#endif

extern char *__progname;

#ifdef __NetBSD__
/* setname takes three arguments */
#define THIRDARG , 0
#else
#define THIRDARG
#endif

#ifdef PTHREAD_MAX_NAMELEN_NP  // e.g. NetBSD
#define NAMELEN PTHREAD_MAX_NAMELEN_NP
#else
#define NAMELEN 16
#endif

int
main(void)
{
#if defined(__CYGWIN__) && CYGWIN_VERSION_API_MINOR < 261
  void *libc = dlopen ("cygwin1.dll", 0);
  int (*pthread_getname_np) (pthread_t, char *, size_t) = dlsym (libc, "pthread_getname_np");
  int (*pthread_setname_np) (pthread_t, const char *) = dlsym (libc, "pthread_setname_np");
#endif

  char *buf = (char *) malloc (NAMELEN);
  pthread_t thr = pthread_self ();
  int ret;

#ifndef __NetBSD__ // segfaults
  ret = pthread_getname_np (thr, NULL, NAMELEN-1); // null buffer and too short
  printf ("getname_np: %s\n", strerror (ret));

  ret = pthread_getname_np (thr, NULL, NAMELEN); // null buffer
  printf ("getname_np: %s\n", strerror (ret));
#endif

  ret = pthread_getname_np (thr, buf, NAMELEN-1); // too short
  printf ("getname_np: %s\n", strerror (ret));

  ret = pthread_getname_np (thr, buf, NAMELEN); // just right
  printf ("getname_np: %s: '%s'\n", strerror (ret), buf);

#ifndef __NetBSD__  // GNU extension
  program_invocation_short_name = "foobar";
  ret = pthread_getname_np (thr, buf, NAMELEN); // no effect
  printf ("getname_np: %s: '%s'\n", strerror (ret), buf);
#endif

  __progname = "foobar";
  ret = pthread_getname_np (thr, buf, NAMELEN); // no effect
  printf ("getname_np: %s: '%s'\n", strerror (ret), buf);

#if !defined(__GLIBC__) && !defined(__NetBSD__) // segfaults
  ret = pthread_setname_np (thr, NULL); // null string
  printf ("setname_np: %s\n", strerror (ret));
  ret = pthread_getname_np (thr, buf, NAMELEN);
  printf ("getname_np: %s: '%s'\n", strerror (ret), buf);
#endif

  ret = pthread_setname_np (thr, "" THIRDARG); // empty string
  printf ("setname_np: %s\n", strerror (ret));
  ret = pthread_getname_np (thr, buf, NAMELEN);
  printf ("getname_np: %s: '%s'\n", strerror (ret), buf);

  ret = pthread_setname_np (thr, "12345678901234567890123456789012" THIRDARG); // too long
  printf ("setname_np: %s\n", strerror (ret));
  ret = pthread_getname_np (thr, buf, NAMELEN);  // Linux: still empty
  printf ("getname_np: %s: '%s'\n", strerror (ret), buf);

  ret = pthread_setname_np (thr, "123456789012345" THIRDARG); // just right for all
  printf ("setname_np: %s\n", strerror (ret));
  ret = pthread_getname_np (thr, buf, NAMELEN);
  printf ("getname_np: %s: '%s'\n", strerror (ret), buf);

  return 0;
}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add pthread_getname_np, pthread_setname_np
  2012-02-24  3:38 [PATCH] Add pthread_getname_np, pthread_setname_np Yaakov (Cygwin/X)
@ 2012-02-24  9:38 ` Corinna Vinschen
  2012-02-24 11:00   ` Yaakov (Cygwin/X)
  0 siblings, 1 reply; 5+ messages in thread
From: Corinna Vinschen @ 2012-02-24  9:38 UTC (permalink / raw)
  To: cygwin-patches

On Feb 23 21:38, Yaakov (Cygwin/X) wrote:
> This patchset adds pthread_getname_np and pthread_setname_np.  These
> were added to glibc in 2.12[1] and are also present in some form on
> NetBSD and several UNIXes.  IIUC recent versions of GDB can benefit from
> this support.

Thanks for your patch, but I don't think it's the whole thing.

Consider, if you implement pthread_[gs]etname_np as you did, then you
have pthread names which are only available to the process in which
the threads are running.  So, how could GDB get the information for
its inferior process?

Actually GDB reads the thread name using a target specific function
which is so far only implemented for Linux.  It does not use
pthread_getname_np, rather it reads the name from /proc/$PID/task/$TID/comm.

And that's a bit of a problem in Cygwin.  Every Cygwin process is
multi-threaded (think signals), but only the application-started threads
are pthreads.

So, again, thanks for doing this, but I think this requires more work to
be useful.  The basic task is to provide /proc/$PID/task for all threads
running in a Cygwin process.  If that's available, the pthread_[gs]etname_np
will become useful and their (different) implementation probably falls into
place.


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add pthread_getname_np, pthread_setname_np
  2012-02-24  9:38 ` Corinna Vinschen
@ 2012-02-24 11:00   ` Yaakov (Cygwin/X)
  2012-02-24 12:18     ` Corinna Vinschen
  0 siblings, 1 reply; 5+ messages in thread
From: Yaakov (Cygwin/X) @ 2012-02-24 11:00 UTC (permalink / raw)
  To: cygwin-patches

On Fri, 2012-02-24 at 10:38 +0100, Corinna Vinschen wrote:
> On Feb 23 21:38, Yaakov (Cygwin/X) wrote:
> > This patchset adds pthread_getname_np and pthread_setname_np.  These
> > were added to glibc in 2.12[1] and are also present in some form on
> > NetBSD and several UNIXes.  IIUC recent versions of GDB can benefit from
> > this support.
> 
> Thanks for your patch, but I don't think it's the whole thing.
> 
> Consider, if you implement pthread_[gs]etname_np as you did, then you
> have pthread names which are only available to the process in which
> the threads are running.

My implementation is based on NetBSD's[1].  So what purpose do these
functions serve then on that it and the UNIXes?  (Serious question.)


Yaakov

[1] http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libpthread/pthread.c?rev=1.125


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add pthread_getname_np, pthread_setname_np
  2012-02-24 11:00   ` Yaakov (Cygwin/X)
@ 2012-02-24 12:18     ` Corinna Vinschen
  2012-02-24 16:56       ` Pedro Alves
  0 siblings, 1 reply; 5+ messages in thread
From: Corinna Vinschen @ 2012-02-24 12:18 UTC (permalink / raw)
  To: cygwin-patches

On Feb 24 05:00, Yaakov (Cygwin/X) wrote:
> On Fri, 2012-02-24 at 10:38 +0100, Corinna Vinschen wrote:
> > On Feb 23 21:38, Yaakov (Cygwin/X) wrote:
> > > This patchset adds pthread_getname_np and pthread_setname_np.  These
> > > were added to glibc in 2.12[1] and are also present in some form on
> > > NetBSD and several UNIXes.  IIUC recent versions of GDB can benefit from
> > > this support.
> > 
> > Thanks for your patch, but I don't think it's the whole thing.
> > 
> > Consider, if you implement pthread_[gs]etname_np as you did, then you
> > have pthread names which are only available to the process in which
> > the threads are running.
> 
> My implementation is based on NetBSD's[1].  So what purpose do these
> functions serve then on that it and the UNIXes?  (Serious question.)

See the source of the pthread_setname_np function.  There's a call to
the kernel:

  thread->pt_name = cp;
  (void)_lwp_setname(thread->pt_lid, cp);

_lwp_setname ultimately calls the kernel function sys__lwp_setname in
http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/kern/sys_lwp.c?rev=1.53
So the kernel knows the name and the sys__lwp_getname entry point
can be used to fetch the name of a thread in another process.  How
exactly this is fetched by which BSD tool, I don't know, but it's
all in the sources :)


Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Project Co-Leader          cygwin AT cygwin DOT com
Red Hat

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Add pthread_getname_np, pthread_setname_np
  2012-02-24 12:18     ` Corinna Vinschen
@ 2012-02-24 16:56       ` Pedro Alves
  0 siblings, 0 replies; 5+ messages in thread
From: Pedro Alves @ 2012-02-24 16:56 UTC (permalink / raw)
  To: cygwin-patches

Just FYI,

Windows' way to have the program affect thread names in the
debugger is with SetThreadName, which throws a magic exception
which the debugger can catch.  GDB doesn't know about this though.

 http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx

Just for completeness...  I don't know if there's a native
method that's closer to pthread_setname_np's semantics.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-02-24 16:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-24  3:38 [PATCH] Add pthread_getname_np, pthread_setname_np Yaakov (Cygwin/X)
2012-02-24  9:38 ` Corinna Vinschen
2012-02-24 11:00   ` Yaakov (Cygwin/X)
2012-02-24 12:18     ` Corinna Vinschen
2012-02-24 16:56       ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).