3

I am trying to understand how to do a wait for zero operation in unix. I have this code, but it stops waiting always with the same value as given.

int main(void){

    int sem;
    struct sembuf sops[2];


    if((sem = semget(IPC_PRIVATE, 1,  IPC_CREAT | 0600))==-1){
        perror("Error semget");
        return 100;
    }

    fork();
    //printf("Empieza la accion\n");

    if(semctl(sem,0,SETVAL,2)==-1){
        printf("Error semctl\n");
        exit(100);
    }
    printf("Value: %d\n",semctl(sem,0,GETVAL));
    sops[0].sem_num=0;     
    sops[0].sem_op=-1;     
    sops[0].sem_flg=0;      

    //WAIT(0)   
    sops[1].sem_num=0;     
    sops[1].sem_op=0;     
    sops[1].sem_flg=0;
    printf("Value: %d\n",semctl(sem,0,GETVAL));

    if(semop(sem,&sops,2)<0) printf("Error semop\n");
    printf("Value: %d\n",semctl(sem,0,GETVAL));
    printf("End\n");

}
tux3
  • 7,171
  • 6
  • 39
  • 51
  • I believe the problem here is that your first thread calls `semop()` which will decrement the value to 1, and then wait for the value to become 0, however until that first thread returns from `semop()` the second one cannot enter it in order to decrement it again. You'll probably need to break your operations up into multiple semop() calls. I am not positive on this... I've never used semop(), I'm just reading the man page. – mah Apr 15 '15 at 19:13

1 Answers1

1

Gcc complains to me about your code:

sem.c:37: warning: passing argument 2 of ‘semop’ from incompatible pointer type /usr/include/sys/sem.h:59: note: expected ‘struct sembuf *’ but argument is of type ‘struct sembuf (*)[2]’

This is the code it doesn't like:

    if(semop(sem,&sops,2)<0) printf("Error semop\n");

If I change it to

    if(semop(sem,sops,2)<0) printf("Error semop\n");

then GCC does not complain, and the program hangs indefinitely on the semop() call, as I would expect.

In particular, note that semop() applies all the specified operations as an atomic group, or not at all. Your program could only proceed past the semop() call if the operations specified by the two processes were overlapped, such that the two decrements were performed first, then the two wait-for-zeroes.

Your program works about as you may have expected if I move the SETVAL operation before the fork() call, and have each process perform two separate semop() calls, one to decrement the semaphore, and then one to wait for it to become zero.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • While a valid comment, this doesn't answer the question being asked. I admit that his English is not necessarily very clear about what he's looking for (probably ESL). I believe the problem he's having is exactly what you've confirmed is happening -- the infinite wait. It seems to me that he `fork()`s with the incorrect expectation of having the wait complete when both threads have decremented the semaphore value -- which I don't think is possible given his current approach. – mah Apr 15 '15 at 19:28
  • @mah, fair enough. I have updated my answer to explain the reason for the hang, it to suggest a way around it. – John Bollinger Apr 15 '15 at 19:42
  • Thanks! But moving the SETVAL before the fork doesn't solve the probleme of the infinite wait. What more I have to do? – Javi González García Apr 15 '15 at 19:53
  • I told you already. Each process must perform the decrement operation and the wait-for-zero operation with *separate* `semop()` calls. – John Bollinger Apr 15 '15 at 20:34