server: Add a serial event mask change counter. Take 2.
Dmitry Timoshkov
dmitry at baikal.ru
Mon Sep 9 21:29:57 CDT 2013
This allows to detect a serial event mask change even if the new mask
is equal to an old one.
---
dlls/kernel32/tests/comm.c | 6 ++----
dlls/ntdll/serial.c | 18 +++++++++++-------
server/protocol.def | 1 +
server/serial.c | 9 +++++----
4 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/dlls/kernel32/tests/comm.c b/dlls/kernel32/tests/comm.c
index e54be7a..7646766 100644
--- a/dlls/kernel32/tests/comm.c
+++ b/dlls/kernel32/tests/comm.c
@@ -860,8 +860,7 @@ todo_wine
{
/* unblock pending wait */
trace("recovering after WAIT_TIMEOUT...\n");
- /* FIXME: Wine fails to unblock with new mask being equal to the old one */
- res = SetCommMask(hcom, 0);
+ res = SetCommMask(hcom, EV_TXEMPTY);
ok(res, "SetCommMask error %d\n", GetLastError());
res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
@@ -968,8 +967,7 @@ todo_wine
/* unblock pending wait */
trace("recovering after WAIT_TIMEOUT...\n");
- /* FIXME: Wine fails to unblock with new mask being equal to the old one */
- res = SetCommMask(hcom, 0);
+ res = SetCommMask(hcom, EV_TXEMPTY);
ok(res, "SetCommMask error %d\n", GetLastError());
res = WaitForSingleObject(ovl_wait.hEvent, TIMEOUT);
diff --git a/dlls/ntdll/serial.c b/dlls/ntdll/serial.c
index 07ba633..5e6eaf4 100644
--- a/dlls/ntdll/serial.c
+++ b/dlls/ntdll/serial.c
@@ -380,7 +380,7 @@ static NTSTATUS get_timeouts(HANDLE handle, SERIAL_TIMEOUTS* st)
return status;
}
-static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD* mask)
+static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD *mask, DWORD *cookie)
{
NTSTATUS status;
@@ -388,7 +388,10 @@ static NTSTATUS get_wait_mask(HANDLE hDevice, DWORD* mask)
{
req->handle = wine_server_obj_handle( hDevice );
if (!(status = wine_server_call( req )))
+ {
*mask = reply->eventmask;
+ if (cookie) *cookie = reply->cookie;
+ }
}
SERVER_END_REQ;
return status;
@@ -794,6 +797,7 @@ typedef struct async_commio
IO_STATUS_BLOCK* iosb;
HANDLE hEvent;
DWORD evtmask;
+ DWORD cookie;
DWORD mstat;
serial_irq_info irq_info;
} async_commio;
@@ -906,9 +910,9 @@ static DWORD CALLBACK wait_for_event(LPVOID arg)
if (!server_get_unix_fd( commio->hDevice, FILE_READ_DATA | FILE_WRITE_DATA, &fd, &needs_close, NULL, NULL ))
{
serial_irq_info new_irq_info;
- DWORD new_mstat, new_evtmask;
+ DWORD new_mstat, dummy, cookie;
LARGE_INTEGER time;
-
+
TRACE("device=%p fd=0x%08x mask=0x%08x buffer=%p event=%p irq_info=%p\n",
commio->hDevice, fd, commio->evtmask, commio->events, commio->hEvent, &commio->irq_info);
@@ -934,8 +938,8 @@ static DWORD CALLBACK wait_for_event(LPVOID arg)
&new_irq_info, &commio->irq_info,
new_mstat, commio->mstat);
if (*commio->events) break;
- get_wait_mask(commio->hDevice, &new_evtmask);
- if (commio->evtmask != new_evtmask)
+ get_wait_mask(commio->hDevice, &dummy, &cookie);
+ if (commio->cookie != cookie)
{
*commio->events = 0;
break;
@@ -964,7 +968,7 @@ static NTSTATUS wait_on(HANDLE hDevice, int fd, HANDLE hEvent, PIO_STATUS_BLOCK
commio->events = events;
commio->iosb = piosb;
commio->hEvent = hEvent;
- get_wait_mask(commio->hDevice, &commio->evtmask);
+ get_wait_mask(commio->hDevice, &commio->evtmask, &commio->cookie);
/* We may never return, if some capabilities miss
* Return error in that case
@@ -1159,7 +1163,7 @@ static inline NTSTATUS io_control(HANDLE hDevice,
case IOCTL_SERIAL_GET_WAIT_MASK:
if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
{
- if (!(status = get_wait_mask(hDevice, lpOutBuffer)))
+ if (!(status = get_wait_mask(hDevice, lpOutBuffer, NULL)))
sz = sizeof(DWORD);
}
else
diff --git a/server/protocol.def b/server/protocol.def
index 9164e3e..a7c5478 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2219,6 +2219,7 @@ enum message_type
unsigned int writeconst;
unsigned int writemult;
unsigned int eventmask;
+ unsigned int cookie;
@END
diff --git a/server/serial.c b/server/serial.c
index aac20fa..2f0b8f2 100644
--- a/server/serial.c
+++ b/server/serial.c
@@ -76,6 +76,7 @@ struct serial
unsigned int writemult;
unsigned int eventmask;
+ unsigned short generation; /* event mask change counter */
struct termios original;
@@ -135,6 +136,7 @@ struct object *create_serial( struct fd *fd )
serial->writemult = 0;
serial->writeconst = 0;
serial->eventmask = 0;
+ serial->generation = 0;
serial->fd = (struct fd *)grab_object( fd );
set_fd_user( fd, &serial_fd_ops, &serial->obj );
return &serial->obj;
@@ -210,6 +212,7 @@ DECL_HANDLER(get_serial_info)
/* event mask */
reply->eventmask = serial->eventmask;
+ reply->cookie = serial->generation;
release_object( serial );
}
@@ -235,10 +238,8 @@ DECL_HANDLER(set_serial_info)
if (req->flags & SERIALINFO_SET_MASK)
{
serial->eventmask = req->eventmask;
- if (!serial->eventmask)
- {
- fd_async_wake_up( serial->fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
- }
+ if (++serial->generation >= 0xffff) serial->generation = 1;
+ fd_async_wake_up( serial->fd, ASYNC_TYPE_WAIT, STATUS_SUCCESS );
}
release_object( serial );
--
1.8.3.4
More information about the wine-patches
mailing list