세마포어의 버그 발견?

---s_test.c(세마포 함수부분)----------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define _UW_SOURCE
int d_sem_opr(semid, sem_num, flag)
int semid; /* semid */
int flag; /* 1LOCK, 2UNLOCK */
{
int num;
pid_t sempid;
union semun {
int val;
struct semid_ds * buf;
ushort * array;
} sval;
/*----- */
static struct sembuf op_lock[1] = {
0, -1, SEM_UNDO /* then increment sem#0 by 1 */
};
static struct sembuf op_unlock[1] = {
0, 1, (IPC_NOWAIT|SEM_UNDO)
/* decrement sem#0 by 1 (sets it to 0) */
};
sempid = semctl(semid, sem_num, GETPID, sval);
if(sempid == 0) {
sval.val = 1;
semctl(semid, sem_num, SETVAL, sval);
}
op_lock[0].sem_num = sem_num;
op_unlock[0].sem_num = sem_num;
/*===== LOCK =====*/
if (flag == 1)
{
if (semop (semid, &op_lock[0], 1) < 0 && errno != 0) {
#ifdef _LIB_DEBUG
printf ("[d_sem_opr] semop SEND LOCK \n");
#endif
return(-1);
}
/*===== UNLOCK =====*/
} else if (flag == 2) {
if (semop (semid, &op_unlock[0], 1) < 0 && errno != 0) {
#ifdef _LIB_DEBUG
printf ("[d_sem_opr] semop UNLOCK \n");
#endif
return(-1);
}
}
return(0);
}
--------------end of s_test.c------------------------------------
--------------semtest.c------------------------------------------
#include
#include
#include
#include
#define LOCK(a) d_sem_opr(a, 0, 1)
#define UNLOCK(a) d_sem_opr(a, 0, 2)
#define SND_LOCK(a) d_sem_opr(a, 1, 1)
#define SND_UNLOCK(a) d_sem_opr(a, 1, 2)
int sem_test(int semid)
{
char ch;
puts("before SND_LOCK");
SND_LOCK(semid);
puts("after SND_LOCK");
LOCK(semid);
puts("after LOCK");
fflush(stdin);
printf("\ncontinue? ");
scanf("%c", &ch);
if(ch != 'Y' && ch != 'y') {
UNLOCK(semid);
SND_UNLOCK(semid);
return(-1);
}
UNLOCK(semid);
puts("after UNLOCK");
sleep(1);
LOCK(semid);
puts("after LOCK");
// usleep(1000); <=== 주목!!!!!
UNLOCK(semid);
puts("after UNLOCK");
SND_UNLOCK(semid);
puts("after SND_UNLOCK");
puts("\n++++++++++++++++++\n");
return(0);
}
int main()
{
int semid;
if((semid = semget(1111, 3, IPC_CREAT | 0666)) < 0) {
#ifdef _LIB_DEBUG
perror("[d_msgget]semget");
#endif
return(-1);
}
while(1) {
if(sem_test(semid) < 0)
break;
}
}
-------------end of semtest.c -----------------------------
-------------st.c -----------------------------------------
#include
#include
#include
#include
#define LOCK(a) d_sem_opr(a, 0, 1)
#define UNLOCK(a) d_sem_opr(a, 0, 2)
#define SND_LOCK(a) d_sem_opr(a, 1, 1)
#define SND_UNLOCK(a) d_sem_opr(a, 1, 2)
int main()
{
int semid;
if((semid = semget(1111, 3, IPC_CREAT | 0666)) < 0) {
#ifdef _LIB_DEBUG
perror("[d_msgget]semget");
#endif
return(-1);
}
LOCK(semid);
printf("LOCK\n");
sleep(2);
UNLOCK(semid);
printf("UNLOCK\n");
}
-----------------end of st.c ----------------------------------
컴파일
cc -c s_test.c
cc -c semtest.c
cc -c st.c
cc -o semtest s_test.o semtest.o
cc -o st s_test.o st.o
설명
1. semtest의 로직
SND_LOCK
LOCK
입력 대기
UNLOCK
LOCK
//usleep(1000); <== 주목!!!
UNLOCK
SND_LOCK
2. st의 로직
LOCK
sleep()
UNLOCK
test1
먼저 semtest를 세개를 순서대로 띄웁니다.(편의상 순서대로 s1, s2, s3라
고 부르겠습니다)
1. s1, s2, s3를 다 띄웁니다.
(s1에서 continue?란 메시지가 나옴, s2, s3는 before SND_LOCK 상태)
2. st를 띄웁니다.
3. s1의 continue?라는 곳에 y라고 입력합니다.
4. st에서 LOCK이란 메시지를 볼수 있음
5. st는 2초후에 UNLOCK을 한후에 종료
6. st가 UNLOCK한 후에 s1에서 또다시 continue?라는 표시가 나옵니다.
(이게 이상합니다. 당연히 s2 가 LOCK을 얻어야 하는데요)
7. 2로 반복합니다.
제어권은 계속 s1 => st => s1 => st로 반복됩니다.
s2, s3는 결코 lock을 얻지 못하고 소외됩니다.
test2
설명에 (<=== 주목!!!)이라고 되어 있는 부분을 풀고 같은 테스트를 합니
다.
같은 실험을 반복하면 s1 => st => s2 => st => s3 => st순으로 원래 의
도대로 돌아갑니다.
질문
test1과 test2에서 알수 있듯이 <== 주목이라는 부분에 usleep을 넣지 않
으면 정상적으로 작동하지 않습니다.
usleep을 넣지 않더라도 test1이 제대로 동작할 수 있는 방법이 있을까요?
(s1 => st => s2 => st = s3 순서)
아니면 이게 세마포의 버그라고 판단 할 수 있을까요?
고수님들의 많은 조언을 바랍니다.
댓글 달기