8 Jun 2002 (updated 8 Jun 2002 at 06:06 UTC)
»
Valgrind
tried playing with valgrind to debug evolution-mail at
home here, on my celeron 400 w/ 256 mb ram and it was just a
might bit slower than molasis flowing uphill in january
while being debugged under gdb on a low-end solaris machine
remotely over ssh with X forwarding (well, it would be if
molasis was a unix X application).
just so you don't get your panties in a twist, I don't
put the full blame of this on valgrind (which is why I
mention I'm running a celeron - not to mention
evolution-mail is a heavy weight champion on steroids).
valgrind has certainly come a long way since I last
looked at it a few months ago - in fact, last time I looked
at it, it wasn't able to handle any multithreaded
application at all, and now it can even handle
evolution-mail (albeit a bit slowly on my hardware).
overall, I'm still impressed to say the least. sure beats
the pants off my libeaks LD_PRELOAD hack.
POSIX Threads
Let me just say... they screwed the pooch on this one.
I'm extremely disappointed that pthread_once()
doesn't block until the callback has been completed. Rather,
the first thread to get to the pthread_once() function gets
to call the callback while the other threads return
immediately and go on their merry way. The whole point of
this function as far as I can tell is to provide a means for
applications to initialise some static data for later use by
the rest of the library/function/whatever. Unfortunately,
the fact that all other threads return immediately makes
this totally useless for that operation because initialising
data in that pthread_once() callback function is not
an atomic operation. So here, let me give you the way this
should have been implemented
in-my-not-so-humble-but-correct-opinion:
typedef struct {
pthread_mutex_t mutex;
unsigned int complete;
} pthread_once_t;
#define PTHREAD_ONCE_INIT { PTHREAD_MUTEX_INITIALIZER, 0 }
int
pthread_once (pthread_once_t *once, void (*init_func)
(void))
{
if (!once->complete) {
pthread_mutex_lock (&once->mutex);
if (!once->complete) {
init_func ();
once->complete = 1;
}
pthread_mutex_unlock (&once->mutex);
}
return 0;
}
While I'm on the subject, I think I'm gonna write a
library called ppthreads (Portable Portable Operating System
Interface Threads) or maybe tppthreads (Truly Portable
Portable Operating System Interface Threads) since pthreads
are notoriously not portable at all. Well, at least not
beyond the very basics. I've spent a lot of time stumbling
over inconsistancies between Linux and Solaris
pthreads (and apparently Mac OS X pthreads aren't so
complete either) in the Mono
project. Everytime
I get time to hack on the SPARC port I find myself porting
the code over to Solaris.
Isn't it sad when portable doesn't mean portable?