Fixed get/set thread name implementations for macOS and FreeBSD
So, the story of fixing `pthread_getname_np` and `pthread_setname_np` continues, but this time I fixed the macOS implementation.
### [`pthread_getname_np`](c032e0b076/src/pthread.c (L1160-L1175))
The function never fails except for an invalid thread. Miri never verifies thread identifiers and uses them as indices when accessing a vector of threads. Therefore, the only possible result is `0` and a possibly trimmed output.
```c
int
pthread_getname_np(pthread_t thread, char *threadname, size_t len)
{
if (thread == pthread_self()) {
strlcpy(threadname, thread->pthread_name, len);
return 0;
}
if (!_pthread_validate_thread_and_list_lock(thread)) {
return ESRCH;
}
strlcpy(threadname, thread->pthread_name, len);
_pthread_lock_unlock(&_pthread_list_lock);
return 0;
}
```
#### [`strcpy`](https://www.man7.org/linux/man-pages/man7/strlcpy.7.html)
```
strlcpy(3bsd)
strlcat(3bsd)
Copy and catenate the input string into a destination
string. If the destination buffer, limited by its size,
isn't large enough to hold the copy, the resulting string
is truncated (but it is guaranteed to be null-terminated).
They return the length of the total string they tried to
create.
```
### [`pthread_setname_np`](c032e0b076/src/pthread.c (L1178-L1200))
```c
pthread_setname_np(const char *name)
{
int res;
pthread_t self = pthread_self();
size_t len = 0;
if (name != NULL) {
len = strlen(name);
}
_pthread_validate_signature(self);
res = __proc_info(5, getpid(), 2, (uint64_t)0, (void*)name, (int)len);
if (res == 0) {
if (len > 0) {
strlcpy(self->pthread_name, name, MAXTHREADNAMESIZE);
} else {
bzero(self->pthread_name, MAXTHREADNAMESIZE);
}
}
return res;
}
```
Where `5` is [`PROC_INFO_CALL_SETCONTROL`](8d741a5de7/bsd/sys/proc_info_private.h (L274)), and `2` is [`PROC_INFO_CALL_SETCONTROL`](8d741a5de7/bsd/sys/proc_info.h (L821)). And `__proc_info` is a syscall handled by the XNU kernel by [`proc_info_internal`](8d741a5de7/bsd/kern/proc_info.c (L300-L314)):
```c
int
proc_info_internal(int callnum, int pid, uint32_t flags, uint64_t ext_id, int flavor, uint64_t arg, user_addr_t buffer, uint32_t buffersize, int32_t * retval)
{
switch (callnum) {
// ...
case PROC_INFO_CALL_SETCONTROL:
return proc_setcontrol(pid, flavor, arg, buffer, buffersize, retval);
```
And the actual logic from [`proc_setcontrol`](8d741a5de7/bsd/kern/proc_info.c (L3218-L3227)):
```c
case PROC_SELFSET_THREADNAME: {
/*
* This is a bit ugly, as it copies the name into the kernel, and then
* invokes bsd_setthreadname again to copy it into the uthread name
* buffer. Hopefully this isn't such a hot codepath that an additional
* MAXTHREADNAMESIZE copy is a big issue.
*/
if (buffersize > (MAXTHREADNAMESIZE - 1)) {
return ENAMETOOLONG;
}
```
Unrelated to the current pull request, but perhaps, there's a very ugly thing in the kernel/libc because the last thing happening in `PROC_SELFSET_THREADNAME` is `bsd_setthreadname` which sets the name in the user space. But we just saw that `pthread_setname_np` sets the name in the user space too. Guess, I need to open a ticket in one of Apple's repositories at least to clarify that :D
Pipe minor changes: diagnostics, flag support and comments
This PR:
- Add the exact syscall names to the blocking not supported diagnostic
- Added support for ``pipe2`` ``O_NONBLOCK``
- Fix minor comment error in ``tests/pass-dep/libc/libc-epoll-blocking.rs``
Fixes#3912
Fix over synchronization of epoll
Fixes#3944.
The clock used by epoll is now per event generated, rather than by the `epoll's` ready_list.
The same epoll tests that existed before are unchanged and still pass. Also the `tokio` test case we had worked on last week still passes with this change.
This change does beg the question of how the epoll event states should change. Perhaps rather than expose public crate bool fields, so setters should be provided that include a clock parameter or an optional clock parameter. Also should all the epoll event possibilities have their clock sync tested the way these commit lay out testing. In this first go around, only the pipe's EPOLLIN is tested. The EPOLLOUT might deserve testing too, as would the eventfd. Any future source of epoll events would also fit into that category.
Fixed pthread_getname_np impl for glibc
The behavior of `glibc` differs a bit different for `pthread_getname_np` from other implementations. It requires the buffer to be at least 16 bytes wide without exception.
[Docs](https://www.man7.org/linux/man-pages/man3/pthread_setname_np.3.html):
```
The pthread_getname_np() function can be used to retrieve the
name of the thread. The thread argument specifies the thread
whose name is to be retrieved. The buffer name is used to return
the thread name; size specifies the number of bytes available in
name. The buffer specified by name should be at least 16
characters in length. The returned thread name in the output
buffer will be null terminated.
```
[Source](https://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/pthread_getname.c;hb=dff8da6b3e89b986bb7f6b1ec18cf65d5972e307#l37):
```c
int
__pthread_getname_np (pthread_t th, char *buf, size_t len)
{
const struct pthread *pd = (const struct pthread *) th;
/* Unfortunately the kernel headers do not export the TASK_COMM_LEN
macro. So we have to define it here. */
#define TASK_COMM_LEN 16
if (len < TASK_COMM_LEN)
return ERANGE;
```
Added rust-analyzer instructions for Helix
That pull request adds information on how to configure Helix to use `rust-analyzer`, and moves the existing configuration to the `src/etc` directory as it's in the `rust` repository. Not adding instructions for other IDE because there's a link leading to the how-to for `rustc`.
avoid pthread_attr_t in tests
We don't support `pthread_attr_init` so the code here is actually technically wrong (passing attributes to `pthread_create` that were not initialized properly). It's also unnecessary, we can just pass a null pointer for the attributes to indicate "default attributes please".
Prefer refutable slice patterns over len check + index op
Just something I noticed while reviewing other PRs
We do it for shim arguments almost everywhere, but when the size is not statically known, we didn't use the helpers as they rely on array ops. But we can avoid a len check followed by several index ops by just using a refutable slice pattern with `let else`.
The pattern is so common, it seems almost worth a dedicated macro