This is an archive of the discontinued LLVM Phabricator instance.

[Support] Add functions to get and set thread name.
ClosedPublic

Authored by zturner on Mar 1 2017, 11:39 PM.

Details

Summary

It is often useful however for an application to set the names of its various threads for diagnostic purposes, either when logging or when debugging the application with a debugger that understands how to display thread names.

Because it is extremely non-portable, the methods for getting and setting thread names vary wildly on each platform, and not all operations are supported on every platform.

Regardless, since it is non-critical functionality used mostly for diagnostics, it seems reasonable to provide "best effort" functions, which is what this patch does. This code is a modified version of the logic in LLDB for doing the same thing. If people don't want this, I can always leave it in LLDB, but since it's so hard to make portable and since LLDB has implementations for a lot of different platforms, it might be useful to have it available to anyone who wants it.

Here I provide implementations for the following platforms / operations:

GetName - FreeBSD, NetBSD, Linux.
SetName - Linux, FreeBSD, NetBSD, Apple, Windows.

It's probably possible to do this on many other platforms, but this is already a lot for one person :)

The implementations have already been in use for some time on LLDB so I know they work, but in re-writing the code for LLDB I may have made some syntax errors.

Diff Detail

Repository
rL LLVM

Event Timeline

zturner created this revision.Mar 1 2017, 11:39 PM
zturner updated this revision to Diff 90288.Mar 1 2017, 11:44 PM

Fix a mistake in the linux implementation. I originally had this returning an llvm::Error, but it seemed obnoxious / unnecessary to have to check the return value of a function which is documented as being "best effort"

davide added a subscriber: davide.Mar 1 2017, 11:55 PM

The FreeBSD related bits are correct. The whole chain of #ifdef is a little nasty, but I'm not sure there's an easy way to avoid it.

llvm/lib/Support/Threading.cpp
158–170 ↗(On Diff #90288)

I'm wondering if there's a way to avoid this ugly #ifdef dance.

davide added inline comments.Mar 1 2017, 11:59 PM
llvm/lib/Support/Threading.cpp
43–50 ↗(On Diff #90288)

The inner `#if defined(FreeBSD) is redundant, maybe? (as you're doing the same outside)

158–163 ↗(On Diff #90288)

Maybe you can merge these two cases?

164–166 ↗(On Diff #90288)

Amazing how 4 operating systems define pretty much the same call with slightly different variants.

labath requested changes to this revision.Mar 2 2017, 2:40 AM
llvm/lib/Support/Threading.cpp
155 ↗(On Diff #90288)

It might be overkill, but you could potentially save a copy if you use the Twine.toNullTerminatedStringRef trick

248 ↗(On Diff #90288)

This is not correct. pthread_self returns a pthread_t, which bears no relation to the OS-level thread ID's. You'd need to use syscall(SYS_gettid) here. Also according to the docs http://man7.org/linux/man-pages/man3/pthread_setname_np.3.html it seems a better file to read would be /proc/self/task/<tid>/comm. As was as I know these files always have the same contents, but maybe the other one is deprecated (?)

However, the main issue here is that the set and get code are wildly out of sync. There is a pthread_getname_np pair to the pthread_setname_np (see manpage above), so we should either use that here (guarded by the same ifdefs), or switch the setting code to write directly to the file as well (these functions are basically documented as utilities for reading/writing the file).

I'm sorry I am dumping this on you, but I think the llvm bar for this should be higher than in lldb. I can do this next week if you don't feel comfortable touching that.

This revision now requires changes to proceed.Mar 2 2017, 2:40 AM
zturner updated this revision to Diff 90384.Mar 2 2017, 1:27 PM
zturner edited edge metadata.

Updated with suggestions from labath@

zturner added inline comments.Mar 2 2017, 1:49 PM
llvm/lib/Support/Threading.cpp
43–50 ↗(On Diff #90288)

I don't think pthread_np.h exists on the other flavors of BSD though right? (I actually dont' know, but this is how I translated the code from LLDB. NetBSD and FreeBSD Kernel were not including these headers.

158–163 ↗(On Diff #90288)

The name of the function is slightly different though. For FreeBSD there is an extra underscore. So I have to paper over that difference with a #define somewhere, even if not here.

164–166 ↗(On Diff #90288)

I know right? Very annoying :-/

zturner updated this revision to Diff 90390.Mar 2 2017, 2:08 PM

Also added a function to get the current thread id. std::this_thread::get_id(), unfortunately cannot be examined portably.

zturner updated this revision to Diff 90402.Mar 2 2017, 2:48 PM

This file is starting to get pretty unwieldy, so I suppose it's time to split it into the .inc files. This makes the preprocessor stuff slightly less terrible.

zturner updated this revision to Diff 90421.Mar 2 2017, 5:16 PM

Fixed a compiler error. This now compiles on Linux, Windows, and OSX. Don't have the ability to test any other configurations but I think I got all the includes right.

labath added a comment.Mar 3 2017, 4:34 AM

Thank you, it looks much better. Let me know what you think about the name.

llvm/include/llvm/Support/Threading.h
133 ↗(On Diff #90421)

I'd remove the _np suffix. It is present on the pthread functions to differentiate them from other pthread_*** functions, which are expected to behave the same on all conforming implementations. Since the purpose of this function is to provide a *portable* wrapper around different versions of those functions, having the suffix here seems wrong.

llvm/lib/Support/Unix/Threading.inc
100 ↗(On Diff #90421)

I am wondering whether this is a useful fallback. pthread_t is used in completely different contexts than OS-level thread handles, so it may be better to just return 0 or something here. I don't feel strongly about it though.

labath accepted this revision.Mar 3 2017, 7:19 AM

I think the same goes for net/freebsd threads as well. Potentially we could document that the thread id only makes sense within the context of the current process, but I think that's about it.

looks good as far as I am concerned.

This revision is now accepted and ready to land.Mar 3 2017, 7:19 AM
This revision was automatically updated to reflect the committed changes.

I will improve this code for NetBSD as we must not include <sys/user.h>. This header is long empty and it will be removed.

thakis added a subscriber: thakis.Apr 28 2018, 5:37 PM
thakis added inline comments.
llvm/trunk/lib/Support/Unix/Threading.inc
98

LLVM_ON_WIN32 will never be set in Unix/Threading.inc, will it? Is this branch ever used?

Hmm I don’t remember why i did that, certainly looks like an accident

Removed it in r331151, thanks!

TomTan added a subscriber: TomTan.Jan 2 2019, 4:17 PM

Hi Zachary, does this line "#include "Windows/WindowsSupport.h" " need to be changed to "#include "WindowsSupport.h" " after it is moved from Threading.cpp to Threading.inc, because Threading.inc which includes WindowsSupport.h is under Windows folder, so no need to have it in the include path. This current include path could trigger warning "#include resolved using non-portable Microsoft search rules as: ..."