This is the mail archive of the
cygwin-patches
mailing list for the Cygwin project.
[PATCH] Add pthread_getname_np, pthread_setname_np
- From: "Yaakov (Cygwin/X)" <yselkowitz at users dot sourceforge dot net>
- To: cygwin-patches at cygwin dot com
- Date: Thu, 23 Feb 2012 21:38:15 -0600
- Subject: [PATCH] Add pthread_getname_np, pthread_setname_np
- Authentication-results: mr.google.com; spf=pass (google.com: domain of yselkowitz@gmail.com designates 10.43.51.135 as permitted sender) smtp.mail=yselkowitz@gmail.com; dkim=pass header.i=yselkowitz@gmail.com
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
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:
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>
/*
* 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;
}