세마포어(semaphore)는 멀티스레드 환경에서 스레드들이 임계영역(Critical Section)을 동시에 실행하므로서 발생할 수 있는 공유자원의 오류를 방지하기 위한 방안이다.
세마포어를 이용한 동작은 하나의 스레드가 임계영역을 실행하기 전에 세마포어라는 변수를 보고서 임계영역을 실행할 수 있는 값일 경우에만 그 코드영역을 실행한다.
임계영역에 대한 실행 권한을 얻은 스레드는 임계영역을 실행하기 전에 세마포어의 값을 변경해 주어 자신이 사용하고 있음을 표시하여 준 다음에 실제로 임계영역을 실행한다.
임계영역의 실행이 끝나고 나서는 세마포어 변수 값을 재 설정하여 임계영역을 실행하고자 하는 다른 스레드가 임계영역을 실행할 수 있도록 뒤 처리도 해주어야 한다.
⊕ 추가 설명은 IOT 기술 메뉴에서 ROTS 커널 부분을 참조할 수 있다.
|
♦ 공유자원
◊ 여러 스레드들이 함께 값을 읽고 쓰고 할 수 있는 변수, 메모리 영역
◊ 여러 스레드들이 함께 이용하고 제어할 수 있는 장치, ex) Timer, GPIO, 프린터
♦ 임계영역(critical section)
공유자원을 액세스, 즉 읽고, 쓰고, 제어하는 코드영역
♦ mxos 에서 사용하고 있는 세마포어는 카운팅(counting) 세마포어이다.
|
1. semaphre 데모 구현내용
/* demo sem*/
static mos_semphr_id_t sem;
#define SEM_COUNT 10
semtx_thread |
새마포어를 획득한 다음 임계영역을 실행한다.
여기서 임계영역은 단순한 예로 로그메시지를 보내는 행위이다.
세마포어를 획득 못할 경우 무한정 대기할 수 없으므로 time-out은 1초로 설정하였다.
|
/* demo sem*/
static mos_semphr_id_t sem;
#define SEM_COUNT 10
static void semrx_thread(void *arg)
{
int fd;
struct timeval t;
fd_set rd;
int ret;
fd = mos_event_fd_new(sem);
app_log(“event fd: %d”, fd);
while(1) {
t.tv_sec = 10;
t.tv_usec = 0;
FD_ZERO(&rd);
FD_SET(fd, &rd);
select(fd+1, &rd, NULL, NULL, &t);
if (FD_ISSET(fd, &rd)) {
ret = mos_semphr_acquire(sem, 1);
app_log(“RX sem ret %d”, ret);
} else {
app_log(“RX sem timeout”);
break;
}
}
mos_event_fd_delete(fd);
app_log(“semrx_thread exit”);
mos_thread_delete(NULL);
}
static void semtx_thread(void *arg)
{
int i;
int ret;
for(i=0;i<20;i++) {
ret = mos_semphr_release(sem);
if (ret != kNoErr) {
app_log(“put sem %d fail %d”, i, ret);
}
}
mos_sleep(5);
for(i=0;i<5;i++) {
ret = mos_semphr_release(sem);
if (ret != kNoErr) {
app_log(“put sem %d fail”, i);
}
mos_sleep(1);
}
app_log(“semtx_thread exit”);
mos_thread_delete(NULL);
}
static void sem_demo(void)
{
mos_thread_id_t rt, tt;
app_log(“sem demo start”);
sem = mos_semphr_new(SEM_COUNT);
rt = mos_thread_new(5, “rx”, semrx_thread, 0x500, NULL);
tt = mos_thread_new(5, “tx”, semtx_thread, 0x500, NULL);
mos_thread_join(rt);
mos_thread_join(tt);
app_log(“sem demo end”);
mos_semphr_delete(sem);
mos_sleep(1);
}
{
//thread_demo();
// timer_demo();
sem_demo();
//queue_demo(1);
//queue_demo(2);
//queue_demo(3);
//queue_demo(4);
return 0;
}
2. semaphre 데모 동작확인
♦ VSC(Visual Studio Code)의 터미널에서 semaphore 데모를 컴파일하고 Flash 다운로드→ mxos make os@emw3080 download jtag=jlink
♦ EMW3080을 Reset하고 DBG 시리얼포트로 동작을 확인한 결과는 아래와 같다.