Hi Robert, The tricky part is to make pthread_once MT-safe without doing a busy wait. Your code is not MT-safe; more than one thread can enter init_routine. I'm not familiar with the requirements of pthread_once but I'm expecting the following to be true: 1. Only one thread may enter init_routine (otherwise the "once" suffix doesn't make any sense). 2. if init_routine is currently being run by some thread then all other threads must block until the function has completed. Here is my implementation of pthread_once using busy waiting. If init_routine takes a long time then busy waiting becomes very bad :-( >>>> typedef struct {unsigned int state; unsigned int lock;} pthread_once_t; #define PTHREAD_ONCE_INIT {0, 0} inline unsigned int pthread_once_try_lock(pthread_once_t* once_control) { register unsigned int previous; asm volatile ("xchgl %0, %1" : "=&r" (previous), "=m" (once_control->lock) : "0" (1)); return !previous; } int __pthread_once(pthread_once_t* once_control, void (*init_routine) (void)) { if (!once_control->state) { // should init_routine possible be called by this thread while (!pthread_once_try_lock(once_control)); // wait for exclusive lock // only one thread can be here at any time if (!once_control->state) { // should this thread run init_routine init_routine(); once_control->state = 1; // make sure init_routine is not called again } once_control->lock = 0; // release lock } return 0; } <<<< Warning: I have not checked and optimized it thoroughly. P.S. I have put the code in the attachment! René Robert Collins wrote: > > Rene, this isn't pointed at you! I just reread my reply and I realised > I'd missed an IMO important point. > > ----- Original Message ----- > From: "René Møller Fonseca" <[EMAIL PROTECTED]> > > > Please correct me if I'm wrong. > > > > The problem, as I understand it, is that gcc is not built with thread > > support which is required for exception handling to work in a > > multithreaded environment. Unfortunately the thread support has not > been > > ported to the win32 api. I suspect functionality like "pthread_once" > to > > be required (tricky to implement). > > Guys, Girls, secret service agents, > > Contributing to cygwin is not hard. In fact it's dead easy. The biggest > obstacle is perception. All you need are basic C++ (even straight C will > do if you're a hacker or just willing to try new things) skills, and a > small target. > > (Non-coders, you are hereby off the coding hook, and onto the why don't > you contribute your knowledge in the form of feedback on documentation - > something every open source project can use more of). > > I strongly suspect that most of you coders out there are guilty of the > thought "Gee it would be nice if cygwin had feature foo, but I [wouldn't > know where to start to fix it|I don't have the time to contribute] so > I'll just spend hours now working around the lack of foo". > > I am guilty of that thought. Then one day I got tired of the the fact > that I couldn't built squid with thread support, so I ported the thread > code to win32 threads. During that port I realised just how thin a layer > cygwin is over win32 - it's hardly there at all. So I threw out the > win32 threads code, and fixed up what was missing in Cygwin. That core > fixup took me about twice as long as porting the original code, but I > can reuse the fixedup cygwin code to port other applications with > greater ease. > > The follow-up to that spurt of coding was that I got tired of the > lamentations about threads and cygwin and started fixing the entire > thread support... In fact I've now been labelled the pthreads > maintainer, which as far as I can tell means that you lot are now > *allowed* to complain about pthreads! > > I want to ask you all to do something for cygwin (and I have no right to > ask this, but I'm going to anyway): The next time you work around a bug > in cygwin when porting an application, put aside 2 hours (thats all > you'll need for most things). Download the cygwin source via CVS. (The > documentation is accurate). Build it. Add your feature, or a tweak to an > existing feature, or even just the outline code to return ENOSYS - no > supported for the relevant function call. Send that in with a Changelog. > You've now become a contributor, and saved yourself sending in a patch > to the application developers for cygwin compatability, all by changing > cygwin. And in future, chances are someone else will add to what you've > done, and finish off your partial code, or tweak it even more. > > Rob. > > P.S. To support my claim about perception being the issue, here is the > code for the diffucult function pthread_once. > > int > __pthread_once (pthread_once_t * once_control, void (*init_routine) > (void)) > { > if (*once_control!=PTHREAD_ONCE_INIT) > init_routine(); > *once_control=!PTHREAD_ONCE_INIT; > return 0; > } > > And most of the cygwin internal functions are not much longer. > > -- > Want to unsubscribe from this list? > Check out: http://cygwin.com/ml/#unsubscribe-simple
#include <stdio.h> typedef struct {unsigned int state; unsigned int lock;} pthread_once_t; #define PTHREAD_ONCE_INIT {0, 0} inline unsigned int pthread_once_try_lock(pthread_once_t* once_control) { register unsigned int previous; asm volatile ("xchgl %0, %1" : "=&r" (previous), "=m" (once_control->lock) : "0" (1)); return !previous; } int __pthread_once(pthread_once_t* once_control, void (*init_routine) (void)) { if (!once_control->state) { // should init_routine possible be called by this thread while (!pthread_once_try_lock(once_control)); // wait for exclusive lock // only one thread can be here at any time if (!once_control->state) { // should this thread run init_routine printf("D: state=%d lock=%d\n", once_control->state, once_control->lock); init_routine(); once_control->state = 1; // make sure init_routine is not called again } once_control->lock = 0; // release lock } return 0; } void myfunction() { printf("I'm only executed once\n"); } int main() { pthread_once_t once= PTHREAD_ONCE_INIT; printf("A: state=%d lock=%d\n", once.state, once.lock); __pthread_once(&once, &myfunction); printf("B: state=%d lock=%d\n", once.state, once.lock); __pthread_once(&once, &myfunction); printf("C: state=%d lock=%d\n", once.state, once.lock); return 0; }
-- Want to unsubscribe from this list? Check out: http://cygwin.com/ml/#unsubscribe-simple