I have NDIS FilterDriver, running on Windows 10 (BUILD_VERSION_STRING: 18362.1.amd64fre.19h1_release.190318-1202).
With one of the test script on the certain test PC, it fails with DPC_WATCHDOG_VIOLATION BSOD.
Callstack looks like below:
nt!KeBugCheckEx
nt!KeAccumulateTicks+0x1815bd
nt!KeClockInterruptNotify+0xc07
hal!HalpTimerClockIpiRoutine+0x21
nt!KiCallInterruptServiceRoutine+0xa5
nt!KiInterruptSubDispatchNoLockNoEtw+0xfa
nt!KiInterruptDispatchNoLockNoEtw+0x37
nt!KxWaitForSpinLockAndAcquire+0x33
nt!KeAcquireSpinLockAtDpcLevel+0x5b
MYDRV!FilterReceiveNetBufferLists+0x1c8 [c:\MYDRV_SRC\my_filter.cpp # 1768]
ndis!ndisCallReceiveHandler+0x60
ndis!ndisInvokeNextReceiveHandler+0x206cf
ndis!NdisMIndicateReceiveNetBufferLists+0x104
e1i65x64!RECEIVE::RxIndicateNBLs+0x12f
e1i65x64!RECEIVE::RxProcessInterrupts+0x20a
e1i65x64!INTERRUPT::MsgIntDpcTxRxProcessing+0x124
e1i65x64!INTERRUPT::MsgIntMessageInterruptDPC+0x1ff
e1i65x64!INTERRUPT::MiniportMessageInterruptDPC+0x28
ndis!ndisInterruptDpc+0x19c
nt!KiExecuteAllDpcs+0x30a
nt!KiRetireDpcList+0x1ef
nt!KxRetireDpcList+0x5
nt!KiDispatchInterruptContinue
nt!KiDpcInterrupt+0x2ee
nt!RtlpHpSegPageRangeShrink+0x2d5
nt!ExFreeHeapPool+0x751
nt!ExFreePool+0x9
MYDRV!StartReqCancel+0x16f [c:\MYDRV_SRC\my_device.cpp # 1420]
nt!IoCancelIrp+0x71
nt!IopCancelIrpsInCurrentThreadList+0x104
MYDRV!StartReqCancel is Cancel routine to user's IRP.
Execution stuck in FilterReceiveNetBufferLists here:
NdisDprAcquireSpinLock(&pFilter->startIrpLock);
In MYDRV!StartReqCancel cancel routine this spinlock is locked to free the associated resources, like:
// Clear Cancel routine
IoSetCancelRoutine(pIrp, NULL);
// Release the cancel spinlock
IoReleaseCancelSpinLock(pIrp->CancelIrql);
NdisDprAcquireSpinLock(&pFilter->startIrpLock);
// Clear capture data
//...
for (int i=0; i<pFilter->dataN; ++i )
ExFreePool(pFilter->pCaptData[i]); //non-paged data!
//...
NdisDprReleaseSpinLock(&pFilter->startIrpLock);
// Complete the request
pIrp->IoStatus.Status = STATUS_CANCELLED;
pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);//CAPTURE_START_IRP
It looks like during the ExFreePool call, HW driver gets interrupt for incoming packets, and eventually calls my filter driver's FilterReceiveNetBufferLists, where it tries to acquire the pFilter->startIrpLock spinlock (at DISPATCH_LEVEL), which was locked by MYDRV!StartReqCancel. But it looks like StartReqCancel never returns from ExFreePool. Value of pFilter->dataN is not too big (<64).
Do you have any ideas why it can be?
Just found a reason of this strange accident, thanks to Driver Verifier:
//....
// Release the cancel spinlock
// Here we have IRQL = DISPATCH_LEVEL here
IoReleaseCancelSpinLock(pIrp->CancelIrql);
// Now we have IRQL < DISPATCH_LEVEL !!!
NdisDprAcquireSpinLock(&pFilter->startIrpLock); // !!! No real spinlock acquisition here!!!
// NON LOCKED code here.
// ....
// NdisDprReleaseSpinLock(&pFilter->startIrpLock); // Nothing unlocked here
Related
I have some (mostly CubeMX-generated) code:
volatile uint8_t buf[4];
int main(void)
{
...
HAL_UART_Receive_IT(&huart3, buf, sizeof(buf));
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART3) {
HAL_UART_Transmit(&huart3, buf, sizeof(buf), 0xFFFF);
HAL_UART_Receive_IT(&huart3, buf, sizeof(buf));
}
}
This successfully echos everything which is received on USART3. (This code is just a throw-away example to learn about the serial port.)
I am concerned about the time between HAL_UART_RxCpltCallback() being called and HAL_UART_Receive_IT() setting up the next receive.
Is there any feature of the STM32F103 which guarantees that data won't be lost in this interval? I haven't found any evidence of more than a two byte receive buffer on the USART.
I am particularly concerned that some higher-priority USB-device activity might delay the calling of HAL_UART_RxCpltCallback(), and so one or more characters might be lost.
Quick answer:
HAL_UART_Transmit is a blocking function, so, until it completes HAL_UART_Receive_IT is not called and the uart will surely go overflow. If you are worried of any other interrupt can preemt your execution, use dma or disable the troublesome interrupts while you issue the command. You could also rise UART interrupt priority but....
Hints:
....you should not call HAL_UART_Transmit and HAL_UART_Receive_IT within HAL_UART_RxCpltCallback as here you are in ISR mode. This cause some side issues on certain versions of the HAL framework. Better to set a flag and check for it from the main code.
Also you should really avoid the use of volatile, better if you use a compiler barrier like gcc __asm volatile("" ::: "memory")
I have some code use qtcpsocket to write and read,
write-->sleep-->read;
and ui had 2 and more timer to use this function; by i want i run synchronous;so i add mutex to lock it; by it deadlock;
qt4; qt5;
void MainWindow::Start()
{
pTimer = new QTimer(this);
pTimer->setInterval(100);
connect(pTimer,SIGNAL(timeout()), this, SLOT(OnTimer()) );
pTimer->start();
pTimer2 = new QTimer(this);
pTimer2->setInterval(100);
connect(pTimer2,SIGNAL(timeout()), this, SLOT(OnTimer()) );
pTimer2->start();
}
void MainWindow::OnTimer()
{
FunCal(); // in my real code it will MyObj.DoSometing();
}
void MainWindow::FunCal()
{
qDebug()<<"log in fun...";
QMutexLocker loc(&this->_mtx);
qDebug()<<"getted lock in fun...";
QEventLoop loop;
QTimer::singleShot(100, &loop, SLOT(quit()));
loop.exec();
qDebug()<<"log out fun...";
}
I Want i run and out put as:
log in fun...
getted lock in fun ...
log out fun...
log in fun...
getted lock in fun...
log out fun...
but It Run like this:
log in fun...
getted lock in fun ...
log in fun....
---------------------------------no more ---------------------
IMHO the issue of OP results from a basic misunderstanding:
QTimer doesn't introduce multithreading.
It's just a facility to queue events which will sent after a certain time.
That's why, the QEventLoop is necessary to make it running at all.
However, it's still a deterministic execution and this is what probably happens inside the code of OP:
pTimer->start(); → starts first timer
pTimer2->start(); → starts second timer
control flow returns to event loop of QApplication (not exposed in code)
first timer becomes due and calls MainWindow::FunCal()
qDebug()<<"log in fun..."; → output of log in fun...
QMutexLocker loc(&this->_mtx); → this->_mtx becomes locked
qDebug()<<"getted lock in fun..."; → output of getted lock in fun...
loop.exec(); → enter a nested event loop (Nested event loops are allowed in Qt.)
second timer becomes due and calls MainWindow::FunCal() (Please, remember that it was immediately started after first with same interval time.)
qDebug()<<"log in fun..."; → output of log in fun...
QMutexLocker loc(&this->_mtx); → PROBLEM!
To illustrate it further, imagine the following call stack at this point (above called below):
QApplication::exec()
QEventLoop::exec()
QEventLoop::processEvents()
QTimer::timerEvent()
QTimer::timeOut()
MainWindow::onTimer()
MainWindow::FunCal()
QEventLoop::exec()
QTimer::timerEvent()
QTimer::timeOut()
MainWindow::onTimer()
MainWindow::FunCal()
QMutexLocker::QMutexLocker()
QMutex::lock()
(Note: In reality, you will see much more entries in the call-stack which I considered as irrelevant details in this case.)
The problem is: This second call of MainWindow::FunCal() cannot lock the mutex because it is already locked. Hence, the execution is suspended until the mutex is unlocked but this will never happen. The locking of mutex happened in the same thread (in the first/outer call of MainWindow::FunCal()). Unlocking would require to return from this point but it cannot because it's suspended due to the locked mutex.
If you think this sounds like a cat byting into its own tail – yes, this impression is right. However, the official term is Deadlock.
The usage of a QMutex doesn't make much sense as long as there are no competing threads. In a single thread, a simple bool variable would do as well because there are no concurrent accesses possible in a single thread.
Whatever OP tried to achieve in this code: Concerning the event-based programming forced/required by Qt, the problem is simply modeled wrong.
In single threading, a function cannot be entered twice accept by
a (direct or indirect) recursive call
a call out of a triggered interrupt handler.
Leaving the 2. aside (irrelevant for OPs Qt issue), the recursive call happens explicitly due to establishing a second (nested) event loop. Without this, the whole (mutex) locking is unnecessary and should be removed as well.
To understand event-based programming in general – it's described in the Qt doc. The Event System.
Additionally, I found Another Look at Events by Jasmin Blanchette which IMHO gives a nice little introduction into how the Qt event-based execution works.
Note:
Event-based programming can become confusing as soon as the amount of involved objects and signals becomes large enough. While debugging my Qt applications, I noticed from time to time recursions which I didn't expect.
A simple example: A value is changed and emits a signal. One of the slots updates a Qt widget which emits a signal about modification. One of the slots updates the value. Hence, the value is changed and emits a signal...
To break such infinite recursions, a std::lock_guard might be used with a simple DIY class Lock:
#include <iostream>
#include <mutex>
#include <functional>
#include <cassert>
// a lock class
class Lock {
private:
bool _lock;
public:
Lock(): _lock(false) { }
~Lock() = default;
Lock(const Lock&) = delete;
Lock& operator=(const Lock&) = delete;
operator bool() const { return _lock; }
void lock() { assert(!_lock); _lock = true; }
void unlock() { assert(_lock); _lock = false; }
};
A sample object with
a property-like member: bool _value
a simplified signal emitter: std::function<void()> sigValueSet
and a lock used to prevent recursive calls to setValue(): Lock _lockValue
// a sample data class with a property
class Object {
private:
bool _value; // a value
Lock _lockValue; // a lock to prevent recursion
public:
std::function<void()> sigValueSet;
public:
Object(): _value(false) { }
bool value() const { return _value; }
void setValue(bool value)
{
if (_lockValue) return;
std::lock_guard<Lock> lock(_lockValue);
// assign value
_value = value;
// emit signal
if (sigValueSet) sigValueSet();
}
};
Finally, some code to force the lock into action:
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(Object obj);
std::cout << "obj.value(): " << obj.value() << '\n';
DEBUG(obj.sigValueSet = [&](){ obj.setValue(obj.value()); });
DEBUG(obj.setValue(true));
std::cout << "obj.value(): " << obj.value() << '\n';
}
To keep things short, I connected a slot to the signal which directly sets value again while the signal is emitted.
Output:
Object obj;
obj.value(): 0
obj.sigValueSet = [&](){ obj.setValue(obj.value()); };
obj.setValue(true);
obj.value(): 1
Live Demo on coliru
For a counter-example, I excluded the test if (_lockValue) return; and got the following output:
a.out: main.cpp:18: void Lock::lock(): Assertion `!_lock' failed.
Object obj;
obj.value(): 0
obj.sigValueSet = [&](){ obj.setValue(obj.value()); };
obj.setValue(true);
bash: line 7: 12214 Aborted (core dumped) ./a.out
Live Demo on coliru
This is similar to what happened in OPs case with the only difference that in my case double-locking just violated the assert().
To make this complete, I exluded the lock guard std::lock_guard<Lock> lock(_lockValue); as well and got the following output:
execution expired
Live Demo on coliru
The execution was trapped into an infinite recursion, and the online compiler aborted this after a certain time. (Sorry, coliru. I won't do it again.)
I'm new to the PSoC board and I'm trying to read the x,y,z values from a Digital Compass but I'm having a problem in beginning the Transmission with the compass itself.
I found some Arduino tutorial online here but since PSoC doesn't have the library I can't duplicate the code.
Also I was reading the HMC5883L datasheet here and I'm suppose to write bytes to the compass and obtain the values but I was unable to receive anything. All the values I received are zero which might be caused by reading values from wrong address.
Hoping for your answer soon.
PSoC is sorta tricky when you are first starting out with it. You need to read over the documentation carefully of both the device you want to talk to and the i2c module itself.
The datasheet for the device you linked states this on page 18:
All bus transactions begin with the master device issuing the start sequence followed by the slave address byte. The
address byte contains the slave address; the upper 7 bits (bits7-1), and the Least Significant bit (LSb). The LSb of the
address byte designates if the operation is a read (LSb=1) or a write (LSb=0). At the 9
th clock pulse, the receiving slave
device will issue the ACK (or NACK). Following these bus events, the master will send data bytes for a write operation, or
the slave will clock out data with a read operation. All bus transactions are terminated with the master issuing a stop
sequence.
If you use the I2C_MasterWriteBuf function, it wraps all that stuff the HMC's datasheet states above. The start command, dealing with that ack, the data handling, etc. The only thing you need to specify is how to transmit it.
If you refer to PSoC's I2C module datasheet, the MasterWriteBuf function takes in the device address, a pointer to the data you want to send, how many bytes you want to send, and a "mode". It shows what the various transfer modes in the docs.
I2C_MODE_COMPLETE_XFER Perform complete transfer from Start to Stop.
I2C_MODE_REPEAT_START Send Repeat Start instead of Start.
I2C_MODE_NO_STOP Execute transfer without a Stop
The MODE_COMPLETE_XFRE transfer will send the start and stop command for you if I'm not mistaken.
You can "bit-bang" this also if you want but calling directly on the I2C_MasterSendStart, WriteByte, SendStop, etc. But it's just easier to call on their writebuf functions.
Pretty much you need to write your code like follows:
// fill in your data or pass in the buffer of data you want to write
// if this is contained in a function call. I'm basing this off of HMC's docs
uint8 writeBuffer[3];
uint8 readBuffer[6];
writeBuffer[0] = 0x3C;
writeBuffer[1] = 0x00;
writeBuffer[2] = 0x70;
I2C_MasterWriteBuf(HMC_SLAVE_ADDRESS, &writeBuffer, 3, I2C_MODE_COMPLETE_XFER);
while((I2C_MasterStatus() & I2C_MSTAT_WR_CMPLT) == 0u)
{
// wait for operation to finish
}
writeBuffer[1] = 0x01;
writeBuffer[2] = 0xA0;
I2C_MasterWriteBuf(HMC_SLAVE_ADDRESS, &writeBuffer, 3, I2C_MODE_COMPLETE_XFER);
// wait for operation to finish
writeBuffer[1] = 0x02;
writeBuffer[2] = 0x00;
I2C_MasterWriteBuf(HMC_SLAVE_ADDRESS, &writeBuffer, 3, I2C_MODE_COMPLETE_XFER);
// wait for operation to finish
CyDelay(6); // docs state 6ms delay before you can start looping around to read
for(;;)
{
writeBuffer[0] = 0x3D;
writeBuffer[1] = 0x06;
I2C_MasterWriteBuf(HMC_SLAVE_ADDRESS, &writeBuffer, 2, I2C_MODE_COMPLETE_XFER);
// wait for operation to finish
// Docs don't state any different sort of bus transactions for reads.
// I'm assuming it'll be the same as a write
I2C_MasterReadBuf(HMC_SLAVE_ADDRESS, readBuffer, 6, I2C_MODE_COMPLETE_XFER);
// wait for operation to finish, wait on I2C_MSTAT_RD_CMPLT instead of WR_COMPLT
// You should have something in readBuffer to work with
CyDelay(67); // docs state to wait 67ms before reading again
}
I just sorta wrote that off the top of my head. I have no idea if that'll work or not, but I think that should be a good place to start and try. They have I2C example projects to look at also I think.
Another thing to look at so the WriteBuf function doesn't just seem like some magical command, if you right-click on the MasterWriteBuf function and click on "Find Definition" (after you build the project) it'll show you what it's doing.
Following are the samples for I2C read and write operation on PSoC,
simple Write operation:
//Dumpy data values to write
uint8 writebuffer[3]
writebuffer[0] = 0x23
writebuffer[1] = 0xEF
writebuffer[2] = 0x0F
uint8 I2C_MasterWrite(uint8 slaveAddr, uint8 nbytes)
{
uint8 volatile status;
status = I2C_MasterClearStatus();
if(!(status & I2C_MSTAT_ERR_XFER))
{
status = I2C_MasterWriteBuf(slaveAddr, (uint8 *)&writebuffer, nbytes, I2C_MODE_COMPLETE_XFER);
if(status == I2C_MSTR_NO_ERROR)
{
/* wait for write complete and no error */
do
{
status = I2C_MasterStatus();
} while((status & (I2C_MSTAT_WR_CMPLT | I2C_MSTAT_ERR_XFER)) == 0u);
}
else
{
/* translate from I2CM_MasterWriteBuf() error output to
* I2C_MasterStatus() error output */
status = I2C_MSTAT_ERR_XFER;
}
}
return status;
}
Read Operation:
void I2C_MasterRead(uint8 slaveaddress, uint8 nbytes)
{
uint8 volatile status;
status = I2C_MasterClearStatus();
if(!(status & I2C_MSTAT_ERR_XFER))
{
/* Then do the read */
status = I2C_MasterClearStatus();
if(!(status & I2C_MSTAT_ERR_XFER))
{
status = I2C_MasterReadBuf(slaveaddress,
(uint8 *)&(readbuffer),
nbytes, I2C_MODE_COMPLETE_XFER);
if(status == I2C_MSTR_NO_ERROR)
{
/* wait for reading complete and no error */
do
{
status = I2C_MasterStatus();
} while((status & (I2C_MSTAT_RD_CMPLT | I2C_MSTAT_ERR_XFER)) == 0u);
if(!(status & I2C_MSTAT_ERR_XFER))
{
/* Decrement all RW bytes in the EZI2C buffer, by different values */
for(uint8 i = 0u; i < nbytes; i++)
{
readbuffer[i] -= (i + 1);
}
}
}
else
{
/* translate from I2C_MasterReadBuf() error output to
* I2C_MasterStatus() error output */
status = I2C_MSTAT_ERR_XFER;
}
}
}
if(status & I2C_MSTAT_ERR_XFER)
{
/* add error handler code here */
}
}
MyApp.exe is installed using an InstallScript 2014 project. The folks in manufacturing recently tried to upgrade to a more recent development version but did not close the existing instance of MyApp. This resulted in many permission denied errors since the various dll's used by the app were locked and in use.
I expected the InstallScript executable to do the usual "stage and reboot" thing that all Windows folks are intimate with. It did not do that, and I can't see anything in the InstallShield project editor that obviously lets me force that behavior.
I also expected InstallScript to allow me to somehow detect that my app was already running - if I can do that, I can display a dialog to give the user a chance to close the app and continue. The only solution for this is InstallSite.org List and Shutdown Running Processes. (Note this is unanswered on another S/O question.)
That does not properly detect all of the running tasks, including my own.
Before I spend a couple of days trying to fix what seems to be an obviously missing feature of InstallScript, I thought I'd ask if there's a better approach.
Here's what I came up with. Hope this helps.
// defines/protos for finding a process
#define TH32CS_SNAPPROCESS 0x00000002
// in Kernel32.dll
prototype NUMBER Kernel32.CreateToolhelp32Snapshot(NUMBER , NUMBER);
prototype BOOL Kernel32.Process32First(HWND , POINTER );
prototype BOOL Kernel32.Process32Next(HWND , POINTER );
// from minwindef.h, windows api
typedef PROCESSENTRY32
begin
number dwSize;
number cntUsage;
number th32ProcessID; // this process
number th32DefaultHeapID;
number th32ModuleID; // associated exe
number cntThreads;
number th32ParentProcessID; // this process's parent process
number pcPriClassBase; // Base priority of process's threads
number dwFlags;
STRING szExeFile[MAX_PATH]; // Path
end;
// ========================================================================================
// list all of the running processes, see if Flex is running
// based on https://msdn.microsoft.com/en-us/library/windows/desktop/ms686701(v=vs.85).aspx
// ========================================================================================
function BOOL IsProcessRunning(sProcessName)
HWND hProcessSnap;
PROCESSENTRY32 pe;
POINTER ppe;
NUMBER ret;
begin
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pe.dwSize = SizeOf(pe);
ppe = &pe;
ret = Process32First(hProcessSnap, ppe);
if (ret == 0) then
//printError(TEXT("Process32First")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return(FALSE);
endif;
repeat
if (StrCompare(sProcessName, pe.szExeFile) == 0) then
CloseHandle(hProcessSnap); // clean the snapshot object
return(TRUE);
endif;
ret = Process32Next(hProcessSnap, ppe);
until (ret == 0);
return(FALSE);
end;
You then call it
if (IsProcessRunning("WORD.EXE")) then
blah blah
endif;
I'm writing a garage door opener and monitor.
The monitor receives the door status via another Arduino over RF (315 MHz). The code below works, but I feel that I shouldn't need to check the status every time I make a request to the server to open the door. Is there a way to split the code out so that I check the door status every 20 seconds, and the opening and closing of the garage are on demand?
Here is the code:
https://github.com/dhysong/ArduinoGarageOpener/blob/master/src/GarageDoorOpener/GarageDoorOpener.ino
Based on this post: http://arduino.cc/forum/index.php/topic,5686.0.html
I was able to add a mult-threading like capability to my app. Source code has been updated to reflect the change.
Here's the pertinent piece:
boolean cycleCheck(unsigned long *lastMillis, unsigned int cycle)
{
unsigned long currentMillis = millis();
if(currentMillis - *lastMillis >= cycle)
{
*lastMillis = currentMillis;
return true;
}
else
return false;
}
Here's the github code for anyone that might benefit: https://github.com/dhysong/ArduinoGarageOpener/blob/master/src/GarageDoorOpener/GarageDoorOpener.ino