Re: [PATCH 2/4] X event queue mutex

2008-11-07 Thread Tiago Vignatti
Hi Jeremy,

Jeremy Huddleston escreveu:
 Well the problem was that mieqProcessInputEvents DOESN'T use those 
 locks, so it can read the incremented value of miEventQueue.tail 
 thinking that the item at head=tail-1 is ready to read when in fact 
 mieqEnqueue is still in the process of writing to it.
 
 Further, mieqEnqueue sometimes edits miEventQueue.tail-1 (when the 
 current and tail-1 events are MotionNotify)... but 
 mieqProcessInputEvents is already reading it.

yeah. Now your last patch makes more sense to me (but not that first hunk).


 For this reason, I went back to locking inside mieqProcessInputEvents 
 with XQUARTZ.

Your mutex will lags your cursor update on screen because the input 
thread will block before enqueuing while the main thread pops events. On 
this case try to keep the lock near the critical region on mieqPIE, 
avoiding coarse grained locking.


Cheers,

PS: this problem of the event queue being processed by more then one 
user shows how multi-threaded applications suck so much to program. 
Moreover, if you try to use gdb to debug then you'll see the crazy world 
that we're living.

-- 
Tiago Vignatti
C3SL - Centro de Computação Científica e Software Livre
www.c3sl.ufpr.br
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg


Re: [PATCH 2/4] X event queue mutex

2008-11-07 Thread Jeremy Huddleston

On Nov 7, 2008, at 12:23, Tiago Vignatti wrote:
For this reason, I went back to locking inside  
mieqProcessInputEvents with XQUARTZ.


Your mutex will lags your cursor update on screen because the input  
thread will block before enqueuing while the main thread pops  
events. On this case try to keep the lock near the critical region  
on mieqPIE, avoiding coarse grained locking.



Cheers,

PS: this problem of the event queue being processed by more then one  
user shows how multi-threaded applications suck so much to program.  
Moreover, if you try to use gdb to debug then you'll see the crazy  
world that we're living.


Yeah, that's pretty much what it's doing now in the xorg-server-1.4- 
apple branch... the one thing I don't like is that screensaver  
block... can that be moved to after we copy the event (to lessen the  
lock time) or is there some reason that I don't see that it's first?


--Jeremy



smime.p7s
Description: S/MIME cryptographic signature
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Re: [PATCH 2/4] X event queue mutex

2008-11-06 Thread Tiago Vignatti
Peter Hutterer escreveu:
 From: Peter Hutterer [EMAIL PROTECTED]
 Date: Tue, 4 Nov 2008 15:27:30 +1030
 Subject: [PATCH] mi: clean up mieqProcessInputEvents, copy all events before 
 processing.
 
 Copy the EventRec's information into local variables before processing them,
 this should make it safer for upcoming threading and also makes it easier to
 read.
 
 Simplify the event allocation code from the abyss it was before.
 
 This also fixes a potential bug where a custom handler could scramble the
 event before the same -now scrambled- event was then passed through the
 master's custom event handler.
 
 Signed-off-by: Peter Hutterer [EMAIL PROTECTED]

Signed-off-by Tiago Vignatti [EMAIL PROTECTED]

It's fine for me. Applied and tested here.


Thanks,

-- 
Tiago Vignatti
C3SL - Centro de Computação Científica e Software Livre
www.c3sl.ufpr.br
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg


Re: [PATCH 2/4] X event queue mutex

2008-11-06 Thread Tiago Vignatti
Hey,

Jeremy Huddleston escreveu:
 Looks good!  A recent bug report has surfaced for us since I got rid of 
 the locking in mieqProcessInputEvents.  We need to update 
 miEventQueue.tail only after the data has actually been pushed into the 
 tail.  This should take care of that problem on master, but I haven't 
 tested it:

Well, it won't be a problem with Xorg input thread because mieqEnqueue 
is tread-safe. There's a mutex protecting writes to the tail pointer in 
that function and xquartz will need it as well.


 diff --git a/mi/mieq.c b/mi/mieq.c
 index 062dede..5016d73 100644
 --- a/mi/mieq.c
 +++ b/mi/mieq.c
 @@ -122,7 +122,8 @@ mieqResizeEvents(int min_size)
  void
  mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
  {
 -unsigned int   oldtail = miEventQueue.tail, newtail;
 +unsigned int   oldtail = miEventQueue.tail;
 +unsigned int   newtail = oldtail;
  EventListPtr   evt;
  intisMotion = 0;
  intevlen;
 @@ -184,7 +185,6 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
  return;
  }
  stuck = 0;
 -miEventQueue.tail = newtail;
  }
 
  evlen = sizeof(xEvent);
 @@ -218,6 +218,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
  miEventQueue.events[oldtail].pDev = pDev;
 
  miEventQueue.lastMotion = isMotion;
 +miEventQueue.tail = newtail;
  }

Anyway this patch is not good enough. newtail is also deferenced (line 
173) before his first usage, making the first hunk not utilized.


Thanks,

-- 
Tiago Vignatti
C3SL - Centro de Computação Científica e Software Livre
www.c3sl.ufpr.br
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg


Re: [PATCH 2/4] X event queue mutex

2008-11-04 Thread Jeremy Huddleston


On Nov 3, 2008, at 22:08, Peter Hutterer wrote:

...


righty-o. hunk 2 is different, with the change you suggested. To make
the flow cleaner, I moved all the EQ and memory alloc stuff together  
and the

copies into local variables below it.


Almost... you need to move the pop down 4 lines.  ie this:

bad
miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

+dev = e-pDev;
+master  = (!dev-isMaster  dev-u.master) ? dev-u.master :  
NULL;

+type= e-events-event-u.u.type;
+screen  = e-pScreen;
+
/bad

should be this:
good
+dev = e-pDev;
+master  = (!dev-isMaster  dev-u.master) ? dev-u.master :  
NULL;

+type= e-events-event-u.u.type;
+screen  = e-pScreen;
+
miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
/good

After you increment miEventQueue.head, you can't read from e. ... so  
you could also do this if you wanted to be anal about popping quickly:


good
+dev = e-pDev;
+screen  = e-pScreen;
+
miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

+type= event-u.u.type;
+master  = (!dev-isMaster  dev-u.master) ? dev-u.master :  
NULL;

/good

--Jeremy



smime.p7s
Description: S/MIME cryptographic signature
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Re: [PATCH 2/4] X event queue mutex

2008-11-04 Thread Peter Hutterer
On Tue, Nov 04, 2008 at 09:34:23AM -0800, Jeremy Huddleston wrote:
 good
 +dev = e-pDev;
 +screen  = e-pScreen;
 +
 miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

 +type= event-u.u.type;
 +master  = (!dev-isMaster  dev-u.master) ? dev-u.master :  
 NULL;

From 7693b94cd08030b9668130410104f432162f2859 Mon Sep 17 00:00:00 2001
From: Peter Hutterer [EMAIL PROTECTED]
Date: Tue, 4 Nov 2008 15:27:30 +1030
Subject: [PATCH] mi: clean up mieqProcessInputEvents, copy all events before 
processing.

Copy the EventRec's information into local variables before processing them,
this should make it safer for upcoming threading and also makes it easier to
read.

Simplify the event allocation code from the abyss it was before.

This also fixes a potential bug where a custom handler could scramble the
event before the same -now scrambled- event was then passed through the
master's custom event handler.

Signed-off-by: Peter Hutterer [EMAIL PROTECTED]
---
 mi/mieq.c |   98 
 1 files changed, 46 insertions(+), 52 deletions(-)

diff --git a/mi/mieq.c b/mi/mieq.c
index 986e3a1..52bb841 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -307,8 +307,12 @@ mieqProcessInputEvents(void)
 mieqHandler handler;
 EventRec *e = NULL;
 int x = 0, y = 0;
-xEvent* event,
-*master_event = NULL;
+int type, nevents, evlen, i;
+ScreenPtr screen;
+xEvent *event,
+   *master_event = NULL;
+DeviceIntPtr dev = NULL,
+ master = NULL;
 
 while (miEventQueue.head != miEventQueue.tail) {
 if (screenIsSaved == SCREEN_SAVER_ON)
@@ -322,79 +326,69 @@ mieqProcessInputEvents(void)
 #endif
 
 e = miEventQueue.events[miEventQueue.head];
+
+/* GenericEvents always have nevents == 1 */
+nevents = e-nevents;
+evlen   = (nevents  1) ? sizeof(xEvent) : e-events-evlen;
+event   = xcalloc(nevents, evlen);
+
+if (!event)
+FatalError([mi] No memory left for event processing.\n);
+
+for (i = 0; i  nevents; i++)
+memcpy(event[i], e-events[i].event, evlen);
+
+
+dev = e-pDev;
+screen  = e-pScreen;
+
 miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
 
+type= event-u.u.type;
+master  = (!dev-isMaster  dev-u.master) ? dev-u.master : NULL;
+
 /* Custom event handler */
-handler = miEventQueue.handlers[e-events-event-u.u.type];
+handler = miEventQueue.handlers[type];
 
-if (e-pScreen != DequeueScreen(e-pDev)  !handler) {
+if (screen != DequeueScreen(dev)  !handler) {
 /* Assumption - screen switching can only occur on motion events. 
*/
-DequeueScreen(e-pDev) = e-pScreen;
-x = e-events[0].event-u.keyButtonPointer.rootX;
-y = e-events[0].event-u.keyButtonPointer.rootY;
-NewCurrentScreen (e-pDev, DequeueScreen(e-pDev), x, y);
+DequeueScreen(dev) = screen;
+x = event-u.keyButtonPointer.rootX;
+y = event-u.keyButtonPointer.rootY;
+NewCurrentScreen (dev, DequeueScreen(dev), x, y);
 }
 else {
-/* FIXME: Bad hack. The only event where we actually get multiple
- * events at once is a DeviceMotionNotify followed by
- * DeviceValuators. For now it's safe enough to just take the
- * event directly or copy the bunch of events and pass in the
- * copy. Eventually the interface for the processInputProc needs
- * to be changed. (whot)
- */
-if (e-nevents  1)
-{
-int i;
-event = xcalloc(e-nevents, sizeof(xEvent));
-if (!event)
-FatalError([mi] No memory left for event processing.\n);
-for (i = 0; i  e-nevents; i++)
-{
-memcpy(event[i], e-events[i].event, sizeof(xEvent));
-}
-} else
-event = e-events-event;
-if (!e-pDev-isMaster  e-pDev-u.master)
-{
-CopyGetMasterEvent(e-pDev-u.master, event,
-   master_event, e-nevents);
-} else
+if (master)
+CopyGetMasterEvent(master, event,
+   master_event, nevents);
+else
 master_event = NULL;
 
 /* If someone's registered a custom event handler, let them
  * steal it. */
 if (handler)
 {
-handler(DequeueScreen(e-pDev)-myNum, e-events-event,
-e-pDev, e-nevents);
-if (!e-pDev-isMaster  e-pDev-u.master)
-{
-handler(DequeueScreen(e-pDev-u.master)-myNum,
-e-events-event, 

Re: [PATCH 2/4] X event queue mutex

2008-11-04 Thread Jeremy Huddleston
Looks good!  A recent bug report has surfaced for us since I got rid  
of the locking in mieqProcessInputEvents.  We need to update  
miEventQueue.tail only after the data has actually been pushed into  
the tail.  This should take care of that problem on master, but I  
haven't tested it:


diff --git a/mi/mieq.c b/mi/mieq.c
index 062dede..5016d73 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -122,7 +122,8 @@ mieqResizeEvents(int min_size)
 void
 mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 {
-unsigned int   oldtail = miEventQueue.tail, newtail;
+unsigned int   oldtail = miEventQueue.tail;
+unsigned int   newtail = oldtail;
 EventListPtr   evt;
 intisMotion = 0;
 intevlen;
@@ -184,7 +185,6 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
return;
 }
stuck = 0;
-   miEventQueue.tail = newtail;
 }

 evlen = sizeof(xEvent);
@@ -218,6 +218,7 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 miEventQueue.events[oldtail].pDev = pDev;

 miEventQueue.lastMotion = isMotion;
+miEventQueue.tail = newtail;
 }

 void



On Nov 4, 2008, at 14:18, Peter Hutterer wrote:


On Tue, Nov 04, 2008 at 09:34:23AM -0800, Jeremy Huddleston wrote:

good
+dev = e-pDev;
+screen  = e-pScreen;
+
   miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

+type= event-u.u.type;
+master  = (!dev-isMaster  dev-u.master) ? dev- 
u.master :

NULL;


From 7693b94cd08030b9668130410104f432162f2859 Mon Sep 17 00:00:00 2001
From: Peter Hutterer [EMAIL PROTECTED]
Date: Tue, 4 Nov 2008 15:27:30 +1030
Subject: [PATCH] mi: clean up mieqProcessInputEvents, copy all  
events before processing.


Copy the EventRec's information into local variables before  
processing them,
this should make it safer for upcoming threading and also makes it  
easier to

read.

Simplify the event allocation code from the abyss it was before.

This also fixes a potential bug where a custom handler could  
scramble the
event before the same -now scrambled- event was then passed through  
the

master's custom event handler.

Signed-off-by: Peter Hutterer [EMAIL PROTECTED]
---
mi/mieq.c |   98 +++ 
+

1 files changed, 46 insertions(+), 52 deletions(-)

diff --git a/mi/mieq.c b/mi/mieq.c
index 986e3a1..52bb841 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -307,8 +307,12 @@ mieqProcessInputEvents(void)
mieqHandler handler;
EventRec *e = NULL;
int x = 0, y = 0;
-xEvent* event,
-*master_event = NULL;
+int type, nevents, evlen, i;
+ScreenPtr screen;
+xEvent *event,
+   *master_event = NULL;
+DeviceIntPtr dev = NULL,
+ master = NULL;

while (miEventQueue.head != miEventQueue.tail) {
if (screenIsSaved == SCREEN_SAVER_ON)
@@ -322,79 +326,69 @@ mieqProcessInputEvents(void)
#endif

e = miEventQueue.events[miEventQueue.head];
+
+/* GenericEvents always have nevents == 1 */
+nevents = e-nevents;
+evlen   = (nevents  1) ? sizeof(xEvent) : e-events-evlen;
+event   = xcalloc(nevents, evlen);
+
+if (!event)
+FatalError([mi] No memory left for event processing. 
\n);

+
+for (i = 0; i  nevents; i++)
+memcpy(event[i], e-events[i].event, evlen);
+
+
+dev = e-pDev;
+screen  = e-pScreen;
+
miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

+type= event-u.u.type;
+master  = (!dev-isMaster  dev-u.master) ? dev- 
u.master : NULL;

+
/* Custom event handler */
-handler = miEventQueue.handlers[e-events-event-u.u.type];
+handler = miEventQueue.handlers[type];

-if (e-pScreen != DequeueScreen(e-pDev)  !handler) {
+if (screen != DequeueScreen(dev)  !handler) {
/* Assumption - screen switching can only occur on  
motion events. */

-DequeueScreen(e-pDev) = e-pScreen;
-x = e-events[0].event-u.keyButtonPointer.rootX;
-y = e-events[0].event-u.keyButtonPointer.rootY;
-NewCurrentScreen (e-pDev, DequeueScreen(e-pDev), x, y);
+DequeueScreen(dev) = screen;
+x = event-u.keyButtonPointer.rootX;
+y = event-u.keyButtonPointer.rootY;
+NewCurrentScreen (dev, DequeueScreen(dev), x, y);
}
else {
-/* FIXME: Bad hack. The only event where we actually  
get multiple

- * events at once is a DeviceMotionNotify followed by
- * DeviceValuators. For now it's safe enough to just  
take the
- * event directly or copy the bunch of events and pass  
in the
- * copy. Eventually the interface for the  
processInputProc needs

- * to be changed. (whot)
- */
-if (e-nevents  1)
-{
-int i;
-event = 

Re: [PATCH 2/4] X event queue mutex

2008-11-03 Thread Peter Hutterer
Sorry for the late reply, I was tied up and missed the mail.

On Thu, Oct 23, 2008 at 02:47:30PM -0700, Jeremy Huddleston wrote:
 And here's a stab at setting up mieqProcessInputEvents in master to be  
 more friendly towards this locking.  master doesn't work for us on OSX, 
 so I can't really verify that it works... I may have missed an e- to e. 
 or e-events[i]-event to event[i] somewhere...

 This also fixes what I think is a bug in the custom event handler...  
 right now we have:

 handler(DequeueScreen(e-pDev)-myNum, e-events-event,
 e-pDev, e-nevents);
 if (!e-pDev-isMaster  e-pDev-u.master) {
 handler(DequeueScreen(e-pDev-u.master)-myNum,
 e-events-event, e-pDev-u.master, e-nevents);
 }

 But that fails if e-nevents  1 ... granted all current custom event  
 handlers have nevents=1, but it's worth noting.

with the move of the handler procesing (dac9e918) this should now be.

handler(.., event, ...);
if (!e-pDev-isMaster  ...)
  handler(..., master_event, ...)

otherwise we're not protected against event manipulation in the handler.

 Also, why do we call the handler twice here?

Only one event is in the queue, but we need to process it twice, once as
coming from the slave device, once as coming from the master device. These two
are independent.


-e = miEventQueue.events[miEventQueue.head];
+memcpy(e, miEventQueue.events[miEventQueue.head],  sizeof(EventRec));

if we're not using the EventRec as such anyway, it might just be better to
extract the things we need and improve readability.

+event = xcalloc(e.nevents, sizeof(xEvent));

that doesn't work. GenericEvents may be larger than xEvent, hence the slightly
weird copying code. What you are doing here corrupts memory after the first
device switch. How about this one here, quick test shows it works:

From b783944ac784c42ba84b3dfe77d60107b9581a30 Mon Sep 17 00:00:00 2001
From: Peter Hutterer [EMAIL PROTECTED]
Date: Tue, 4 Nov 2008 15:27:30 +1030
Subject: [PATCH] mi: clean up mieqProcessInputEvents, copy all events before 
processing.

Copy the EventRec's information into local variables before processing them,
this should make it safer for upcoming threading and also makes it easier to
read.

Simplify the event allocation code from the abyss it was before.

This also fixes a potential bug where a custom handler could scramble the
event before the same -now scrambled- event was then passed through the
master's custom event handler.
---
 mi/mieq.c |   95 +++-
 1 files changed, 43 insertions(+), 52 deletions(-)

diff --git a/mi/mieq.c b/mi/mieq.c
index 986e3a1..ec11e00 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -307,8 +307,12 @@ mieqProcessInputEvents(void)
 mieqHandler handler;
 EventRec *e = NULL;
 int x = 0, y = 0;
-xEvent* event,
-*master_event = NULL;
+int type, nevents, evlen, i;
+ScreenPtr screen;
+xEvent *event,
+   *master_event = NULL;
+DeviceIntPtr dev = NULL,
+ master = NULL;
 
 while (miEventQueue.head != miEventQueue.tail) {
 if (screenIsSaved == SCREEN_SAVER_ON)
@@ -324,77 +328,64 @@ mieqProcessInputEvents(void)
 e = miEventQueue.events[miEventQueue.head];
 miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
 
+dev = e-pDev;
+master  = (!dev-isMaster  dev-u.master) ? dev-u.master : NULL;
+type= e-events-event-u.u.type;
+nevents = e-nevents;
+screen  = e-pScreen;
+
+/* GenericEvents always have nevents == 1 */
+evlen = (nevents  1) ? sizeof(xEvent) : e-events-evlen;
+event = xcalloc(nevents, evlen);
+
+if (!event)
+FatalError([mi] No memory left for event processing.\n);
+
+for (i = 0; i  nevents; i++)
+memcpy(event[i], e-events[i].event, evlen);
+
 /* Custom event handler */
-handler = miEventQueue.handlers[e-events-event-u.u.type];
+handler = miEventQueue.handlers[type];
 
-if (e-pScreen != DequeueScreen(e-pDev)  !handler) {
+if (screen != DequeueScreen(dev)  !handler) {
 /* Assumption - screen switching can only occur on motion events. 
*/
-DequeueScreen(e-pDev) = e-pScreen;
-x = e-events[0].event-u.keyButtonPointer.rootX;
-y = e-events[0].event-u.keyButtonPointer.rootY;
-NewCurrentScreen (e-pDev, DequeueScreen(e-pDev), x, y);
+DequeueScreen(dev) = screen;
+x = event-u.keyButtonPointer.rootX;
+y = event-u.keyButtonPointer.rootY;
+NewCurrentScreen (dev, DequeueScreen(dev), x, y);
 }
 else {
-/* FIXME: Bad hack. The only event where we actually get multiple
- * events at once is a DeviceMotionNotify followed by
- * DeviceValuators. For now it's safe enough to just take the
- * event directly or copy the bunch of 

Re: [PATCH 2/4] X event queue mutex

2008-11-03 Thread Peter Hutterer
On Mon, Nov 03, 2008 at 09:41:48PM -0800, Jeremy Huddleston wrote:
 That looks much better (and is much more readable), but it's still open 
 to data-thrashing when the queue is full.  Move this:

 miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

 after this:

 +for (i = 0; i  nevents; i++)
 +memcpy(event[i], e-events[i].event, evlen);

 e is the head, and it becomes writeable by the other thread after we  
 do the pop... so we want to only pop it after we're done copying.

 With that change, I think it's golden =)

righty-o. hunk 2 is different, with the change you suggested. To make
the flow cleaner, I moved all the EQ and memory alloc stuff together and the
copies into local variables below it.

From 218f4664a032a8096d576ab8a43f33226007b6a4 Mon Sep 17 00:00:00 2001
From: Peter Hutterer [EMAIL PROTECTED]
Date: Tue, 4 Nov 2008 15:27:30 +1030
Subject: [PATCH] mi: clean up mieqProcessInputEvents, copy all events before 
processing.

Copy the EventRec's information into local variables before processing them,
this should make it safer for upcoming threading and also makes it easier to
read.

Simplify the event allocation code from the abyss it was before.

This also fixes a potential bug where a custom handler could scramble the
event before the same -now scrambled- event was then passed through the
master's custom event handler.
---
 mi/mieq.c |   96 -
 1 files changed, 44 insertions(+), 52 deletions(-)

diff --git a/mi/mieq.c b/mi/mieq.c
index 986e3a1..33c2936 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -307,8 +307,12 @@ mieqProcessInputEvents(void)
 mieqHandler handler;
 EventRec *e = NULL;
 int x = 0, y = 0;
-xEvent* event,
-*master_event = NULL;
+int type, nevents, evlen, i;
+ScreenPtr screen;
+xEvent *event,
+   *master_event = NULL;
+DeviceIntPtr dev = NULL,
+ master = NULL;
 
 while (miEventQueue.head != miEventQueue.tail) {
 if (screenIsSaved == SCREEN_SAVER_ON)
@@ -322,79 +326,67 @@ mieqProcessInputEvents(void)
 #endif
 
 e = miEventQueue.events[miEventQueue.head];
+
+/* GenericEvents always have nevents == 1 */
+nevents = e-nevents;
+evlen   = (nevents  1) ? sizeof(xEvent) : e-events-evlen;
+event   = xcalloc(nevents, evlen);
+
+if (!event)
+FatalError([mi] No memory left for event processing.\n);
+
+for (i = 0; i  nevents; i++)
+memcpy(event[i], e-events[i].event, evlen);
+
 miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
 
+dev = e-pDev;
+master  = (!dev-isMaster  dev-u.master) ? dev-u.master : NULL;
+type= e-events-event-u.u.type;
+screen  = e-pScreen;
+
 /* Custom event handler */
-handler = miEventQueue.handlers[e-events-event-u.u.type];
+handler = miEventQueue.handlers[type];
 
-if (e-pScreen != DequeueScreen(e-pDev)  !handler) {
+if (screen != DequeueScreen(dev)  !handler) {
 /* Assumption - screen switching can only occur on motion events. 
*/
-DequeueScreen(e-pDev) = e-pScreen;
-x = e-events[0].event-u.keyButtonPointer.rootX;
-y = e-events[0].event-u.keyButtonPointer.rootY;
-NewCurrentScreen (e-pDev, DequeueScreen(e-pDev), x, y);
+DequeueScreen(dev) = screen;
+x = event-u.keyButtonPointer.rootX;
+y = event-u.keyButtonPointer.rootY;
+NewCurrentScreen (dev, DequeueScreen(dev), x, y);
 }
 else {
-/* FIXME: Bad hack. The only event where we actually get multiple
- * events at once is a DeviceMotionNotify followed by
- * DeviceValuators. For now it's safe enough to just take the
- * event directly or copy the bunch of events and pass in the
- * copy. Eventually the interface for the processInputProc needs
- * to be changed. (whot)
- */
-if (e-nevents  1)
-{
-int i;
-event = xcalloc(e-nevents, sizeof(xEvent));
-if (!event)
-FatalError([mi] No memory left for event processing.\n);
-for (i = 0; i  e-nevents; i++)
-{
-memcpy(event[i], e-events[i].event, sizeof(xEvent));
-}
-} else
-event = e-events-event;
-if (!e-pDev-isMaster  e-pDev-u.master)
-{
-CopyGetMasterEvent(e-pDev-u.master, event,
-   master_event, e-nevents);
-} else
+if (master)
+CopyGetMasterEvent(master, event,
+   master_event, nevents);
+else
 master_event = NULL;
 
 /* If someone's registered a custom event handler, let 

Re: [PATCH 2/4] X event queue mutex

2008-11-03 Thread Jeremy Huddleston
That looks much better (and is much more readable), but it's still  
open to data-thrashing when the queue is full.  Move this:


miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

after this:

+for (i = 0; i  nevents; i++)
+memcpy(event[i], e-events[i].event, evlen);

e is the head, and it becomes writeable by the other thread after we  
do the pop... so we want to only pop it after we're done copying.


With that change, I think it's golden =)

--Jeremy

On Nov 3, 2008, at 21:06, Peter Hutterer wrote:


Sorry for the late reply, I was tied up and missed the mail.

On Thu, Oct 23, 2008 at 02:47:30PM -0700, Jeremy Huddleston wrote:
And here's a stab at setting up mieqProcessInputEvents in master to  
be
more friendly towards this locking.  master doesn't work for us on  
OSX,
so I can't really verify that it works... I may have missed an e-  
to e.

or e-events[i]-event to event[i] somewhere...

This also fixes what I think is a bug in the custom event handler...
right now we have:

handler(DequeueScreen(e-pDev)-myNum, e-events-event,
   e-pDev, e-nevents);
if (!e-pDev-isMaster  e-pDev-u.master) {
   handler(DequeueScreen(e-pDev-u.master)-myNum,
   e-events-event, e-pDev-u.master, e-nevents);
}

But that fails if e-nevents  1 ... granted all current custom event
handlers have nevents=1, but it's worth noting.


with the move of the handler procesing (dac9e918) this should now be.

handler(.., event, ...);
if (!e-pDev-isMaster  ...)
 handler(..., master_event, ...)

otherwise we're not protected against event manipulation in the  
handler.



Also, why do we call the handler twice here?


Only one event is in the queue, but we need to process it twice,  
once as
coming from the slave device, once as coming from the master device.  
These two

are independent.


-e = miEventQueue.events[miEventQueue.head];
+memcpy(e, miEventQueue.events[miEventQueue.head],   
sizeof(EventRec));


if we're not using the EventRec as such anyway, it might just be  
better to

extract the things we need and improve readability.

+event = xcalloc(e.nevents, sizeof(xEvent));

that doesn't work. GenericEvents may be larger than xEvent, hence  
the slightly
weird copying code. What you are doing here corrupts memory after  
the first

device switch. How about this one here, quick test shows it works:

From b783944ac784c42ba84b3dfe77d60107b9581a30 Mon Sep 17 00:00:00 2001
From: Peter Hutterer [EMAIL PROTECTED]
Date: Tue, 4 Nov 2008 15:27:30 +1030
Subject: [PATCH] mi: clean up mieqProcessInputEvents, copy all  
events before processing.


Copy the EventRec's information into local variables before  
processing them,
this should make it safer for upcoming threading and also makes it  
easier to

read.

Simplify the event allocation code from the abyss it was before.

This also fixes a potential bug where a custom handler could  
scramble the
event before the same -now scrambled- event was then passed through  
the

master's custom event handler.
---
mi/mieq.c |   95 ++ 
+-

1 files changed, 43 insertions(+), 52 deletions(-)

diff --git a/mi/mieq.c b/mi/mieq.c
index 986e3a1..ec11e00 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -307,8 +307,12 @@ mieqProcessInputEvents(void)
mieqHandler handler;
EventRec *e = NULL;
int x = 0, y = 0;
-xEvent* event,
-*master_event = NULL;
+int type, nevents, evlen, i;
+ScreenPtr screen;
+xEvent *event,
+   *master_event = NULL;
+DeviceIntPtr dev = NULL,
+ master = NULL;

while (miEventQueue.head != miEventQueue.tail) {
if (screenIsSaved == SCREEN_SAVER_ON)
@@ -324,77 +328,64 @@ mieqProcessInputEvents(void)
e = miEventQueue.events[miEventQueue.head];
miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

+dev = e-pDev;
+master  = (!dev-isMaster  dev-u.master) ? dev- 
u.master : NULL;

+type= e-events-event-u.u.type;
+nevents = e-nevents;
+screen  = e-pScreen;
+
+/* GenericEvents always have nevents == 1 */
+evlen = (nevents  1) ? sizeof(xEvent) : e-events-evlen;
+event = xcalloc(nevents, evlen);
+
+if (!event)
+FatalError([mi] No memory left for event processing. 
\n);

+
+for (i = 0; i  nevents; i++)
+memcpy(event[i], e-events[i].event, evlen);
+
/* Custom event handler */
-handler = miEventQueue.handlers[e-events-event-u.u.type];
+handler = miEventQueue.handlers[type];

-if (e-pScreen != DequeueScreen(e-pDev)  !handler) {
+if (screen != DequeueScreen(dev)  !handler) {
/* Assumption - screen switching can only occur on  
motion events. */

-DequeueScreen(e-pDev) = e-pScreen;
-x = e-events[0].event-u.keyButtonPointer.rootX;
-y = e-events[0].event-u.keyButtonPointer.rootY;
-

Re: [PATCH 2/4] X event queue mutex

2008-10-23 Thread Jeremy Huddleston

Hey Tiago,

I hope things are going well for you.  I've recently hit an issue  
using locks in miEq.  We're doing it the same way in mieq.c as your  
proposal (patch 2/4) and this causes us to hit a deadlock when the  
enqueueing thread is waiting for the lock to push an event and the  
dequeuing thread (the server thread) is processing an event that  
requires a message to be sent to the enqueueing thread.


I am going to try solving this by making the lock a bit more  
conservative in mieqProcessInputEvents.  Our current implementation  
(we're still on 1.4) passes the event to the handler as a pointer to  
the event within the queue.  In 1.5, mieqProcessInputEvents now copies  
the nevents first... so we might be able to release that a bit sooner...


The thing is that we have:

e = miEventQueue.events[miEventQueue.head];

Then e-events is copied, but 'e' itself is still directly referenced  
throughout mieqProcessInputEvents.  Could we actually just copy all of  
miEventQueue.events[miEventQueue.head] to a local copy and release the  
lock after that? I see us using:


e-pDev
e-nevents
e-events (already copied in 1.5.x and later if nevents  1)

--Jeremy

Begin forwarded message:


From: Jeremy Huddleston [EMAIL PROTECTED]
Date: October 19, 2008 12:59:16 PDT
To: Kevin Van Vechten [EMAIL PROTECTED], Jordan Hubbard [EMAIL PROTECTED]
Cc: George Peter Staplin [EMAIL PROTECTED]
Subject: mach_msg async? thread communication question

So... I've made some progress with fullscreen...

It now renders the weaved background and only crashes if there are  
windows other than the root window... but if you just want to stare  
at a black and white X11 weave background, we're there!


Aside from this crash, I noticed a thread communication deadlock  
issue (see the stack traces below):


Thread 2's mieqProcessInputEvents and mieqEnqueue lock the input  
event queue... but some of the handlers for mieqProcessInputEvents  
actually need to msg the Appkit thread which appears to cause the  
deadlock.


Is there a way to allow mach_msg to be async?  In these cases, we  
don't care about return values.


Or do I need to do something clever (read: annoying) to address this  
issue?


Call graph:
   4783 Thread_2503
 4783 start
   4783 main
 4783 mach_msg_server
   4783 mach_startup_server
 4783 _Xstart_x11_server
   4783 do_start_x11_server
 4783 server_main
   4783 X11ControllerMain
 4783 X11ApplicationMain
   4783 -[NSApplication run]
 4783 -[X11Application sendEvent:]
   4783 -[NSApplication sendEvent:]
 4783 -[NSApplication  
_handleKeyEquivalent:]

   4783 -[NSMenu performKeyEquivalent:]
 4783 -[NSCarbonMenuImpl  
performActionWithHighlightingForItemAtIndex:]
   4783 -[NSMenu  
performActionForItemAtIndex:]
 4783 -[NSApplication  
sendAction:to:from:]
   4783 -[X11Controller  
toggle_fullscreen:]

 4783 DarwinSendDDXEvent
   4783 mieqEnqueue
 4768 pthread_mutex_lock
   4768  
semaphore_wait_trap
 4768  
semaphore_wait_trap

 15 0x
   15 _sigtramp
 15 _sigtramp
   4783 Thread_2703
 4783 thread_start
   4783 _pthread_start
 4783 server_thread
   4783 dix_main
 4783 Dispatch
   4783 ProcessInputEvents
 4783 mieqProcessInputEvents
   4783 DarwinEventHandler
 4783 QuartzHide
   4783 QuartzSetFullscreen
 4783 X11ApplicationShowHideMenubar
   4783 message_kit_thread
 4783 mach_msg
   4783 mach_msg_trap
 4783 mach_msg_trap






smime.p7s
Description: S/MIME cryptographic signature
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Re: [PATCH 2/4] X event queue mutex

2008-10-23 Thread Jeremy Huddleston
And here's a stab at setting up mieqProcessInputEvents in master to be  
more friendly towards this locking.  master doesn't work for us on  
OSX, so I can't really verify that it works... I may have missed an e- 
 to e. or e-events[i]-event to event[i] somewhere...


This also fixes what I think is a bug in the custom event handler...  
right now we have:


handler(DequeueScreen(e-pDev)-myNum, e-events-event,
e-pDev, e-nevents);
if (!e-pDev-isMaster  e-pDev-u.master) {
handler(DequeueScreen(e-pDev-u.master)-myNum,
e-events-event, e-pDev-u.master, e-nevents);
}

But that fails if e-nevents  1 ... granted all current custom event  
handlers have nevents=1, but it's worth noting.


Also, why do we call the handler twice here?

--Jeremy

diff --git a/mi/mieq.c b/mi/mieq.c
index 062dede..3e1d2f8 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -305,8 +305,9 @@ void
 mieqProcessInputEvents(void)
 {
 mieqHandler handler;
-EventRec *e = NULL;
+EventRec e;
 int x = 0, y = 0;
+int i;
 xEvent* event,
 *master_event = NULL;

@@ -321,43 +322,44 @@ mieqProcessInputEvents(void)
 DPMSSet(serverClient, DPMSModeOn);
 #endif

-e = miEventQueue.events[miEventQueue.head];
+memcpy(e, miEventQueue.events[miEventQueue.head],  
sizeof(EventRec));

 miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;
+event = xcalloc(e.nevents, sizeof(xEvent));
+
+/* FIXME: Bad hack. The only event where we actually get  
multiple

+ * events at once is a DeviceMotionNotify followed by
+ * DeviceValuators. For now it's safe enough to just take the
+ * event directly or copy the bunch of events and pass in the
+ * copy. Eventually the interface for the processInputProc  
needs

+ * to be changed. (whot)
+ */
+
+if (!event)
+FatalError([mi] No memory left for event processing.\n);
+for (i = 0; i  e.nevents; i++) {
+memcpy(event[i], e.events[i].event, sizeof(xEvent));
+}
+
+/* Just using event array, null this out now since we don't  
want to
+ * rely on it (another thread can change it during an enqueue  
and we

+ * just copied all we care about)
+ */
+e.events = NULL;

 /* Custom event handler */
-handler = miEventQueue.handlers[e-events-event-u.u.type];
+handler = miEventQueue.handlers[event[0].u.u.type];

-if (e-pScreen != DequeueScreen(e-pDev)  !handler) {
+if (e.pScreen != DequeueScreen(e.pDev)  !handler) {
 /* Assumption - screen switching can only occur on  
motion events. */

-DequeueScreen(e-pDev) = e-pScreen;
-x = e-events[0].event-u.keyButtonPointer.rootX;
-y = e-events[0].event-u.keyButtonPointer.rootY;
-NewCurrentScreen (e-pDev, DequeueScreen(e-pDev), x, y);
-}
-else {
-/* FIXME: Bad hack. The only event where we actually get  
multiple

- * events at once is a DeviceMotionNotify followed by
- * DeviceValuators. For now it's safe enough to just take  
the
- * event directly or copy the bunch of events and pass in  
the
- * copy. Eventually the interface for the  
processInputProc needs

- * to be changed. (whot)
- */
-if (e-nevents  1)
-{
-int i;
-event = xcalloc(e-nevents, sizeof(xEvent));
-if (!event)
-FatalError([mi] No memory left for event  
processing.\n);

-for (i = 0; i  e-nevents; i++)
-{
-memcpy(event[i], e-events[i].event,  
sizeof(xEvent));

-}
-} else
-event = e-events-event;
-if (!e-pDev-isMaster  e-pDev-u.master)
+DequeueScreen(e.pDev) = e.pScreen;
+x = event[0].u.keyButtonPointer.rootX;
+y = event[0].u.keyButtonPointer.rootY;
+NewCurrentScreen (e.pDev, DequeueScreen(e.pDev), x, y);
+} else {
+if (!e.pDev-isMaster  e.pDev-u.master)
 {
-CopyGetMasterEvent(e-pDev-u.master, event,
-   master_event, e-nevents);
+CopyGetMasterEvent(e.pDev-u.master, event,
+   master_event, e.nevents);
 } else
 master_event = NULL;

@@ -365,35 +367,33 @@ mieqProcessInputEvents(void)
  * steal it. */
 if (handler)
 {
-handler(DequeueScreen(e-pDev)-myNum, e-events- 
event,

-e-pDev, e-nevents);
-if (!e-pDev-isMaster  e-pDev-u.master)
+handler(DequeueScreen(e.pDev)-myNum, event,
+e.pDev, e.nevents);
+if (!e.pDev-isMaster  e.pDev-u.master)
 {
-

Re: [PATCH 2/4] X event queue mutex

2008-10-23 Thread Jeremy Huddleston


On Oct 23, 2008, at 16:05, Tiago Vignatti wrote:


Hey Jeremy, I'm going well. Thanks my friend.

Jeremy Huddleston escreveu:
I hope things are going well for you.  I've recently hit an issue  
using locks in miEq.  We're doing it the same way in mieq.c as your  
proposal (patch 2/4) and this causes us to hit a deadlock when the  
enqueueing thread is waiting for the lock to push an event and the  
dequeuing thread (the server thread) is processing an event that  
requires a message to be sent to the enqueueing thread.


I posted another version of that patch that doesn't requires a lock  
in mieqProcessInputEvents().


Hmm... I must've missed that version... I thought I was looking at the  
Oct 1 one, but maybe I misclicked... sorry


We just need to guarantee order of events enqueued (to protect  
writes to the tail pointer in mieqEnqueue) and don't need to  
serialize dequeuing events. So no locks in the server thread is  
needed.
(well, this is the theory of the X server with Xorg DDX and the  
input thread craziness. Maybe your problem is a bit different from  
mine)


I think by not locking, we open ourselves up to clobber because we  
reference the event on the queue after we pop the event off the event  
queue:


server thread:
e = miEventQueue.events[miEventQueue.head];
miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE;

-- context switch to input thread with a 1-open-slot event queue  
(miEventQueue.head = miEventQueue.head - 1) --
miEventQueue.events[miEventQueue.tail] gets set, but this is what 'e'  
is.


-- context switch to server thread --
e was just clobbered by the input thread

-

I think you're right, actually, that we don't need to actually lock  
here.  We just need to copy the data locally then pop the queue.  If  
we keep the data in the queue and point to it, then we need to either  
lock (bad IMO), pop on return (possibly a good solution), or cache it  
locally (what I did in the patch I sent a few hours ago).






smime.p7s
Description: S/MIME cryptographic signature
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Re: [PATCH 2/4] X event queue mutex

2008-10-06 Thread Keith Packard
On Tue, 2008-10-07 at 00:46 -0300, Tiago Vignatti wrote:

 BTW, all mieqEnqueue() calls isn't needed to be wrapped by 
 OsBlockSignals() and OsReleaseSignals()? This is not what is happening 
 in our code.

OsBlockSignals is only required when queuing events other than from the
SIGIO handler as signals are blocked while that handler is running.

-- 
[EMAIL PROTECTED]


signature.asc
Description: This is a digitally signed message part
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Re: [PATCH 2/4] X event queue mutex

2008-10-06 Thread Tiago Vignatti
Simon Thum escreveu:
 Keith Packard wrote:
 Why does inserting events do anything but pull events from the kernel,
 insert them to the queue and update the sprite location on the screen?
 All event processing should happen in the main server thread; the only
 latency we're looking to reduce is the mouse-sprite update.
 It's really not much: Middle button emu, translation/acceleration, ...
 The point being their guts are exposed via input properties. Most cases
 are trivial, which reads 'fairly safe given properly aligned writes are
 atomic'. For the rest, there should be provisions (like suppressing
 input processing) or a clear statement against complicated stuff in
 props. At least, that's my opinion.

(Just to note: my last patch totally ignores the eventual races issues 
with input thread and input device properties)


Sh*t, the things are starting to get confused again. Keith was right 
saying that the IT needs only to worry with sprite updates, and we're 
_not_ doing this right now. The input thread covers all the input event 
generation stage and more other bits.

A problem that I see is in GetPointerEvents() function. It's bloated and 
confusing. It generates X events and also updates the cursor on screen. 
We don't need to mix this two actions in one function. For instance, I 
did a quickly hack here calling miPointerSetPosition() directly from 
evdev driver (!) instead inside GPE and apparently all worked nice. So 
if we could only put in a separate thread the pieces that deal with 
cursor's update and not related with X events then we'd be winning -- I 
failed to not see this before  :(

On the other hand, if we're moving to the kernel the pieces of our stack 
which are close with hw interaction, then it'd be more logical to move 
also all this not-window-related stuff to the kernel (inside drm, etc) 
and forget the input thread for all eternity.

So yeah, I have to think a little more about this all. I think I still 
have a breath to start adventure again in kernel side.


Cheers,

-- 
Tiago Vignatti
C3SL - Centro de Computação Científica e Software Livre
www.c3sl.ufpr.br
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg


Re: [PATCH 2/4] X event queue mutex

2008-10-03 Thread Simon Thum
 On Fri, 2008-10-03 at 05:57 +0300, Daniel Stone wrote:
 Except if the lock is held across the entire event processing, because
 we need to queue events from event processing.
I guess that's what I meant with guaranteeing order.
 
 That makes it more important that the mutex cover precisely the values
 which will be modified in multiple threads, inserting events into the
 queue, and not pulling them out, which is done only in a single thread.
Fine so far.

But how do we touch structures which the IT uses before enqueuing
from the main thread? E.g. with input properties, you're likely to 
modify IT-relevant data. I guess that's mostly a single write so 
visibility won't hurt much anyway, but there might be more complex ops. 
This should be considered a no-go or we need means to cope with it.

A possiblity would be to lock the queue while processing prop handlers 
so the unlock guarantees visiblity, but this still doesn't provide a 
100%-fix for data races.

Opinions?

___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg


Re: [PATCH 2/4] X event queue mutex

2008-10-02 Thread Simon Thum
Keith Packard wrote:
 On Wed, 2008-10-01 at 21:39 -0300, Tiago Vignatti wrote:
 
 A mutex is needed because the X event queue is a critical region. Though
 the X event queue is re-entrant, we cannot guarantee the simultaneous
 processing by both main and input threads.
 
 The input queue is written so that each user modifies only one of the
 two pointers (head and tail). There shouldn't be any need to have a
 mutex which protects both of these values together, and doing so
 prevents mouse motion while the server is processing events.
 
 Is there something fundamentally different between threaded input and
 SIGIO- or kernel-based input that I'm missing here?
I believe tiagos words are a bit misleading: The mutex makes it possible 
to block event enqueuing, which is needed to guarantee order of events 
enqueued on the main thread. If I got it right, the intent is to 
'emulate' OsBlockSignals(), though I'm missing that bit.
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg


Re: [PATCH 2/4] X event queue mutex

2008-10-02 Thread Simon Thum
Keith Packard wrote:
 On Thu, 2008-10-02 at 18:58 -0300, Tiago Vignatti wrote:
 Keith Packard escreveu:
 The input queue is written so that each user modifies only one of the
 two pointers (head and tail). There shouldn't be any need to have a
 mutex which protects both of these values together, and doing so
 prevents mouse motion while the server is processing events.
 Yeah, but the input thread can change the tail pointer while the main
 thread is reading that, doing dirty things.
 
 That won't be a problem on any SMP machine where writes from one CPU are
 visible to the other CPU. The key is to have each thread writing only
 one of the two values, and we have that already.
It may be constructed, but IMO this means the queue size is not fully 
utilizable given head is 'old':
else {
newtail = (oldtail + 1) % QUEUE_SIZE;

if (newtail == miEventQueue.head) {
 ErrorF([mi] EQ overflowing. The server is probably stuck 
in an infinite loop.\n);
return;
 }
miEventQueue.tail = newtail;
 }
It might make sense to increase QUEUE_SIZE when threaded (I'm unaware of 
any reasoning behind the current size).

BTW, given SMP visibility, isn't it a tiny bit risky to have 3 
'independent' miEventQueue.head reads in miEnqueue?


 So, we either need to fix the users of checkForInput along with all
 users of miEventQueue, or we need to assert that we're running on a
 sensible CPU that doesn't require a mutex to make memory changes visible
 across processors, in which case we don't need any mutex at all.
At XDS, we identified 2 scenarios:
  a) Full block of input processing (halt IT at defined state)
  b) block enqueuing on IT-side (so e.g. XTest can guarantee order)

(b) may suffice. Locking the queue in OsBlockSigs() should do it and fix 
most miEnqueue users.

Given that more input-related stuff is going to be done in input 
properties (which are processed on the main thread), (a) may be the only 
viable option in some circumstances (If I'm the only, let's forget it). 
Then we'd also need to assert visibility of writes when the IT is to 
continue. I don't know how to do that pthready however.

Processing input properties on the input thread may avoid that (a) crap 
altogether. (cc'ed peter for that). If I didn't miss something, this and 
(b) should get the job done.


___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg


Re: [PATCH 2/4] X event queue mutex

2008-10-02 Thread Keith Packard
On Fri, 2008-10-03 at 02:01 +0200, Simon Thum wrote:

 It may be constructed, but IMO this means the queue size is not fully 
 utilizable given head is 'old':

Yes, that's fairly common in queues -- you often can't use the last
entry. Not a huge deal if you make the queue big enough.

 BTW, given SMP visibility, isn't it a tiny bit risky to have 3 
 'independent' miEventQueue.head reads in miEnqueue?

Given the old 'SIGIO' based code, it didn't matter. Even now, it doesn't
really matter as in the worst case we fail to store an event when the
queue is nearly full but the server is processing events.

 (b) may suffice. Locking the queue in OsBlockSigs() should do it and fix 
 most miEnqueue users.

Or just lock the queue in mieqEnqueue itself; keeping the lock near the
code seems like a lot better plan to me.

-- 
[EMAIL PROTECTED]


signature.asc
Description: This is a digitally signed message part
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Re: [PATCH 2/4] X event queue mutex

2008-10-02 Thread Daniel Stone
On Thu, Oct 02, 2008 at 06:53:09PM -0700, Keith Packard wrote:
 On Fri, 2008-10-03 at 02:01 +0200, Simon Thum wrote:
  (b) may suffice. Locking the queue in OsBlockSigs() should do it and fix 
  most miEnqueue users.
 
 Or just lock the queue in mieqEnqueue itself; keeping the lock near the
 code seems like a lot better plan to me.

Except if the lock is held across the entire event processing, because
we need to queue events from event processing.

Cheers,
Daniel


signature.asc
Description: Digital signature
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Re: [PATCH 2/4] X event queue mutex

2008-10-02 Thread Keith Packard
On Fri, 2008-10-03 at 05:57 +0300, Daniel Stone wrote:
 On Thu, Oct 02, 2008 at 06:53:09PM -0700, Keith Packard wrote:
  On Fri, 2008-10-03 at 02:01 +0200, Simon Thum wrote:
   (b) may suffice. Locking the queue in OsBlockSigs() should do it and fix 
   most miEnqueue users.
  
  Or just lock the queue in mieqEnqueue itself; keeping the lock near the
  code seems like a lot better plan to me.
 
 Except if the lock is held across the entire event processing, because
 we need to queue events from event processing.

That makes it more important that the mutex cover precisely the values
which will be modified in multiple threads, inserting events into the
queue, and not pulling them out, which is done only in a single thread.

-- 
[EMAIL PROTECTED]


signature.asc
Description: This is a digitally signed message part
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

[PATCH 2/4] X event queue mutex

2008-10-01 Thread Tiago Vignatti


--
Tiago Vignatti
C3SL - Centro de Computação Científica e Software Livre
www.c3sl.ufpr.br
From 6e0692f6a5757b6d838d857bdb68596a5208c6e2 Mon Sep 17 00:00:00 2001
From: Tiago Vignatti [EMAIL PROTECTED]
Date: Wed, 1 Oct 2008 21:15:15 -0300
Subject: [PATCH] X event queue mutex.

A mutex is needed because the X event queue is a critical region. Though
the X event queue is re-entrant, we cannot guarantee the simultaneous
processing by both main and input threads.

Signed-off-by: Tiago Vignatti [EMAIL PROTECTED]
---
 mi/mieq.c |   55 +++
 1 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/mi/mieq.c b/mi/mieq.c
index 0a1b740..f9f9d8f 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -53,6 +53,10 @@ in this Software without prior written authorization from The Open Group.
 # include   extinit.h
 # include   exglobals.h
 
+#ifdef INPUT_THREAD
+#include   pthread.h
+#endif
+
 #ifdef DPMSExtension
 # include dpmsproc.h
 # define DPMS_SERVER
@@ -81,6 +85,13 @@ typedef struct _EventQueue {
 
 static EventQueueRec miEventQueue;
 
+#ifdef INPUT_THREAD
+/* We need mutex because the X event queue is a critical region.
+Though the X event queue is re-entrant, we cannot guarantee the
+simultaneous processing by both main and input threads. */
+pthread_mutex_t miEventQueueMutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
 Bool
 mieqInit(void)
 {
@@ -122,6 +133,9 @@ mieqResizeEvents(int min_size)
 void
 mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 {
+#ifdef INPUT_THREAD
+pthread_mutex_lock(miEventQueueMutex);
+#endif
 unsigned int   oldtail = miEventQueue.tail, newtail;
 EventListPtr   evt;
 intisMotion = 0;
@@ -146,6 +160,9 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 
 if (laste-nevents  6) {
 ErrorF([mi] mieqEnqueue: more than six valuator events; dropping.\n);
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 return;
 }
 if (oldtail == miEventQueue.head ||
@@ -157,10 +174,16 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 ((lastkbp-deviceid  DEVICE_BITS) !=
  (v-deviceid  DEVICE_BITS))) {
 ErrorF([mi] mieqEnequeue: out-of-order valuator event; dropping.\n);
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 return;
 }
 
 memcpy((laste-events[laste-nevents++].event), e, sizeof(xEvent));
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 return;
 }
 
@@ -176,6 +199,9 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 	if (newtail == miEventQueue.head) {
 ErrorF([mi] EQ overflowing. The server is probably stuck 
in an infinite loop.\n);
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 	return;
 }
 	miEventQueue.tail = newtail;
@@ -193,6 +219,9 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 if (!evt-event)
 {
 ErrorF([mi] Running out of memory. Tossing event.\n);
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 return;
 }
 }
@@ -212,24 +241,43 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e)
 miEventQueue.events[oldtail].pDev = pDev;
 
 miEventQueue.lastMotion = isMotion;
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 }
 
 void
 mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX)
 {
+#ifdef INPUT_THREAD
+pthread_mutex_lock(miEventQueueMutex);
+#endif
+
 EnqueueScreen(pDev) = pScreen;
 if (fromDIX)
 	DequeueScreen(pDev) = pScreen;
+
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 }
 
 void
 mieqSetHandler(int event, mieqHandler handler)
 {
+#ifdef INPUT_THREAD
+pthread_mutex_lock(miEventQueueMutex);
+#endif
+
 if (handler  miEventQueue.handlers[event])
 ErrorF([mi] mieq: warning: overriding existing handler %p with %p for 
event %d\n, miEventQueue.handlers[event], handler, event);
 
 miEventQueue.handlers[event] = handler;
+
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 }
 
 /**
@@ -304,6 +352,10 @@ mieqProcessInputEvents(void)
 xEvent* event,
 *master_event = NULL;
 
+#ifdef INPUT_THREAD
+pthread_mutex_lock(miEventQueueMutex);
+#endif
+
 while (miEventQueue.head != miEventQueue.tail) {
 if (screenIsSaved == SCREEN_SAVER_ON)
 dixSaveScreens (serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
@@ -390,5 +442,8 @@ mieqProcessInputEvents(void)
 miPointerUpdateSprite(e-pDev);
 }
 }
+#ifdef INPUT_THREAD
+pthread_mutex_unlock(miEventQueueMutex);
+#endif
 }
 
-- 
1.5.4.3

___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg

Re: [PATCH 2/4] X event queue mutex

2008-10-01 Thread Keith Packard
On Wed, 2008-10-01 at 21:39 -0300, Tiago Vignatti wrote:

 A mutex is needed because the X event queue is a critical region. Though
 the X event queue is re-entrant, we cannot guarantee the simultaneous
 processing by both main and input threads.

The input queue is written so that each user modifies only one of the
two pointers (head and tail). There shouldn't be any need to have a
mutex which protects both of these values together, and doing so
prevents mouse motion while the server is processing events.

Is there something fundamentally different between threaded input and
SIGIO- or kernel-based input that I'm missing here?

-- 
[EMAIL PROTECTED]


signature.asc
Description: This is a digitally signed message part
___
xorg mailing list
xorg@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/xorg