Hi Ico,

just quick:

pthread_create() returns after the thread context has been created; but
the actual thread-function is not run directly.

The main function may continue before the actual thread is run.

In your case the pd_cwiid_doConnect() can be called before the
pd_cwiid_pthreadForAudioUnfriendlyOperations() enters the while() loop.

That seems to be a problem - it's too much code to dig though for me at
the moment to tell why this is so -  but since usleep() seems to solve
the issue, it probably is. (quick check: does it also crash if you
usleep() after the if (argc==2) {}; just before the return(x); ?

`man 3 pthread_yield` is better that usleep(). it's basically a
usleep(minimum-time-needed-to-run-other-threads).

Another option is to wait after thread-creation in the parent on a
barrier or lock that is released by the child-thread when it starts.

2c,
robin

On 10/02/10 02:36, Ivica Ico Bukvic wrote:
> Hi all,
> 
> I am wondering if anyone can shed some light on the following
> predicament. I am by no means a multi-threading guru so any insight
> would be most appreciated.
> 
> The following are relevant excerpts from the code of an external. AFAIK
> the external initializes mutex and cond and spawns a secondary worker
> thread that deals with audio-unfriendly (xrun-causing) write operations
> to the wiimote and terminates it when the object is destructed waiting
> for the thread to join back and then destroying the mutex.
> 
> Now, if I add a bit of usleep right after the thread has been spawned as
> part of the constructor (as included below) the external seems very
> stable (e.g. cutting and pasting it as fast as keyboard allows, or in
> other words constructing and destructing instances of it as fast as
> possible does not result in a crash). Yet, when one does not use usleep
> right after spawning the secondary (worker) thread in the constructor,
> the whole thing is very crash-prone, almost as if the spawning of thread
> does not go well unless given adequate time to do get things all into
> sync, so to say, even though this makes to me no sense as the way I
> understand it the constructor does not move ahead until pthread_create
> does not return a value (which in this case I am not bothering to read).
> 
> Curiously, when not using usleep, a crash may occur right at creation
> time, at any point while the object exists, and even as late as during
> its destruction. Any ideas?
> 
> P.S. I am also including the entire file for those interested in trying
> it out.
> 
> Best wishes,
> 
> Ico
> 
> Relevant excerpts (in random order and incomplete to allow for greater
> legibility):
> 
> //struct defining the object
> typedef struct _wiimote
> {
>       t_object x_obj; // standard pd object (must be first in struct)
> 
>       ...
>       
>       //Creating separate threads for actions known to cause sample drop-outs
>       pthread_t unsafe_t;
>       pthread_mutex_t unsafe_mutex;
>       pthread_cond_t unsafe_cond;
> 
>       t_float unsafe;
> 
>       ...
> 
>       t_float led;
> 
>       ...
> 
> } t_wiimote;
> 
> 
> //constructor
> static void *pd_cwiid_new(t_symbol* s, int argc, t_atom *argv)
> {
>       ...
> 
>       x->led = 0;
> 
>       // spawn threads for actions known to cause sample drop-outs
>       threadedFunctionParams rPars;
>       rPars.wiimote = x;
>       pthread_mutex_init(&x->unsafe_mutex, NULL);
>       pthread_cond_init(&x->unsafe_cond, NULL);
>       pthread_create( &x->unsafe_t, NULL, (void *)
> &pd_cwiid_pthreadForAudioUnfriendlyOperations, (void *) &rPars);
> 
>       //WHY IS THIS NECESSARY? I thought that pthread_create call will first
> finish spawning thread before proceeding
>       usleep(100); //allow thread to sync (is there a better way to do this?)
>       
>       ...
> }
> 
> //destructor
> static void pd_cwiid_free(t_wiimote* x)
> {
>       if (x->connected) {
>               pd_cwiid_doDisconnect(x); //this one has nothing to do with 
> thread but
> rather disconnects the wiimote
>       }
> 
>       x->unsafe = -1; //to allow secondary thread to exit the while loop
> 
>       pthread_mutex_lock(&x->unsafe_mutex);
>       pthread_cond_signal(&x->unsafe_cond);
>       pthread_mutex_unlock(&x->unsafe_mutex);
> 
>       pthread_join(x->unsafe_t, NULL);
>       pthread_mutex_destroy(&x->unsafe_mutex);
> 
>       ...
> }
> 
> //worker thread
> void pd_cwiid_pthreadForAudioUnfriendlyOperations(void *ptr)
> {
>       threadedFunctionParams *rPars = (threadedFunctionParams*)ptr;
>       t_wiimote *x = rPars->wiimote;
>       t_float local_led = 0;
>       t_float local_rumble = 0;
>       unsigned char local_rpt_mode = x->rpt_mode;
> 
>       while(x->unsafe > -1) {
>               pthread_mutex_lock(&x->unsafe_mutex);
>               if ((local_led == x->led) && (local_rumble == x->rumble) &&
> (local_rpt_mode == x->rpt_mode)) {
>                       pthread_cond_wait(&x->unsafe_cond, &x->unsafe_mutex);
>               }
> 
>               if (local_led != x->led) {
>                       local_led = x->led;
>                       //do something
>                       }
>               }
>               if (local_rumble != x->rumble) {
>                       local_rumble = x->rumble;
>                       //do something else
>               }
> 
>               ...
> 
>               pthread_mutex_unlock(&x->unsafe_mutex);
>       }
>       pthread_exit(0);
> }
> 
> //an example of how the thread is affected by the main thread
> void pd_cwiid_setLED(t_wiimote *x, t_floatarg f)
> {
>       if (x->connected) {
>               x->led = f;
> 
>               pthread_mutex_lock(&x->unsafe_mutex);
>               pthread_cond_signal(&x->unsafe_cond);
>               pthread_mutex_unlock(&x->unsafe_mutex);
>       }
> }
> 
> 
> 
> 
> _______________________________________________
> Linux-audio-dev mailing list
> Linux-audio-dev@lists.linuxaudio.org
> http://lists.linuxaudio.org/listinfo/linux-audio-dev
_______________________________________________
Linux-audio-dev mailing list
Linux-audio-dev@lists.linuxaudio.org
http://lists.linuxaudio.org/listinfo/linux-audio-dev

Reply via email to