Add pthread_getname_np and pthread_setname_np
This patch 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. The code is based on NetBSD's implementation with changes to better match Linux behaviour. Implementation quirks: * pthread_setname_np with a NULL pointer segfaults (as linux) * pthread_setname_np returns ERANGE for names longer than 16 characters (as linux) * pthread_getname_np with a NULL pointer returns EFAULT (as linux) * pthread_getname_np with a buffer length of less than 16 returns ERANGE (as linux) * pthread_getname_np truncates the thread name to fit the buffer length. This guarantees success even when the default thread name is longer than 16 characters, but means there is no way to discover the actual length of the thread name. (Linux always truncates the thread name to 16 characters) * Changing program_invocation_short_name changes the default thread name (on linux, it has no effect on the default thread name) I'll leave it up to you to decide if any of these matter. This is implemented 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). [1] https://sourceware.org/git/?p=glibc.git;a=blob;f=NEWS
This commit is contained in:
@@ -1106,7 +1106,7 @@ 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 (0),
|
||||
guardsize (wincap.def_guard_page_size ())
|
||||
guardsize (wincap.def_guard_page_size ()), name (NULL)
|
||||
{
|
||||
schedparam.sched_priority = 0;
|
||||
}
|
||||
@@ -2576,6 +2576,69 @@ pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For Linux compatibility, the length of a thread name is 16 characters. */
|
||||
#define THRNAMELEN 16
|
||||
|
||||
extern "C" int
|
||||
pthread_getname_np (pthread_t thread, char *buf, size_t buflen)
|
||||
{
|
||||
char *name;
|
||||
|
||||
if (!pthread::is_good_object (&thread))
|
||||
return ESRCH;
|
||||
|
||||
if (!thread->attr.name)
|
||||
name = program_invocation_short_name;
|
||||
else
|
||||
name = thread->attr.name;
|
||||
|
||||
/* Return ERANGE if the provided buffer is less than THRNAMELEN. Truncate
|
||||
and zero-terminate the name to fit in buf. This means we always return
|
||||
something if the buffer is THRNAMELEN or larger, but there is no way to
|
||||
tell if we have the whole name. */
|
||||
if (buflen < THRNAMELEN)
|
||||
return ERANGE;
|
||||
|
||||
int ret = 0;
|
||||
__try
|
||||
{
|
||||
strlcpy (buf, name, buflen);
|
||||
}
|
||||
__except (NO_ERROR)
|
||||
{
|
||||
ret = EFAULT;
|
||||
}
|
||||
__endtry
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
pthread_setname_np (pthread_t thread, const char *name)
|
||||
{
|
||||
char *oldname, *cp;
|
||||
|
||||
if (!pthread::is_good_object (&thread))
|
||||
return ESRCH;
|
||||
|
||||
if (strlen (name) > THRNAMELEN)
|
||||
return ERANGE;
|
||||
|
||||
cp = strdup (name);
|
||||
if (!cp)
|
||||
return ENOMEM;
|
||||
|
||||
oldname = thread->attr.name;
|
||||
thread->attr.name = cp;
|
||||
|
||||
if (oldname)
|
||||
free (oldname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#undef THRNAMELEN
|
||||
|
||||
/* provided for source level compatability.
|
||||
See http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_getconcurrency.html
|
||||
*/
|
||||
|
Reference in New Issue
Block a user