xTaskNotifyWait Bit Clearing

Hi,
I’m using FreeRTOS v10.0.1 on a Cortex-M class device with tasks that use notifications to trigger event loops (configUSE_TASK_NOTIFICATIONS == 1, tasks block via xTaskNotifyWait). Most notifications are sent via a direct-to-task notification inside of an ISR.

I’m trying to add handling for a catastrophic-error type event where I want to discard most bits (events) that may have become pending in ulNotifiedValue during this iteration of the event loop.

It looked like at first glance, based on the header documentation, that ulBitsToClearOnEntry did what I needed here – the documentation begins: “Bits that are set in ulBitsToClearOnEntry value will be cleared in the calling task’s notification value before the task checks to see if any notifications are pending, and optionally blocks if no notifications are pending”.

However, checking the kernel code, it looks like the bits in ulBitsToClearOnEntry are actually cleared if and only if ucNotifyState != taskNOTIFICATION_RECEIVED – in this case, if an event arrived that I wanted to toss out during the event loop processing, ulBitsToClearOnEntry would not be applied.

Is this just a discrepancy in the documentation, or was the intention that ulBitsToClearOnEntry would be applied before the notification state check? Any clarification is appreciated – thank you!

Looking at the implementation is appears as if ulBitsToClearOnEntry is only applied if a notification is not already pending to ensure you don’t clear bits that
have not been read yet. That would seem logical to prevent a race, so it appears the documentation is wrong.

I note there is a separate function for clearing the notification state but not for clearing the notification bits. Would it be helpful to add a function such
as the following?

uint32_t ulTaskNotifyBitsClear( TaskHandle_t xTask, uint32_t ulBitsToClear )
{
TCB_t *pxTCB;
uint32_t ulReturn;

	/* If null is passed in here then it is the calling task that is having
	its notification state cleared. */
	pxTCB = prvGetTCBFromHandle( xTask );

	taskENTER_CRITICAL();
	{
		/* Return the notification as it was before the bits were cleared,
		then clear the bit mask. */
		ulReturn = pxCurrentTCB->ulNotifiedValue;
		pxCurrentTCB->ulNotifiedValue &= ~ulBitsToClearOnEntry;
	}
	taskEXIT_CRITICAL();

	return xReturn;
}

Hi Richard,

There may be a use case for ulTaskNotifyBitsClear and I certainly think it would improve the overall coverage of the task APIs. I think in this particular use case it still leaves us with a bit of a race condition where, if called before xTaskNotifyWait, there is still the possibility of an event arriving between BitsClear’s exit critical and notifyWait’s enter critical.

In my use case, the workaround isn’t too complicated - I can locally store the word that I had intended to pass to ulBitsToClearOnEntry and clear those bits from the writeback value of pulNotificationValue.

I am still a little unclear on the use case for the conditional clear of ulBitsToClearOnEntry – from the point of view of the task, it’s not really known whether an event has arrived or not, so it seems difficult to rely on the value passed in that parameter? It may just be the requirement there differs too much from my usage to make sense to me at the moment.

Thanks!