//untuk skenario aplikasi mutex + change priority task3
//#define SCENARIO1
//untuk skenario aplikasi mutex tanpa change priority task3
//#define SCENARIO2
//untuk skenario tanpa mutex (menggunakan smaphore binary)
#define SCENARIO3
//untuk skenario tanpa semaphore/ kasus non-reentrant
//#define SCENARIO4
// Define pins
#define TASK1_PIN 19
#define TASK2_PIN 18
#define TASK3_PIN 5
TaskHandle_t task3Handle = NULL;
TaskHandle_t task2Handle = NULL;
TaskHandle_t task1Handle = NULL;
SemaphoreHandle_t mutex;
//Non-reentrant Function
int sharedVar = 0; // Variabel global yang digunakan bersama
void unsafeIncrement(int countMax, int delayVar, String taskSelect) {
for (int i = 0; i < countMax; i++) {
sharedVar++; // Ini tidak aman jika dipanggil dari beberapa tugas
Serial.print(taskSelect);
Serial.print(" unsafe sedang bekerja...sharedVar: ");
Serial.println(sharedVar);
if (taskSelect == "Task1"){
digitalWrite(TASK1_PIN, HIGH);
digitalWrite(TASK1_PIN, LOW);
}else if (taskSelect == "Task3"){
digitalWrite(TASK3_PIN, HIGH);
digitalWrite(TASK3_PIN, LOW);
}
}
}
//Reentrant Function
int safeIncrement(int countMax, int delayVar,String taskSelect) {
int counterVar = 0;
for (int i = 0; i < countMax; i++) {
counterVar++; // Ini tidak aman jika dipanggil dari beberapa tugas
Serial.print(taskSelect);
Serial.print(" safe sedang bekerja...counterVar: ");
Serial.println(counterVar);
if (taskSelect == "Task1"){
digitalWrite(TASK1_PIN, HIGH);
digitalWrite(TASK1_PIN, LOW);
}
else if (taskSelect == "Task2"){
digitalWrite(TASK2_PIN, HIGH);
digitalWrite(TASK2_PIN, LOW);
}
}
return counterVar;
}
void doTask3UnsafeIncrement(){
sharedVar = 0;
Serial.print("Task3 start unsafe, sharedVar: ");
Serial.println(sharedVar);
// Simulasi pekerjaan yang memakan waktu lama
unsafeIncrement(90, 500,"Task3");
Serial.print("Task3 finish unsafe, sharedVar: ");
Serial.println(sharedVar);
}
void doTask2SafeIncrement(){
Serial.println("midPriorityTask2 start safeIncrement ");
// Perform some task
int value = safeIncrement(60,500,"Task2");
Serial.print("Task2 finish safe, value: ");
Serial.println(value);
}
void doTask1UnsafeIncrement(){
sharedVar = 0;
Serial.print("Task1 start unsafe, sharedVar: ");
Serial.println(sharedVar);
// Simulasi pekerjaan yang memakan waktu lama
unsafeIncrement(30, 500,"Task1");
Serial.print("Task1 finish unsafe, sharedVar: ");
Serial.println(sharedVar);
}
void doTask1SafeIncrement(){
Serial.println("Task1 start safeIncrement ");
// Perform some task
int value = safeIncrement(30,500,"Task1");
Serial.print("Task1 finish safe, value: ");
Serial.println(value);
}
void lowPriorityTask3(void *parameter) {
while (1) {
#ifdef SCENARIO4
doTask3UnsafeIncrement();
#else
Serial.println("LowPriorityTask3 mencoba mengambil mutex.");
// Mengunci mutex
if (xSemaphoreTake(mutex, portMAX_DELAY)) {
Serial.println("LowPriorityTask3 mengunci mutex.");
#ifdef SCENARIO1
Serial.println("Task3 taskPriority:3");
vTaskPrioritySet(task3Handle, 3);
#endif
doTask3UnsafeIncrement();
Serial.println("LowPriorityTask3 melepaskan mutex.");
xSemaphoreGive(mutex); // Melepaskan mutex
#ifdef SCENARIO1
Serial.println("Task3 taskPriority:1");
vTaskPrioritySet(task3Handle, 1);
#endif
}
#endif
}
}
void midPriorityTask2(void *pvParameters) {
while (1) {
//vTaskDelay(3 / portTICK_PERIOD_MS); // Memberikan waktu agar lowPriorityTask mendapatkan mutex terlebih dahulu
doTask2SafeIncrement();
}
}
void highPriorityTask1(void *parameter) {
while (1) {
vTaskDelay(250 / portTICK_PERIOD_MS); // Memberikan waktu agar lowPriorityTask mendapatkan mutex terlebih dahulu
#ifdef SCENARIO4
doTask1UnsafeIncrement();
doTask1SafeIncrement();
#else
Serial.println("HighPriorityTask1 mencoba mengambil mutex.");
// Mencoba mengunci mutex
if (xSemaphoreTake(mutex, portMAX_DELAY)) {
Serial.println("HighPriorityTask1 berhasil mendapatkan mutex.");
doTask1UnsafeIncrement();
doTask1SafeIncrement();
Serial.println("HighPriorityTask1 melepaskan mutex.");
xSemaphoreGive(mutex); // Melepaskan mutex
}
#endif
}
}
void setup() {
Serial.begin(115200);
// Initialize LED pins
pinMode(TASK1_PIN, OUTPUT);
pinMode(TASK2_PIN, OUTPUT);
pinMode(TASK3_PIN, OUTPUT);
digitalWrite(TASK1_PIN, LOW);
digitalWrite(TASK2_PIN, LOW);
digitalWrite(TASK3_PIN, LOW);
#if defined(SCENARIO1)
Serial.println("Scenario1 is Running...");
#elif defined(SCENARIO2)
Serial.println("Scenario2 is Running...");
#elif defined(SCENARIO3)
Serial.println("Scenario3 is Running...");
#elif defined(SCENARIO4)
Serial.println("Scenario4 is Running...");
#endif
// Membuat mutex
#ifdef SCENARIO3
mutex = xSemaphoreCreateBinary();
#else
mutex = xSemaphoreCreateMutex();
#endif
// Initially, give the semaphore so tasks can take it
xSemaphoreGive(mutex);
#ifdef SCENARIO4
xTaskCreate(lowPriorityTask3, "Low Priority Task", 2000, NULL, 1, &task3Handle);
xTaskCreate(midPriorityTask2, "Mid Priority Task", 2000, NULL, 1, &task2Handle);
xTaskCreate(highPriorityTask1, "High Priority Task", 2000, NULL, 1, &task1Handle);
#else
// Membuat task dengan prioritas rendah (prioritas 1)
xTaskCreate(lowPriorityTask3, "Low Priority Task", 2000, NULL, 1, &task3Handle);
// Membuat task dengan prioritas sedang (prioritas 2)
xTaskCreate(midPriorityTask2, "Mid Priority Task", 2000, NULL, 2, &task2Handle);
// Membuat task dengan prioritas tinggi (prioritas 3)
xTaskCreate(highPriorityTask1, "High Priority Task", 2000, NULL, 3, &task1Handle);
#endif
}
void loop() {
// Loop kosong
delay(10);
}