Is there a wishlist?

"Markus Wichmann" <[email protected]> Sun, 9 Jan 2011 16:02:04 +0100 (CET)
Newsgroups gmane.linux.lib.dietlibc
Message-ID <[email protected]>
Hi all,

I thought I could work on some features, but I just wanted to know whether
you'd even want them (I dislike to waste my time).

I planned on doing:

- dynamic interpreter support

I.e. run the interpreter like a program and let the first argument be the
program to run. Like ld.so from glibc can. Would be good for testing. Well
it also won't be exactly the same as running as loader. But the glibc guys
couldn't do that as well:

$ /lib/ld*.so /bin/readlink /proc/self/exe
/lib/ld-2.11.2.so

- thread safe errno

Either I didn't look in the right places or handling of errno really isn't
thread safe in dietlibc. How about doing something similar to the glibc,
just not as broken? I thought of

errno.c:
int errno;
#ifdef WANT_THREAD_SAFE
__thread int t_errno;
static pid_t pid;
int* __errno_location()
{

    if (!pid) pid = getpid();
    if (pid == gettid()) return &errno;
    else return &t_errno;
}
#endif

Or something the like. That should keep "extern int errno;" working for
any single threaded program, and even any multithreaded program that only
accesses errno in the main thread. Overhead: One int is superfluous,
namely the t_errno in the main thread. Cannot do much about it. The
alternative would be something like a process global array of errnos. And
an additional array of TIDs, so that the index of this thread's TID into
the TID array would be the same as the index of this thread's errno into
the errno array. Now that should do the trick, but the overhead would be
the number of threads times the size of a TID. Plus, I don't know of a
portable lock-free algorithm to extend a shared dynamic array.

Plus, while scooping around with that matter, I stumbled across a pretty
strange bug. Consider this source code:

#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#ifdef GLIBC
#include <sys/syscall.h>

pid_t gettid()
{
    return syscall(SYS_gettid);
}
#endif

void* child_main(void* data)
{
    (void) data;
    printf("Child TID: %d\n", gettid());
    return NULL;
}

int main()
{
    pthread_t t;
    printf("PID: %d\n", getpid());
    printf("Main TID before pthread_create: %d\n", gettid());
    pthread_create(&t, NULL, child_main, NULL);
    printf("Main TID after pthread_create: %d\n", gettid());
    pthread_join(t, NULL);
    return 0;
}

When compiled against glibc, it runs. When compiled against dietlibc (with
-pthread and -lpthread), the code fails after the second printf. According
to strace, the last system call is sched_yield(). After that, no signal,
no exit(), nothing. Just went dead. How can a process exit without calling
exit() or being signalled?

- introduce futexes
I noticed in libpthread that the mutex locking stuff is done via busy
waits. How about introducing futexes there? Instead of looping
indefinitely, we just have all of the threads queue up and wait to be
woken. It looks easy enough to me. It won't need to be as fancy as the
glibc implementation, where they included a third state for the mutex.
"Locked and there's processes waiting" Now the problem is, you could only
do that with either a more powerful atomic instruction, like compare and
swap, or by wasting some space. Plus it increases complexity of the code,
just to save one system call. And here I was thinking system calls are
cheap.

CYA,
Markus
-- 
Progress (n.): Process through which USENET evolved from smart people in
front of dumb terminals to dumb people in front of smart terminals.