Acfboy commented on issue #18566: URL: https://github.com/apache/nuttx/issues/18566#issuecomment-4702351213
Hi @ppisa, Here is a weekly report about my work. I have implemented the fb, mouse, and keyboard drivers for Microwindows, and ported mwdemo.c to examples in the three commits below. It seems to be running well in my qemu-intel64 and sim environments. 1. fb driver: https://github.com/Acfboy/nuttx-apps/commit/8877bb49cfe9d4af1c499132997b294d324432cf 2. keyboard and mouse driver: https://github.com/Acfboy/nuttx-apps/commit/29058f0c70020ab4f925b1b8618d4f65b9dd762e 3. mwdemo.c: https://github.com/Acfboy/nuttx-apps/commit/b500978d0b339ced516cd328cb483f354622be14 ## Something strange However, I encountered a strange issue when running `mwdemo.c` on QEMU. The animation sometimes gets stuck at the beginning until a mouse or keyboard event occurs. After digging deep into the codebase, I found the reason: In `microwindows/src/mwin/winmain.c`, there is a function `MwSelect` which waits until an event occurs (timer, mouse, or keyboard). [code permalink](https://github.com/ghaerr/microwindows/blob/1e71398cc6f650687f406547230c33788eeaf9c7/src/mwin/winmain.c#L281-L300) ```c int poll = (!canBlock || dragwp); /* just poll if can't block or window move in progress*/ if (!poll) { if ((timeout = MwGetNextTimeoutValue()) == (MWTIMEOUT) -1L) /* get next mwin timer*/ timeout = 0; /* no mwin timers*/ #if MW_FEATURE_TIMERS /* get next timer or use passed timeout and convert to timeval struct*/ if (!GdGetNextTimeout(&tout, timeout)) /* no VTSWITCH timer?*/ #else // we don't enter this branch #endif { to = NULL; /* no timers, block*/ } } ``` I noticed that if a timer expires, `MwGetNextTimeoutValue()` returns 0, so `timeout = 0`. However, if there is no VTSWITCH timer (which is the case in QEMU), `GdGetNextTimeout(&tout, timeout)` will directly return false, and `to` will be set to `NULL`. In other words, the code assumes there are no mwin timers, which is inaccurate and causes an endless block until other events occur (`select(setsize, &rfds, &wfds, &efds, NULL)`). And in `mwdemo.c`, we run this event loop: [code permalink](https://github.com/ghaerr/microwindows/blob/1e71398cc6f650687f406547230c33788eeaf9c7/src/demos/mwin/mwdemo.c#L509-L512) ```c while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } ``` In the first few iterations, it sets the timer (50 + rand ms), draws the background and geometry, waits for the timer, and then resets it. This is where the bug occurs: if the drawing process is quite time-consuming, we get `timeout = 0` and get stuck there. The observations above indicate two things: 1. `MwSelect` does not behave as its implementation implies. It should return immediately if the timer has already expired. 2. Why is the drawing process so slow (about 100ms)? I think it might be because we use `NO_CACHE` in the QEMU fb driver, and we write to the framebuffer pixel-by-pixel during drawing. https://github.com/apache/nuttx/blob/1282b94792767bf40cdb8fb50faf9051db0bda42/arch/x86_64/src/intel64/intel64_fb.c#L265-L267 I would love to hear your thoughts, @ppisa, on this issue and my recent commits. Also, @ghaerr, I wonder your insight on this. Is this behavior in `MwSelect` expected under certain conditions, or could it be a potential edge-case bug when the drawing process takes longer than the timeout? Thank you both for your time and help! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
