🌱 RTOS 09. Đồng bộ hóa giữa các Task với Counting Semaphore
Ở post trước chúng ta đã cùng tìm hiểu về Binary Semaphore, là một trong các cơ chế đồng bộ task trong RTOS. Thì binary semaphore dùng để quản lý đồng bộ 1 hoạt động duy nhất (ở post trước là ví dụ về hoạt động in ra của chiếc máy in). Vậy, với việc đồng bộ nhiều hoạt động, chúng ta cần một cơ chế khác tổng quát hơn, đó là Counting Semaphore.
Các nội dung chính
👉 Counting Semaphore là gì?
Counting Semaphore là một công cụ đồng bộ trong RTOS với khả năng:
- Theo dõi trạng thái của nhiều sự kiện.
- Quản lý số lượng tài nguyên chia sẻ (resource).
Counting Semaphore hoạt động giống như một biến đếm. Trạng thái của nó được biểu diễn bằng một giá trị nguyên không âm (thường trong khoảng 0 đến 255). Binary Semaphore thực chất là một trường hợp đặc biệt của Counting Semaphore, trong đó giá trị chỉ có thể là 0 hoặc 1.
👉 Công dụng của Counting Semaphore
Counting Semaphore thường được sử dụng với 2 mục đích:
➤ Counting Event - Đếm sự kiện
Counting Semaphore có thể hoạt động như một bộ đếm sự kiện:
- Mỗi lần có sự kiện xảy ra, semaphore sẽ được "give", tăng giá trị đếm.
- Mỗi lần sự kiện được xử lý, semaphore sẽ được "take", giảm giá trị đếm.
Ví dụ:
- Đếm số lần một tín hiệu từ phần cứng xảy ra.
- Đảm bảo mỗi tín hiệu chỉ được xử lý một lần.
Công thức:
Giá trị semaphore = Số sự kiện đã xảy ra - Số sự kiện đã được xử lý.
➤ Resource Management - Quản lý tài nguyên
Counting Semaphore giúp quản lý số lượng tài nguyên sẵn có:
- Khi một task Acquire (lấy) tài nguyên, giá trị semaphore giảm đi một đơn vị.
- Khi task Release (trả lại) tài nguyên, giá trị semaphore tăng lên.
Ví dụ:
- Quản lý 3 tài nguyên chung cho nhiều task.
- Nếu semaphore = 0, nghĩa là tất cả tài nguyên đang được sử dụng, task phải chờ.
👉 Ví dụ thực tế về Counting Semaphore
Giả sử chúng ta có:
- 3 task: A, B, và C (cùng độ ưu tiên, sử dụng round-robin scheduling).
- 2 tài nguyên được chia sẻ (Semaphore ban đầu = 2).
➥ Luồng hoạt động (chẳng hạn sử dụng các API freeRTOS)
- Task A chạy trước, gọi hàm osSemaphoreWait để kiểm tra tài nguyên:
- Vì Semaphore = 2 (tài nguyên có sẵn), task A Acquire một tài nguyên.
- Semaphore giảm còn 1.
- Hết lượt (time-slice), task A vào trạng thái ready, Scheduler chuyển quyền cho task B.
- Task B cũng gọi osSemaphoreWait và Acquire tài nguyên.
- Semaphore giảm còn 0.
- Task C bắt đầu chạy, gọi osSemaphoreWait để kiểm tra tài nguyên:
- Lúc này Semaphore = 0 (hết tài nguyên), task C bị chặn và chuyển sang trạng thái waiting.
- Scheduler quay lại task A hoặc task B.
- Khi một trong hai task gọi osSemaphoreRelease, tài nguyên được giải phóng, Semaphore tăng lên 1.
- Task C thoát khỏi trạng thái waiting, quay lại trạng thái ready, tiếp tục thực thi khi đến lượt.
Trên đây là hoạt động của Counting Semaphore, có rất nhiều trường hợp khác có thể xảy ra trên thực tế. Các bạn nên thực hành nó trong một bài toán thực tế để hiểu hơn về Semaphore cũng như RTOS.