Errno when returning from function

alexkushnir wrote on Wednesday, November 06, 2019:

Hello.
I am using Zynq-7000 with Xilinx SDK 2018.2, which provides FreeRTOS 10.0.0 BSP alongside with lwIP 2.02 in sockets mode.

When I am trying to perform a connect to a non-existent server, I get return value of -1 (which is OK), and errno should be set.

When debugging, I do see the errno true value in expressions debug view, but when trying to print the errno, I see a value of 0.

I have configNUM_THREAD_LOCAL_STORAGE_POINTERS set to 5 and configUSE_NEWLIB_REENTRANT set to 1.

Can I anyhow retrieve the value of errno in my application code?

Thanks,
Alex

heinbali01 wrote on Wednesday, November 06, 2019:

Hello Alex,

As far as I know, the (magic) variable errno is not being used in the FreeRTOS kernel or its libraries. The implementation is too specific for the compiler used.

Many functions in FreeRTOS+TCP will return a value as follows:

	BaseType_t rc = FreeRTOS_recv( xSocket, pcBuffer, sizeof( pcBuffer ), 0 );
	if( rc > 0)
	{
		/* Bytes have been received. */
	}
	else if ( rc < 0 )
	{
		printf("Errno %d has occurred\n", -rc );
	}
	else
	{
		/* No bytes were received. */
	}

Within FreeRTOS+FAT, a task-local variable is used in which errno is stored. It can be inspected with this function:

int stdioGET_ERRNO( void )
{
void *pvResult;

	pvResult = pvTaskGetThreadLocalStoragePointer( ( TaskHandle_t )NULL, ffconfigCWD_THREAD_LOCAL_INDEX );
	return ( int ) pvResult;
}

FreeRTOS+FAT uses 3 thread-local variables.

alexkushnir wrote on Wednesday, November 06, 2019:

Got it, thanks :frowning:

So errno is a design problem in the C/C++ library; we should all be aware of this. I have used other RTOSs where we had to modify the context save/restore code to preserve errno as though it were a register in the machine. It is really the same problem as using floating point: you have additional context that needs to be preserved. Just as with floating point, not every task uses errno, and so whether to save it is a per task consideration, but to always save it will only increase task swap time a little, and add to stack usage a little. Depending on how critical swap time and stack size are, you might just opt to always save errno (and ditto for floating point registers, but the overhead is higher here).

The question becomes, is there already an existing modification to preserve errno on a per task basis. I have not gotten into the details of FreeRTOS’s implementation of per task variables yet, so maybe this is a moot question.

Some library, like newlib, use a single “reentrancy” pointer to a structure which holds all the library data that should switch between threads to make the standard library thread safe, including errno. FreeRTOS can automatically change that pointer to the value stored in the Task Control Block.

The question becomes, is there already an existing modification to preserve errno on a per task basis

I answered that question in my earlier response here above.

As for the FPU registers, they can be stored on the task stack, depending on your configuration.