OpenQNX :: The QNX Community Portal

Jul 25, 2008 - 04:08 PM
Google
  Web openqnx.com   
     Create an account Home · Submit News · QNX Forums · QNX Download · Search   
_
Main Menu
Who's Online
There are 26 unlogged users and 4 registered users online.

You can log-in or register for a user account here.

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
m2asseli
Post subject: Mutex with DrawFunction for PtRaw  PostPosted: Apr 20, 2007 - 02:58 AM
Senior Member


Joined: May 11, 2004
Posts: 100

Hello,

I have a PtRaw widget which I am plotting points inside. The redraw function for the PtRaw (when it gets damaged) accesses a global structure. This structure gets updated in another thread, and thus, I had to use a mutex to ensure the redraw function did not access any of it's members while they were being modified.

The problem is, the mutex won't work!!! Are there any tricks to mutexes in Photon processes? I declared the mutex in a global header, initialized it to the default values (removed priority inheritance however), and lock it (or so I thought) before doing modifications to the variables. However, when I get into the redraw function, and I try to obtain the mutex, it doesn't block even though I just locked-it!

Any suggestions?
Thanks.
 
 View user's profile Send private message Visit poster's website  
Reply with quote Back to top
maschoen
Post subject: RE: Mutex with DrawFunction for PtRaw  PostPosted: Apr 20, 2007 - 05:27 AM
QNX Master


Joined: Jun 25, 2003
Posts: 1045

Show us some code. Maybe build a very simple two threaded example that shows the problem?
 
 View user's profile Send private message Send e-mail Visit poster's website  
Reply with quote Back to top
xtang
Post subject: RE: Mutex with DrawFunction for PtRaw  PostPosted: Apr 20, 2007 - 08:23 PM
QNX Master


Joined: Jul 18, 2002
Posts: 291

What function you use to "lock" the mutex, and what is the return value of that function?
 
 View user's profile Send private message Visit poster's website  
Reply with quote Back to top
m2asseli
Post subject:   PostPosted: Apr 23, 2007 - 01:56 AM
Senior Member


Joined: May 11, 2004
Posts: 100

Here is a same code that gives the same "error" as my real code. The error code (45) shown in the output indicates that my thread already has the mutex locked, which is why it cannot lock it again. How can I get around this? The draw() function is called automatically when I attempt to create a new widget on the PtRaw widget.

Thanks.


----------------------------------------------------

#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <Pt.h>

void draw(PtWidget_t * widget, PhTile_t * damage);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
PtArg_t args[4];
PhDim_t Dim = {100,100};
PhPoint_t Pos={10,10},Pos2={0,0};
PtWidget_t *Window,*Raw;

int main(int argc, char *argv[])
{
if( PtInit(NULL)==-1 )
exit(EXIT_FAILURE);
PtSetArg(&args[0], Pt_ARG_POS, &Pos, 0);
PtSetArg(&args[1], Pt_ARG_DIM, &Dim, 0);
if( (Window=PtCreateWidget(PtWindow,Pt_NO_PARENT,2,args)) == NULL)
PtExit(EXIT_FAILURE);

EOK,EAGAIN,EDEADLK,EFAULT,EINVAL,ETIMEDOUT);fflush(stdout);

PtSetArg(&args[0], Pt_ARG_POS, &Pos2, 0);
PtSetArg(&args[2], Pt_ARG_RAW_DRAW_F, &draw, 1 );
if( (Raw=PtCreateWidget(PtRaw,Pt_DEFAULT_PARENT,3,args)) == NULL )
PtExit(EXIT_FAILURE);
PtRealizeWidget(Window);

printf("Lock1: %i\n",pthread_mutex_lock(&mutex));fflush(stdout);
PtRealizeWidget(PtCreateWidget(PtButton,Pt_DEFAULT_PARENT,0,NULL));
printf("UnLock1: %i\n",pthread_mutex_unlock(&mutex));fflush(stdout);

PtMainLoop();
pthread_mutex_destroy( &mutex );
return EXIT_SUCCESS;
}
void draw( PtWidget_t *widget, PhTile_t *damage )
{
PtSuperClassDraw( PtBasic, widget, damage );
printf("Lock2: %i\n",pthread_mutex_lock(&mutex));fflush(stdout);
printf("Do some Raw Drawing.\n");fflush(stdout);
printf("UnLock2: %i\n",pthread_mutex_unlock(&mutex));fflush(stdout);

return;
}


----------------------------------------------------
OUTPUT:

Lock2: 0
Do some Raw Drawing.
UnLock2: 0
Lock1: 0
Lock2: 45
Do some Raw Drawing.
UnLock2: 0
UnLock1: 1
Lock2: 0
Do some Raw Drawing.
UnLock2: 0
 
 View user's profile Send private message Visit poster's website  
Reply with quote Back to top
maschoen
Post subject:   PostPosted: Apr 23, 2007 - 05:09 AM
QNX Master


Joined: Jun 25, 2003
Posts: 1045

m2asseli wrote:
Here is a same code that gives the same "error" as my real code. The error code (45) shown in the output indicates that my thread already has the mutex locked, which is why it cannot lock it again. How can I get around this? The draw() function is called automatically when I attempt to create a new widget on the PtRaw widget.



The answer is very simple. Let me give you two very big hints.
45 = EDEADLK (Deadlock avoided).
This occurs when a thread which has locked a mutex tries to lock it again, non-recursively. Since it would have to wait for itself to unlock the thread, an event that can never happen while it is waiting, the OS returns an error indicating that the dead lock was avoided.

Note, this is not the same as one thread locking a mutex, and a second trying to lock it. In that case, thread 2 would become blocked waiting for thread 1.

I said 2 hints, but the 2nd should be very clear now, you are only dealing with ONE thread here.

Now take a look at your code, the output, and think about the relationship between the Realize call and the draw call, and you will learn something important.

Good luck.
 
 View user's profile Send private message Send e-mail Visit poster's website  
Reply with quote Back to top
m2asseli
Post subject:   PostPosted: Apr 23, 2007 - 02:01 PM
Senior Member


Joined: May 11, 2004
Posts: 100

I feel like I'm back in school.....with an electronic blackboard.

I realize that the PtRealize function invokes the PtRaw's draw function, since I am damaging the PtRaw's canvas by realizing a new widget (within the same thread). In my real code, I am changing values to a structure, which in turn creates new widgets over-top the PtRaw. By creating the new widgets, I am damaging the PtRaw and it's draw function gets called.....which in turn uses the structure which is being modified! Hence why I was trying to use a mutex to avoid accessing possibly invalid structure member values. Does this make sense to you?

Solution? Temporarily disable the draw function until I have completed the changes to the structure members, and have finished with the PtRealize functions. Afterwards, re-instate the draw function and damage the PtRaw, which will then be able to use VALID data from the structure's members.

Correct?
 
 View user's profile Send private message Visit poster's website  
Reply with quote Back to top
maschoen
Post subject:   PostPosted: Apr 23, 2007 - 07:45 PM
QNX Master


Joined: Jun 25, 2003
Posts: 1045

Sorry about invoking teacher mode, I thought you might like to discover this yourself.
It's definitely a Doh! moment.
The reason are seeing this behavior is that PtRealize calls the Draw function.
Here is a psuedo version of what is happening.

main()
{

pthread_mutex_lock()
PtRealize();


}

PtRealize()
{

draw();

}

draw()
{

//This lock fails with 45
pthread_mutex_lock();

}

You only have one thread, so using a mutex is pointless here.
Maybe you are thinking of Java where the Java machine would
silently schedule a draw thread that you don't want to interfere with.

Maybe what is confusing is that with Photon there are other threads going on.
For example, the Photon kernel has a thread, and the video driver itself
has a thread. But these are in different processes, communicated to by
message passing. You don't have to worry about interfering with these.

The only reason you would need a mutex at all if you have more than
one thread in your own code, which you do not appear to.
If you did, you might keep the lock in the draw function, but
not call it in the main().
 
 View user's profile Send private message Send e-mail Visit poster's website  
Reply with quote Back to top
m2asseli
Post subject:   PostPosted: Apr 23, 2007 - 09:27 PM
Senior Member


Joined: May 11, 2004
Posts: 100

Yeah, the DOH hit pretty quick after your first posting.

For some reason I was under the impression that the draw function was called by PtRealize in a new thread, so it would block until I finished modifying my variables. I can see I will have to make some slight modifications to my code, but nothing too difficult.

Thanks maschoen.
 
 View user's profile Send private message Visit poster's website  
Reply with quote Back to top
tfletche
Post subject:   PostPosted: Apr 26, 2007 - 12:42 AM
QNX Master


Joined: Apr 11, 2007
Posts: 36

Alternately, if you really are using multiple threads and this scenario is just an initialization "unfortunate situation" consider using a recursive mutex.

_________________
Thomas
http://sendreceivereply.wordpress.com
 
 View user's profile Send private message Visit poster's website  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2007 The PNphpBB Group
Credits
All logos and trademarks in this site are property of their respective owners. The comments are property of their posters.
Powered by OpenQNX: The QNX Community Portal Site
QNX and the QNX logo are registered trademarks of QNX Software Systems.