spin_lock_irqsave - linux-kernel

I am facing odd problem with spin_lock_irqsave on a uni processor machine.
I have a piece of critical code/function named with rx_process which is shared by two functions rx_timeout and rx_callback. This is located under a Linux kernel driver omap-serial.c
rx_process ( uartNum)
{
//critical section
}
rx_timeout (uartNum)//this is called from softIrq context upon timer expiry
{
rx_process (uartNum);
}
rx_callback(uartNum)//this is called when interrupt handler registers upon interrupt and when 4k buf is full in rx_process function which invokes start_rx_dma which results in this call back function.
{
rx_process (uartNum);
}
I found that the race condition was happening between these two functions, hence I decided to introduce spin_lock_irqsave in the rx_process at the beginning of the function and at the end of the function, but it still result in race condition and from time to time, I observe data loss and kernel panic.
rx_process ( uartNum)
{ spin_lock_irqsave(&lock, flags);
//critical section
spin_unlock_irqrestore(&lock, flags);
}
rx_timeout (uartNum)//this is called from softIrq context upon timer expiry
{
rx_process (uartNum);
}
rx_callback(uartNum)//this is called when interrupt handler registers upon interrupt and when 4k buf is full in rx_process function which invokes start_rx_dma which results in this call back function
{
rx_process (uartNum);
}
Now, I moved spin_lock_irqsave to rx_timeout as well as to rx_callback function and I don't see race condition.
rx_process ( uartNum)
{
//critical section
spin_unlock_irqrestore(&lock, flags);
}
rx_timeout (uartNum)//this is called from softIrq context upon timer expiry
{
spin_lock_irqsave(&lock, flags);
rx_process (uartNum);
spin_unlock_irqrestore(&lock, flags);
}
rx_callback(uartNum)//this is called when interrupt handler registers upon interrupt and when 4k buf is full in rx_process function which invokes start_rx_dma which results in this call back function
{
spin_lock_irqsave(&lock, flags);
rx_process (uartNum);
spin_unlock_irqrestore(&lock, flags);
}
I would really appreciate if someone could explain the reason why the spin_lock_irqsave used inside the rx_process is failing and not preventing race conditions?

Related

Assigning architecture specific interrupt handler

The "handle_arch_irq" function pointer is assigned in 2 places with interrupt handler.
1st place:
void setup_arch()
{
handle_arch_irq = mdesc->handle_irq;
}
2nd place:
int set_handle_irq()
{
handle_arch_irq = handle_irq;
}
The set_handle_irq() is called from irq-gic.c.
Can you help to understand why we are initializing at two places.

Timeout for ConnectEx() in IOCP mode?

In an IOCP Winsock2 client, after ConnectEx() times-out on an unsuccessful connection attempt, the following happens:
An "IO completion" is queued to the associated IO Completion Port.
GetQueuedCompletionStatus() returns FALSE.
WSAGetOverlappedResult() returns WSAETIMEDOUT.
What determines the timeout period between calling ConnectEx() and 1 above? How can I shorten this timeout period?
I know that it is possible to wait for ConnectEx() by passing it a filled-out structure OVERLAPPED.hEvent = WSACreateEvent() and then waiting for this event, e.g. with WaitForSingleObject(Overlapped.hEvent, millisec) to timeout after no connection has been made for the millisec time period. BUT, that solution is outside the scope of this question because it does not refer to the IOCP notification model.
unfortunatelly look like no built-in option for set socket connect timeout. how minimum i not view this and based on this question - How to configure socket connect timeout - nobody not view too.
one possible solution pass event handle to I/O request and if we got ERROR_IO_PENDING - call RegisterWaitForSingleObject for this event. if this call will be successful - our WaitOrTimerCallback callback function will be called - or because I/O will be complete (with any final status) and at this moment event (which we pass both to I/O request and RegisterWaitForSingleObject) will be set or because timeout (dwMilliseconds) expired - in this case we need call CancelIoEx function.
so let say we have class IO_IRP : public OVERLAPPED which have reference counting (we need save pointer to OVERLAPPED used in I/O request for pass it to CancelIoEx. and need be sure that this OVERLAPPED still not used in another new I/O - so yet not free). in this case possible implementation:
class WaitTimeout
{
IO_IRP* _Irp;
HANDLE _hEvent, _WaitHandle, _hObject;
static VOID CALLBACK WaitOrTimerCallback(
__in WaitTimeout* lpParameter,
__in BOOLEAN TimerOrWaitFired
)
{
UnregisterWaitEx(lpParameter->_WaitHandle, NULL);
if (TimerOrWaitFired)
{
// the lpOverlapped unique here (because we hold reference on it) - not used in any another I/O
CancelIoEx(lpParameter->_hObject, lpParameter->_Irp);
}
delete lpParameter;
}
~WaitTimeout()
{
if (_hEvent) CloseHandle(_hEvent);
_Irp->Release();
}
WaitTimeout(IO_IRP* Irp, HANDLE hObject) : _hEvent(0), _Irp(Irp), _hObject(hObject)
{
Irp->AddRef();
}
BOOL Create(PHANDLE phEvent)
{
if (HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL))
{
*phEvent = hEvent;
_hEvent = hEvent;
return TRUE;
}
return FALSE;
}
public:
static WaitTimeout* Create(PHANDLE phEvent, IO_IRP* Irp, HANDLE hObject)
{
if (WaitTimeout* p = new WaitTimeout(Irp, hObject))
{
if (p->Create(phEvent))
{
return p;
}
delete p;
}
return NULL;
}
void Destroy()
{
delete this;
}
// can not access object after this call
void SetTimeout(ULONG dwMilliseconds)
{
if (RegisterWaitForSingleObject(&_WaitHandle, _hEvent,
(WAITORTIMERCALLBACK)WaitOrTimerCallback, this,
dwMilliseconds, WT_EXECUTEONLYONCE|WT_EXECUTEINWAITTHREAD))
{
// WaitOrTimerCallback will be called
// delete self here
return ;
}
// fail register wait
// just cancel i/o and delete self
CancelIoEx(_hObject, _Irp);
delete this;
}
};
and use something like
if (IO_IRP* Irp = new IO_IRP(...))
{
WaitTimeout* p = 0;
if (dwMilliseconds)
{
if (!(p = WaitTimeout::Create(&Irp->hEvent, Irp, (HANDLE)socket)))
{
err = ERROR_NO_SYSTEM_RESOURCES;
}
}
if (err == NOERROR)
{
DWORD dwBytes;
err = ConnectEx(socket, RemoteAddress, RemoteAddressLength,
lpSendBuffer, dwSendDataLength, &dwBytes, Irp)) ?
NOERROR : WSAGetLastError();
}
if (p)
{
if (err == ERROR_IO_PENDING)
{
p->SetTimeout(dwMilliseconds);
}
else
{
p->Destroy();
}
}
Irp->CheckErrorCode(err);
}
another possible solution set timer via CreateTimerQueueTimer and if timer expired - call CancellIoEx or close I/O handle from here. difference with event solution - if I/O will be completed before timer expired - the WaitOrTimerCallback callback function will be not automatically called. in case event - I/O subsystem set event when I/O complete (after intial pending status) and thanks to that (event in signal state) callback will be called. but in case timer - no way pass it to io request as parameter (I/O accept only event handle). as result we need save pointer to timer object by self and manually free it when I/O complete. so here will be 2 pointer to timer object - one from pool (saved by CreateTimerQueueTimer) and one from our object (socket) class (we need it for dereference object when I/O complete). this require reference counting on object which incapsulate timer too. from another side we can use timer not for single I/O operation but for several I/O (because it not direct bind to some I/O)

How to use lambda capture with lock?

In the code below, the member variable (match_room_list_) is a shared resource. So I used a mutex.
But locking confuses me.
Should I use lock or not in an inner lambda function?
void room::join_room(int user_id)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
std::shared_ptr<match_room> find_room = nullptr;
for (auto iter : match_room_list_)
{
if (false == iter.second->is_public_room())
{
continue;
}
if (true == iter.second->is_full())
{
continue;
}
find_room = iter.second;
break;
}
// Something
// async ( other thread call this lambda function )
// call database
database_manager::get_instance().join_room(find_room->get_room_id(), user_id, [=](bool success, std::string room_id, std::vector<int> user_id_list)
{
// How do you think I should using lock?
// std::lock_guard<std::recursive_mutex> lock(mutex_);
// shared resource
match_room_list_[room_id].join_user(user_id);
response_join_room_ntf(room_id, user_id_list);
}
}
If your lambda function will ever run on a different thread (and that's likely) then yes, you do need to lock it.
The only possible problem with doing so could be if it was called on the same thread from a function that had already locked the mutex. But that won't be an issue here since your mutex is a recursive one and a given thread can lock that as many times as it wants.
You may also want to look into conditions such as:
if (false == iter.second->is_public_room())
if (true == iter.second->is_full())
They would be far better written as:
if (! iter.second->is_public_room())
if (iter.second->is_full())

Implementing an asynchronous delay in C++/CX

I am trying to write a function which, given a number of seconds and a callback, runs the callback after the given number of seconds. The callback does not have to be on the same thread. The target language is C++/CX.
I tried using Windows::System::Threading::ThreadPoolTimer, but the result is a memory access exception. The issue appears to be that the callback implementation (in native C++) can't be accessed from the managed thread that the timer is running its callback on.
ref class TimerDoneCallback {
private:
function<void(void)> m_callback;
public:
void EventCallback(ThreadPoolTimer^ timer) {
m_callback(); // <-- memory exception here
}
TimerDoneCallback(function<void(void)> callback) : m_callback(callback) {}
};
void RealTimeDelayCall(const TimeSpan& duration, function<void(void)> callback) {
auto t = ref new TimerDoneCallback(callback);
auto e = ref new TimerElapsedHandler(t, &TimerDoneCallback::EventCallback);
ThreadPoolTimer::CreateTimer(e, duration);
}
void Test() {
RealTimeDelayCall(duration, [](){}); //after a delay, run 'do nothing'
}
I don't want to create a thread and sleep on it, because there may be many concurrent delays.
The TimerDoneCallback instance is not kept alive - delegates in C++/CX take weak references to the target object (to avoid circular references). You can override this behavior by using the extended overload of the delegate constructor:
auto e = ref new TimerElapsedHandler(t, &TimerDoneCallback::EventCallback, CallbackContext::Any, true);
The final bool parameter should be true for strong references, and false for weak references. (False is the default.)
You could also consider using the timer class in PPL agents to make a delayed callback: http://msdn.microsoft.com/en-us/library/hh873170(v=vs.110).aspx to avoid needing to use ThreadPoolTimer.

Emiting code with Exception support

I need to generate code at runtime that do the following:
auto v_cleanup = std::shared_ptr<void>(nullptr, [](void *){ cleanup(); });
//...
do_some_danger_thing();
//...
or C equivalent:
__try {
//...
do_some_danger_thing();
//...
} __finally {
cleanup();
}
The cleanup() function is guaranteed to be exception free, however do_some_danger_thing() may throw exception. This runtime code MUST not use stack, which means when calling do_some_danger_thing() the stack must in the same status as when we enter the runtime code, except that the return address set to the runtime code (the original value was saved to a "jmp" target, in order to return to the caller).
Because we are using dynamic machine code, the target platform is fixed to WIN32 on x86 CPU, the x64 CPU is not currently in focus.
To do this we have to process any exceptions. In WIN32 C++ exception is SEH based, so we have to due with it. The trouble is that we cannot find a way to do this and make it compatible with other code. We have tried a couple of solutions but none of them works, sometimes the user-installed exception handler was never called, sometimes the outer exception handlers was bypassed and we received an "unhandled exception" error.
UPDATE:
It seems to be the case that SEH exception handler chain supports code within the EXE image only. If the exception handler pointed to my generated code it will never been called. What I have to do is to create a static exception handler function stub, and then let it call the generated handler.
I am now have an implementation that is slightly different with the above. Actually, the pseudo code looks like (in C++11):
std::exception_ptr ex;
try {
//...
do_some_danger_things();
//...
} catch (...) {
ex = std::current_exception();
}
cleanup();
if(ex)rethrow_exception(ex);
This is not 100% the same as the above C equivalent because the call of cleanup() occurs before stack unwinding, usually this is not a problem, but the exact exception context could be lost.
I implemented an internal exception handler as the helper function, like the following:
_declspec(thread) void *real_handler = nullptr;
void **get_real_handler_addr(){
return &real_handler;
}
__declspec(naked) int exception_handler(...){
__asm {
call get_real_handler_addr;
mov eax, [eax];
jmp eax;
}
}
The trick here is that this handler must not be generated at runtime, so the stub has to find out where the "real" handler is. We use a thread local storage to do this.
Now the generated code will get the exception handler chain from FS:[0]. However, the chain must be stack based so I use the following code to replace the handler:
void **exception_chain;
__asm {
mov eax, fs:[0]
mov exception_chain, eax
}
//...
void *saved_handler = exception_chain[1];
exception_chain[1] = exception_handler;
*get_real_handler_addr() = generated_code->get_exception_handler();
The generated exception handler can then do the cleanup. However, in case that any current exception handler returns EXCEPTION_CONTINUE_SEARCH, the handler will be called twice. My strategy is just restore the original exception handler within the first call.

Resources