Mailing-List: contact cygwin-help AT sourceware DOT cygnus DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT sources DOT redhat DOT com Delivered-To: mailing list cygwin AT sources DOT redhat DOT com Message-ID: <3AD1D41D.2FC62EF1@mip.sdu.dk> Date: Mon, 09 Apr 2001 17:24:13 +0200 From: =?iso-8859-1?Q?Ren=E9=20M=F8ller?= Fonseca Organization: MIP, University of Southern Denmark X-Mailer: Mozilla 4.76 [en] (Windows NT 5.0; U) X-Accept-Language: en MIME-Version: 1.0 To: Robert Collins Cc: cygwin AT cygwin DOT com Subject: Re: contribution soapbox(was Re: G++ guru's please comment - Re: FW: pthread_create problem in Cygwin 1.1.8-2]) References: <3AD1A64D DOT 7DC36DF0 AT mip DOT sdu DOT dk> <012a01c0c0f1$baf65110$0200a8c0 AT lifelesswks> Content-Type: multipart/mixed; boundary="------------BB7DACD615389B0C8EB49F59" --------------BB7DACD615389B0C8EB49F59 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit 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" > > > 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 --------------BB7DACD615389B0C8EB49F59 Content-Type: text/plain; charset=us-ascii; name="main.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="main.c" #include 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; } --------------BB7DACD615389B0C8EB49F59 Content-Type: text/plain; charset=us-ascii -- Want to unsubscribe from this list? Check out: http://cygwin.com/ml/#unsubscribe-simple --------------BB7DACD615389B0C8EB49F59--