I have three tasks, which shares a binary semaphore myBinarySemaphore. I'd like to know which task is currently having the binary semaphore. I could use a global variable to do this but does freeRTOS provide a method for this ?
Here's the code, I'm looking for a freeRTOS method to check which task has the binarySemaphore, in taskC for example. xTaskOwner is pure invention for example purpose. Thanks.
void taskA(void *pvParameters)
{
for(;;)
{
if(xSemaphoreTake(myBinarySemaphore, (TickType_t) 10) == pdTRUE)
{
xSemaphoreGive(myBinarySemaphore);
}
}
}
void taskB(void *pvParameters)
{
for(;;)
{
if(xSemaphoreTake(myBinarySemaphore, (TickType_t) 10) == pdTRUE)
{
xSemaphoreGive(myBinarySemaphore);
}
}
}
void taskC(void *pvParameters)
{
for(;;)
{
if(xTaskOwner(myBinarySemaphore) == taskA) // <== How to check with freeRTOS which task has the semaphore ?
printf("taskA has the semaphore");
else if (xTaskOwner(myBinarySemaphore) == taskB)
printf("taskB has the semaphore");
}
}
PS & EDIT: let's assume that taskC can be run simultaneously than the other tasks, because otherwise my example is wrong.
I would add a Queue with a simple message in it that says which task currently has the semaphore. Every time you take the semaphore, you overwrite the queue. In taskC you can do a xQueuePeek and see which task did the overwrite.
OR
You can use event flags to signal which task has the semaphore. Each task has its own flag on a share event group.
Related
I have implemented retries around some code in Jenkins pipeline.
retry(2) {
// code
}
Is there a way to identify when a retry has happened? Besides just manually checking console logs.
Would like to identify builds which have retried some flakey code and send notification.
I don't know of a way to know that inside the retry{ } block.
You could try a fairly generic solution (even maybe as a global var in a shared pipeline library), such as using a try catch block (since the retry will wait for an exception):
int retryAttempts = 0
retry(2) {
try {
if (retryAttempts>0) {
// a retry is occurring
// Do pre-retry logic, if needed
...
}
// Do stuff
.....
} catch (e) {
retryAttempts++ // a retry WILL occur
throw e // rethrow to trigger retry
}
}
if (retryAttempts>0) {
// a retry has occurred
// Do post-retry logic, if needed
...
}
#include "main.h"
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
void Task1(void *argument);
void Task2(void *argument);
void PrintMsg(char *data);
/* USER CODE BEGIN PFP */
SemaphoreHandle_t hMutex = NULL;
TaskHandle_t hTask1 = NULL;
TaskHandle_t hTask2 = NULL;
UART_HandleTypeDef huart2;
int main(void) {
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
xTaskCreate(Task1, "Task 1", configMINIMAL_STACK_SIZE, NULL, 2, &hTask1);
xTaskCreate(Task2, "Task 2", configMINIMAL_STACK_SIZE, NULL, 2, &hTask2);
/* USER CODE END 2 */
hMutex = xSemaphoreCreateMutex();
if (hMutex == NULL) {
PrintMsg("Mutex not created\r\n");
} else {
PrintMsg("Mutex created\r\n");
}
vTaskStartScheduler();
/* USER CODE BEGIN WHILE */
while (1) {
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void Task1(void *argument) {
/* USER CODE BEGIN 5 */
/* Infinite loop */
for (;;) {
if (xSemaphoreTake(hMutex,2000) == pdTRUE) {
PrintMsg("Shared Resource Start and Executing Task 1\r\n");
xSemaphoreGive(hMutex);
PrintMsg("Shared Resource End and Executing Task 1\r\n");
vTaskDelay(100);
} else {
PrintMsg("Task 1 Didn't get access to shared resource\r\n");
}
}
/* USER CODE END 5 */
}
void Task2(void *argument) {
/* USER CODE BEGIN 5 */
/* Infinite loop */
for (;;) {
if (xSemaphoreTake(hMutex,2000) == pdTRUE) {
PrintMsg("Shared Resource Start and Executing Task 2\r\n");
//xSemaphoreGive(hMutex);
PrintMsg("Shared Resource End and Executing Task 2\r\n");
vTaskDelay(100);
} else {
PrintMsg("Task 2 Didn't get access to shared resource\r\n");
}
}
/* USER CODE END 5 */
}
void PrintMsg(char *data) {
int i = 0;
while (*(data + i) != '\0') {
HAL_UART_Transmit(&huart2, (uint8_t*) &data[i], 1, 0xFF);
i++;
}
}
HW USED:STM32F446RE
When i run this code,I get output as follows
//Output Start
Mutex created
Shared Resource Start and Executing Task 1
Shared Resource End and Executing Task 1
Task 2 Didn't get access to shared resource
Task 1 DiTask 2 Didn't get access to shared resource
Task 1 Didn't get access to shared resource
Task 2 Didn't get access to shared resource
.
.
//Output End
Question1)
Considering Task1 was scheduled first as the priority of Task1 and 2 are same.
Task1 is executed correctly.
After this,Task2 is scheduled but was not able to take the mutex because of which i got output as "Task 2 Didn't get access to shared resource".Why is this so?
Question2 )
"Task 1 DiTask 2 Didn't get access to shared resource" in this line,it seems that Task1 was exceuting but it got preempted by Task2 which should have not happened as both the Tasks have same priority??
Q1: The likely explanation here is that you're being fooled by competing tasks overwriting each others' buffered UART output. UART is slow, task switching is fast :)
After Task1 prints "Shared Resource Start and Executing Task 1" and releases the mutex for the first time, scheduler immediately switches to Task2 (maybe because Task1 has used up its time slot?). Task2 grabs the mutex, quickly spits both of its messages into UART buffer and enters sleep for 100 ticks. The scheduler immediately switches back to Task1, but unfortunately the buffered messages from Task2 haven't hit the UART output yet. UART buffer gets overwritten by the message "Shared Resource End and Executing Task 1" before a single byte of Task2-s messages is printed.
After that the entire process stalls because you haven't released the mutex in Task2.
Q2: tasks with equal priorities get preempted by each other when the scheduler decides so (usually when they enter sleep or have exhausted their time slot)
I would recommend this tutorial/book, chapter 3 for a great explanation of how tasks work.
USART is a resource, so it can't be shared by two tasks without a sync mechanism, like a mutex. Your usage of PrintMsg() violates this rule.
The scheduler is run at configTICK_RATE_HZ frequency. If configUSE_TIME_SLICING is 1 (or undefined), the scheduler switches between equal priority tasks. If you don't want this default behavior, set configUSE_TIME_SLICING to 0.
Keep it in mind that your configTICK_RATE_HZ setting of 1000 gives at most ~1 ms runtime to each task, unless there are no other tasks ready to run. Higher priority tasks can also preempt it before that 1 ms passes. With 115200 baud rate, you can send ~10 bytes or so in this ~1 ms time period.
I have created two processes in Contiki. In the first process, I want to keep calling a function after a certain amount of time for this I have set an event timer. But while waiting for the event for the expiration of the timer the control of execution is transferred to the second process.
Code:
PROCESS(hello_world_process, "Hello world process");
PROCESS(hello_world_process2, "Hello world process2");
AUTOSTART_PROCESSES(&hello_world_process,&hello_world_process2);
#define TIMEOUT (CLOCK_SECOND / 4)
static struct etimer timer;
void setFlag(void)
{
int i;
i = random_rand();
if (i>0 && i<32767)
{
printf("Setting flag\n");
flag =1;
}
}
PROCESS_THREAD(hello_world_process, ev, data)
{
PROCESS_BEGIN();
printf("1st process started\n");
do
{
etimer_set(&timer, TIMEOUT);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
setFlag();
} while(!flag);
printf("1st process completed\n");
PROCESS_END();
}
PROCESS_THREAD(hello_world_process2, ev, data)
{
printf("2nd process started\n");
PROCESS_BEGIN();
printf("2nd process completed\n");
PROCESS_END();
}
Output:
Contiki-list-1532-g2ca33d4 started with IPV6, RPL
Rime started with address 1.2.3.4.5.6.7.8
MAC nullmac RDC nullrdc NETWORK sicslowpan
Tentative link-local IPv6 address fe80:0000:0000:0000:0302:0304:0506:0708
1st process started
2nd process started
2nd process completed
Setting flag
1st process completed
I want that second process should only be executed once the first process is executed completely i.e. while waiting for the event, the control should not get transferred to the second process.
Try this:
AUTOSTART_PROCESSES(&hello_world_process);
// ...
PROCESS_THREAD(hello_world_process, ev, data)
{
PROCESS_BEGIN();
printf("1st process started\n");
do
{
etimer_set(&timer, TIMEOUT);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
setFlag();
} while(!flag);
printf("1st process completed\n");
process_start(&hello_world_process2, NULL); // start the second process
PROCESS_END();
}
See https://github.com/contiki-os/contiki/wiki/Processes.
Also, don't put any executable code before PROCESS_BEGIN()! You will not get a warning, but the result may not be what you expect, as that code will be executed every time when the process is resumed.
I need custom behavior for the timeout function. For example, when I use:
timeout(time: 10, unit: 'MINUTES') {
doSomeStuff()
}
it terminates the doSomeStuff() function.
What I want to achieve is not to terminate the execution of the function, but to call another function every 10 minutes until doSomeStuff() is done with executing.
I can't use the Build-timeout Plugin from Jenkins since I need to apply this behavior to pipelines.
Any help would be appreciated.
In case anyone else has the same issue: After some research, the only way that came to my mind to solve my problem was to modify the notification plugin for the jenkins pipeline, in a way to add a new field that would contain value of time (in minutes) to delay the invoking of the url. In the code itself, where the url was invoked, i put those lines in a new thread and let that thread sleep for the needed amount of time before executing the remaining code. Something like this:
#Override
public void onStarted(final Run r, final TaskListener listener) {
HudsonNotificationProperty property = (HudsonNotificationProperty) r.getParent().getProperty(HudsonNotificationProperty.class);
int invokeUrlTimeout = 0;
if (property != null && !property.getEndpoints().isEmpty()){
invokeUrlTimeout = property.getEndpoints().get(0).getInvokeUrlTimeout();
}
int finalInvokeUrlTimeout = invokeUrlTimeout;
new Thread(() -> {
sleep(finalInvokeUrlTimeout * 60 * 1000);
Executor e = r.getExecutor();
Phase.QUEUED.handle(r, TaskListener.NULL, e != null ? System.currentTimeMillis() - e.getTimeSpentInQueue() : 0L);
Phase.STARTED.handle(r, listener, r.getTimeInMillis());
}).start();
}
Maybe not the best solution but it works for me, and I hope it helps other people too.
I wrote this code to spin off a large number of WebClients (limited by reactor.ipc.netty.workerCount), start the Mono immediately, and wait for the all Monos to complete:
List<Mono<List<MetricDataModel>>> monos = new ArrayList<>(metricConfigs.size());
for (MetricConfig metricConfig : metricConfigs) {
try {
monos.add(extractMetrics.queryMetricData(metricConfig)
.doOnSuccess(result -> {
metricDataList.addAll(result);
})
.cache());
} catch (Exception e) {
}
}
Mono.when(monos)
.doFinally(onFinally -> {
Map<String, Date> latestMap;
try {
latestMap = extractInsights.queryInsights();
Transform transform = new Transform(copierConfig.getEventType());
ArrayList<Event> eventList = transform.toEvents(latestMap, metricDataList);
} catch (Exception e) {
log.error("copy: mono: when: {}", e.getMessage(), e);
}
})
.block();
It 'works', that is the results are as expected.
Two questions:
Is this correct? Does cache() result in the when waiting for all Monos to complete?
Is it efficient? Is there a way to make this faster?
Thanks.
You should try as much as possible to:
use Reactor operators and compose a single reactive chain
avoid using doOn* operators for something other than side-effects (like logging)
avoid shared state
Your code could look a bit more like
List<MetricConfig> metricConfigs = //...
Mono<List<MetricDataModel>> data = Flux.fromIterable(metricConfigs)
.flatMap(config -> extractMetrics.queryMetricData(config))
.collectList();
Also, the cache() operator does not wait the completion of the stream (that's actually then()'s job).