none
Thread Messaging Difference CE5.0 to CE6.0

    Question

  • Hi,

    I am having a problem with inter-thread messaging in CE6.0 R3.  The following inter-thread messaging works in CE5.0 but not CE6.0:

    I have an stream device driver loaded in kernel mode by Device Manager.   The driver then creates a separate thread in its xxx_Init() function as follows:

                    hOSThreadID = CreateThread (NULL,0, &MyThread, &gMyData, 0, NULL );

    Then when MyThread runs it does the following to initialize its message queue:

                    //Wait for windows manager APIs to be ready before calling PeekMessage.

                    WaitForGWES();

                    //First call creates message queue

                    MSG msg = {0};

                    PeekMessage(&msg, (HWND)-1, WM_USER, WM_USER, PM_NOREMOVE);

    Then the thread checks for messages as follows:

                    while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )               { …. }

    Meanwhile, an application process creates a thread and that thread gets the OS thread ID (via IOCTL to stream driver) and sends messages to the OS thread as follows:

                    #define WM_MYMSG   WM_APP + 34

                    ::PostThreadMessage( hOSThreadID, WM_MYMSG, wParam, lParam );

    The above thread messaging works in CE5.0 but not CE6.0.   I am thinking the problem is due to the change in CE 6.0 where the OS thread is now running in kernel mode but the application thread is running in user mode.

    Instead of using a message in the WM_APP area,  I  tried in the application registering the message as follows.  This did not help.

                    int WM_MyMsg = RegisterWindowMessage( (LPCTSTR)"APP_TO_OS_MSG");

                    ::PostThreadMessage( hOSThreadID, WM_MyMsg, wParam, lParam );

    Is this type of thread messaging possible in CE6.0?

    Do I have to switch to using a point-to-point message queue?

    Thanks in advance.

    Friday, May 25, 2012 1:40 PM

Answers

  • On 5/25/2012 6:16 PM, rletizia wrote:
    > Bruce,
    >
    > Based on Valter's and your answer, it sounds like I must switch to
    > Point2Point messaging.
    >
    > But to answer your question: The application gets the thread ID of the
    > kernel thread. The application then uses PostThreadMesage() with this
    > thread id to send messages to the kernel thread. This worked well in
    > CE5.0. The kernel thread is actually an interrupt service thread (IST)
    > that runs in response to a device interrupt or periodically, and when
    > running it also checks for messages using PeakMessage(). When a message
    > is received it directly contains the data (4 bytes) that the application
    > needed to send the IST. The PostThreadMessage() and PeekMessage()
    > combination seemed like a good way to directly transfer small amounts of
    > data from the application process to the IST.
     
    Ciao rletizia,
    the kind of message queue you are using is related to GWES and the UI,
    if you need some kind of messaging for non-UI related pourposes,
    point-to-point message queues are a better options.
     
     

    Valter Minute
    Windows Embedded MVP
    http://geekswithblogs.net/WindowsEmbeddedCookbook
    • Marked as answer by rletizia Tuesday, May 29, 2012 12:21 PM
    Monday, May 28, 2012 6:51 AM

All replies

  • On 5/25/2012 3:40 PM, rletizia wrote:
    > Hi,
    >
    > I am having a problem with inter-thread messaging in CE6.0 R3.The
    > following inter-thread messaging works in CE5.0 but not CE6.0:
    >
    > I have an stream device driver loaded in kernel mode by Device
    > Manager.The driver then creates a separate thread in its xxx_Init()
    > function as follows:
    >
    > hOSThreadID = CreateThread (NULL,0, &MyThread, &gMyData, 0, NULL );
    >
    > Then when MyThread runs it does the following to initialize its message
    > queue:
    >
    > //Wait for windows manager APIs to be ready before calling PeekMessage.
    >
    > WaitForGWES();
    >
    > //First call creates message queue
    >
    > MSG msg = {0};
    >
    > PeekMessage(&msg, (HWND)-1, WM_USER, WM_USER, PM_NOREMOVE);
    >
    > Then the thread checks for messages as follows:
    >
    > while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) { …. }
    >
    > Meanwhile, an application process creates a thread and that thread gets
    > the OS thread ID (via IOCTL to stream driver) and sends messages to the
    > OS thread as follows:
    >
    > #define WM_MYMSG WM_APP + 34
    >
    > ::PostThreadMessage( hOSThreadID, WM_MYMSG, wParam, lParam );
    >
    > The above thread messaging works in CE5.0 but not CE6.0.I am thinking
    > the problem is due to the change in CE 6.0 where the OS thread is now
    > running in kernel mode but the application thread is running in user mode.
    >
    > Instead of using a message in the WM_APP area, I tried in the
    > application registering the message as follows.This did not help.
    >
    > int WM_MyMsg = RegisterWindowMessage( (LPCTSTR)"APP_TO_OS_MSG");
    >
    > ::PostThreadMessage( hOSThreadID, WM_MyMsg, wParam, lParam );
    >
    > Is this type of thread messaging possible in CE6.0?
    >
    > Do I have to switch to using a point-to-point message queue?
    >
    > Thanks in advance.
    >
     
    You are using GWES messages (created for managing the UI) inside a
    driver thread. In CE 6 drivers have been moved to kernel mode and they
    are no longer allowed to access the UI.
    Moving to Point2Point message queues is the right solution.
     

    Valter Minute
    Windows Embedded MVP
    http://geekswithblogs.net/WindowsEmbeddedCookbook
    • Proposed as answer by Misbah Khan Friday, May 25, 2012 3:03 PM
    Friday, May 25, 2012 2:40 PM
  • That, or have the driver return a value to the application so that the application can post the message.

    Bruce Eitman (eMVP)
    Senior Engineer
    Bruce.Eitman AT Eurotech DOT com
    My BLOG http://geekswithblogs.net/bruceeitman

    Eurotech Inc.
    www.Eurotech.com

    Friday, May 25, 2012 3:05 PM
  • Thanks Valter & Bruce.

    Bruce, can you elaborate on your answer?

    Presently the drive returns the kernel thread ID (via IOCTL) to the application thread.  The application thread then posts messages using this thread id and a registered message id.    This sounds like what you are explaining.

    Thanks again.

    Friday, May 25, 2012 3:18 PM
  • I am sorry, I missread your post a little bit.

    So after reading it again, your driver must not use UI related functions like PeekMessage().   If your app needs to tell the driver something, then either add an IOCTL to the driver that the app can call, or as Valter suggested, use a Point2Point message queue.

    What I don't understand is why the app needs to do anything with regard to the thread ID.  From your description, the app gets the ID from the driver and then tells the driver about its thread ID, is that correct?


    Bruce Eitman (eMVP)
    Senior Engineer
    Bruce.Eitman AT Eurotech DOT com
    My BLOG http://geekswithblogs.net/bruceeitman

    Eurotech Inc.
    www.Eurotech.com

    Friday, May 25, 2012 3:40 PM
  •  

    Bruce,

    Based on Valter's and your answer, it sounds like I must switch to Point2Point messaging.

    But to answer your question:  The application gets the thread ID of the kernel thread.   The application then uses PostThreadMesage() with this thread id to send messages to the kernel thread.   This worked well in CE5.0.   The kernel thread is actually an interrupt service thread (IST) that runs in response to a device interrupt or periodically, and when running it also checks for messages using PeakMessage().  When a message is received it directly contains the data (4 bytes) that the application needed to send the IST.   The PostThreadMessage() and PeekMessage() combination seemed like a good way to directly transfer small amounts of data from the application process to the IST.

    Thanks.

    Friday, May 25, 2012 4:16 PM
  • On 5/25/2012 6:16 PM, rletizia wrote:
    > Bruce,
    >
    > Based on Valter's and your answer, it sounds like I must switch to
    > Point2Point messaging.
    >
    > But to answer your question: The application gets the thread ID of the
    > kernel thread. The application then uses PostThreadMesage() with this
    > thread id to send messages to the kernel thread. This worked well in
    > CE5.0. The kernel thread is actually an interrupt service thread (IST)
    > that runs in response to a device interrupt or periodically, and when
    > running it also checks for messages using PeakMessage(). When a message
    > is received it directly contains the data (4 bytes) that the application
    > needed to send the IST. The PostThreadMessage() and PeekMessage()
    > combination seemed like a good way to directly transfer small amounts of
    > data from the application process to the IST.
     
    Ciao rletizia,
    the kind of message queue you are using is related to GWES and the UI,
    if you need some kind of messaging for non-UI related pourposes,
    point-to-point message queues are a better options.
     
     

    Valter Minute
    Windows Embedded MVP
    http://geekswithblogs.net/WindowsEmbeddedCookbook
    • Marked as answer by rletizia Tuesday, May 29, 2012 12:21 PM
    Monday, May 28, 2012 6:51 AM