Should I use xSemaphoreGiveFromISR() or xSemaphoreGive() in STM32 HAL interrupt callbacks? - freertos

I've implemented a fault task in the FreeRTOS which is taking a binary semaphore used as a fault flag. That fault flag is triggered by the STM32 HAL error callback functions, such as HAL_I2C_ErrorCallback or HAL_UART_ErrorCallback. If an error occurs, error callbacks functions will call signalFault() function, which will raise the fault flag by giving the binary semaphore.
My question is: is my signalFault() function treated as an interrupt service routine (ISR) or not, because it is being called in the HAL ISR error callbacks? Do I need to call xSemaphoreGiveFromISR() or xSemaphoreGive() function in signalFault() function to raise the fault flag?

If you do not trust us then simple check if you are in the interrupt. It will be 100% safe.
int isInISR( void )
{
return ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK );
}
and in your code:
if(isInISR()) xSemaphoreGiveFromISR(...);
else xSemaphoreGive(...);

Sure, you should use xSemaphoreGiveFromISR if the calling context is an ISR.
A function called from an ISR is still part of the ISR.

Related

How to restore runOn Scheduler used in previous operator?

Folks, is it possible to obtain currently used Scheduler within an operator?
The problem that I have is that Mono.fromFuture() is being executed on a native thread (AWS CRT Http Client in my case). As result all subsequent operators are also executed on that thread. And later code wants to obtain class loader context that is obviously null. I realize that I can call .publishOn(originalScheduler) after .fromFuture() but I don't know what scheduler is used to materialize Mono returned by my function.
Is there elegant way to deal with this?
fun myFunction(): Mono<String> {
return Mono.just("example")
.flatMap { value ->
Mono.fromFuture {
// invocation of 3rd party library that executes Future on the thread created in native code.
}
}
.map {
val resource = Thread.currentThread().getContextClassLoader().getResources("META-INF/services/blah_blah");
// NullPointerException because Thread.currentThread().getContextClassLoader() returns NULL
resource.asSequence().first().toString()
}
}
It is not possible, because there's no guarantee that there is a Scheduler at all.
The place where the subscription is made and the data starts flowing could simply be a Thread. There is no mechanism in Java that allows an external actor to submit a task to an arbitrary thread (you have to provide the Runnable at Thread construction).
So no, there's no way of "returning to the previous Scheduler".
Usually, this shouldn't be an issue at all. If your your code is reactive it should also be non-blocking and thus able to "share" whichever thread it currently runs on with other computations.
If your code is blocking, it should off-load the work to a blocking-compatible Scheduler anyway, which you should explicitly chose. Typically: publishOn(Schedulers.boundedElastic()). This is also true for CPU-intensive tasks btw.

AcceptEx() synchronous completion?

I am using IO completion ports and AcceptEx() whilst learning about servers, and am studying Len Holgate's free server framework to do this. He has the following code:
// Basically calls AcceptEx() via a previously obtained function pointer
if (!CMSWinSock::AcceptEx(
m_listeningSocket,
pSocket->m_socket,
reinterpret_cast<void*>(const_cast<BYTE*>(pBuffer->GetBuffer())),
bufferSize,
sizeOfAddress,
sizeOfAddress,
&bytesReceived,
pBuffer))
{
const DWORD lastError = ::WSAGetLastError();
if (ERROR_IO_PENDING != lastError)
{
Output(_T("CSocketServerEx::Accept() - AcceptEx: ") + GetLastErrorMessage(lastError));
pSocket->Release();
pBuffer->Release();
}
}
else
{
// Accept completed synchronously. We need to marshal the data recieved over to the
// worker thread ourselves...
m_iocp.PostStatus((ULONG_PTR)m_listeningSocket, bytesReceived, pBuffer);
}
I am confused about the "Accept completed synchronously" else-case. I have tried many times to get this code path to be hit (by pausing the code before I issue the AcceptEx, connecting, then resuming the code), but whenever I try the call always fails with ERROR_IO_PENDING and I get my notification packet. Furthermore, I have read this MS knowledgebase article (which I may have misinterpreted) which states
Additionally, if a Winsock2 I/O call returns SUCCESS or IO_PENDING, it
is guaranteed that a completion packet will be queued to the IOCP when
the I/O completes
However, I am thinking this doesn't apply to AcceptEx() because the dox for AcceptEx() states of the parameter lpdwBytesReceived
This parameter is set only if the operation completes synchronously.
So it seems it can complete synchronously...can someone tell me how AcceptEx() can complete synchronously (i.e. how I can replicate it in my server?)
Additionally, if a Winsock2 I/O call returns SUCCESS or ERROR_IO_PENDING, it
is guaranteed that a completion packet will be queued to the IOCP when
the I/O completes
this is apply for any I/O request if completion port is associated with the file. but begin from windows vista this also depend from notification mode set for a file handle.
but need first begin look from native view.
by default, if FILE_SKIP_COMPLETION_PORT_ON_SUCCESS not set, exist 3 case by returned NTSTATUS status :
NT_SUCCESS(status) or status >= 0 - will be completion
NT_ERROR(status) or status >= 0xc0000000 - will be no completion
NT_WARNING(status) or status < 0xc0000000 - unclear - if this
error from I/O manager (say - STATUS_DATATYPE_MISALIGNMENT - will
be no completion). if this error from driver (say
STATUS_NO_MORE_FILES - will be completion).
the win32 layer usually separate check for STATUS_PENDING and return ERROR_IO_PENDING in this case (but exist and exceptions, like ReadDirectoryChangesW). otherwise in case NT_ERROR(status) api return fail and set error code. otherwise return success. visible that case NT_WARNING(status) considered as success, but in this case, if error from I/O manager, will be no completion. I/O usually return errors from NT_ERROR(status) range, if parameters is incorrect. only case which i know (for asynchronous api) - STATUS_DATATYPE_MISALIGNMENT can be returned in case wrong aligned buffers, when I/O manager have special knowledge about buffer align. in NtNotifyChangeDirectoryFile
(ReadDirectoryChangesW for win32) or NtQueryDirectoryFile (no corresponded win32 api). so only case which i know when will be no completion, when win32 return success - call ReadDirectoryChangesW with unaligned lpBuffer (it must be DWORD-aligned ) - in this case I/O manager just return STATUS_DATATYPE_MISALIGNMENT but win32 layer interpret this as success code and return true. but will be no completion in this case. however this is rarely case and you probably need use wrong align structures for this. so in general yes:
by default if I/O call returns SUCCESS or ERROR_IO_PENDING will be queued a completion entry to the port. (with special exception case which i try describe)
if we set FILE_SKIP_COMPLETION_PORT_ON_SUCCESS on file object (note this is per file object but not per file handle - documentation not exactly here) all become much more simply and efficient - completion entry will be queue to the port - when and only when I/O request return STATUS_PENDING. ERROR_IO_PENDING from win32 view (except ReadDirectoryChangesW (maybe some else api ?) where win32 layer simply lost return code information)
However, I am thinking this doesn't apply to AcceptEx()
you mistake. this, how i say, apply to any io request. "This parameter is set only if the operation completes synchronously." - and so what ?
if look to code snippet, clear visible that code assume - in case AcceptEx completed synchronous and no error occurs - will be no io completion. or SetFileCompletionNotificationModes(m_listeningSocket, FILE_SKIP_COMPLETION_PORT_ON_SUCCESS) called or code is wrong - will be io completion in this case and not need m_iocp.PostStatus - this is fatal error will be. however i doubt that code used FILE_SKIP_COMPLETION_PORT_ON_SUCCESS - so it wrong. but error never raised because driver side implementation of AcceptEx (underlining ioctl) never return STATUS_SUCCESS: it check parameters - if it wrong - just return some error, otherwise always return STATUS_PENDING. as result, for asynchronous sockets AcceptEx never return true and code never jump to error else case. but anyway code is wrong. also i think design not the best - in case we determinate will be no completion - better just direct call completion routine with returned error code instead Release() (this will be done in completion routine) or PostStatus - for what post ?! - call direct.
how AcceptEx() can complete synchronously
very easy - if m_listeningSocket is handle to synchronous file object. however in this case you can not bind IOCP to file (it can be bind only in case asynchronous file object).
about lpdwBytesReceived parameter - system copy Information member of IO_STATUS_BLOCK or if want OVERLAPPED.InternalHigh, in case operation is completed just. in case pending returned - this data simply not ready and not filled. you got actual number of bytes returned by io in completion

`TWaitResult.wrIOCompletion` is undocumented. Can anyone provide usage tips?

TWaitResult.wrIOCompletion is undocumented. Does anyone know when and how it's used?
It is used only on Windows, by THandleObject (and its descendants TEvent, TSimpleEvent, TMutex, and TSemaphore) in the following methods:
THandleObject.WaitFor(). When the object is created with UseCOMWait set to True, the wait is handled by the Win32 API CoWaitForMultipleHandles() function, where wrIOCompletion is returned if RPC_S_CALLPENDING is reported. When UseCOMWait is False instead, the wait is handled by the Win32 API WaitForMultipleObjectsEx() function 1.
THandleObject.WaitForMultiple(). wrIOCompletion is returned if the UseCOMWait parameter is True and CoWaitForMultipleHandles() reports RPC_S_CALLPENDING, or when UseCOMWait is False and WaitForMultipleObjectsEx() reports WAIT_IO_COMPLETION.
Either way, the meaning is the same 2:
The wait was ended by one or more user-mode asynchronous procedure calls (APC) queued to the thread
Refer to MSDN for more details about APC queues:
Asynchronous Procedure Calls
Alertable I/O
In a nutshell, an Alertable I/O or APC operation allows a user-defined operation/function to be queued in a thread so it will be called by the thread when in a safe state to make such a call. wrIOCompletion indicates that the thread that is calling WaitFor/Multiple() had to stop waiting before the timeout elapsed so it could execute one or more queued Alertable/APC functions. The thread will have to call WaitFor/Multiple() again to finish waiting on its desired object(s) 3.
1: THandleObject.WaitFor() does not currently handle WAIT_IO_COMPLETION (bug?) when UseCOMWait is false. It will return wrError instead (and the value of the THandleObject.LastError property will not be assigned!)
2: the CoWaitForMultipleHandles() documentation describes RPC_S_CALLPENDING as "The timeout period elapsed before the required handle or handles were signaled", but that would be a more appropriate description for RPC_E_TIMEOUT instead. (documentation error?)
3: in practice wrIOCompletion should never happen, because CoWaitForMultipleHandles() is never called with the COWAIT_ALERTABLE flag:
If the COWAIT_ALERTABLE flag is set in dwFlags, a value of WAIT_IO_COMPLETION indicates the wait was ended by one or more user-mode asynchronous procedure calls (APC) queued to the thread.
And WaitForMultipleObjectsEx() is never called with its bAlertable parameter set to True:
bAlertable [in]
If this parameter is TRUE and the thread is in the waiting state, the function returns when the system queues an I/O completion routine or APC, and the thread runs the routine or function. Otherwise, the function does not return and the completion routine or APC function is not executed.
These conditions are needed to trigger the wrIOCompletion result. I have opened a bug report for this in Quality Portal:
RSP-14047 THandleObject never returns wrIOCompletion.

How to get current signal handler on iOS?

Hi i need to get current signal handler that was set with this method:
signal(SIGSEGV, handler);
How to do that?
Unfortunately, the C standard does not foresee reading the current value of the handler.
But fortunately signal() returns the previous value when you change the handler. Hence with a slight risk you could do:
typedef void (*sighandler_t)(int); /* for convenience */
sighandler_t current_handler;
current_handler = signal(SIGSEGV, SIG_IGN); /* (1) */
signal (SIGSERV, current_handler); /* (2) */
There are two risks:
There could be a (very unliklely) error causing signal() to return SIG_ERR. You would then lose the current handler for good! According to iOS man page above, and based on the signal value you're interested in, the conditions for errors are not met.
If a SIGSEGV would be raised between (1) and (2) you would not intercept it. However, looking at the two statements, they are unlikely to trigger a segmentation violation (SIGSEGV)

how do the registers get saved when a process gets interrupted?

this has been bugging me all day. When a program sets itself up to call a function when it receives a certain interrupt, I know that the registers are pushed onto the stack when the program is interrupted, but what I can't figure out is: how do the registers get off the stack? I know that the compiler doesn't know if the function is an interrupt handler, and it can't know how many arguments the interrupt gave to the function. So how on earth does it get the registers off?
It depends on the compiler, the OS and the CPU.
For low level embedded stuff, where an ISR may be called directly in response to an interrupt, the compiler will typically have some extension to the language (usually C or C++) that flags a given routine as an ISR, and registers will be saved and restored at the beginning and end of such a routine. [1]
For common desktop/server OSs though there is normally a level of abstraction between interrupts and user code - interrupts are normally handled first by some kernel code before being passed to a user routine, in which case the kernel code takes care of saving and restoring registers, and there is nothing special about the user-supplied ISR.
[1] E.g. Keil 8051 C compiler:
void Some_ISR(void) interrupt 0 // this routine will get called in response to interrupt 0
{
// compiler generates preamble to save registers
// ISR code goes here
// compiler generates code to restore registers and
// do any other special end-of-ISR stuff
}

Resources