Semaphores on Solaris 7 with GCC 2.8.1

Semaphores on Solaris 7 with GCC 2.8.1

Post by Nicholas Twerdochli » Fri, 02 Apr 1999 04:00:00



I am writing a mutliprocess application that will utilize a circular
buffer in a shared memory segment.  I am using two semaphores to
represent the # of available slots, and the # of slots to consumer by
the server (consumer).

The apps follow this simple model.

Producer:
    decrement the available_slots semaphore
    do something...
    increment the to_consume semaphore.

Consumer:
    decrement the to_consume semaphore.
    do something...
    increment the available_slots semaphore.

The problem is that when I run my test programs and watch the semaphore
values, I see the available_slots semaphore continually increase?  The
program will run for a while if I remove the last increment in the
consumer program, but will eventually fail with errno 34, Result to
large.  Studying the output, it does not appear to me that the value of
the two semaphores ever reaches a critical point.

This simple example has been almost copied line for line from two
different books on this subject, both yielding the same results.  I have
included the source to both of my test apps.  If anyone can see, or
knows of something that I am just overlooking, I would very much like to
hear from you.

Thanks
Nicholas Twerdochlib

Platform info:
    Sun Sparc 20 dual ROSS 125Mhz CPUs 64MB RAM
    Solaris 7/2.7
    GCC v2.8.1

Server/consumer source:
*****************************************************************
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>

union semun {
 int val;
 struct semids_ds *buf;
 ushort *array;

Quote:};

static ushort start_val[2] = {6,0};

union semun arg;

struct sembuf acquire = {0, -1, SEM_UNDO};
struct sembuf release = {0, 1, SEM_UNDO};

int main( void ) {
  int semid;
  key_t SemKey = ftok( "/tmp/loggerd.sem", 'S' );

  if( (semid = semget( SemKey, 2, IPC_CREAT|0666 )) != -1 ) {
    arg.array = start_val;
    if( semctl( semid, 0, SETALL, arg ) < 0 ) {
      printf( "Failed to set semaphore initial states.\n" );
      perror( "SEMCTL: " );

      return -1;
    }
  }

  while( 1 ) {
    printf( "A Ready to consume: SEM %d Value: %d\n", 0, semctl(semid,
0, GETVAL, 0) );
    printf( "A Ready to consume: SEM %d Value: %d\n", 1, semctl(semid,
1, GETVAL, 0) );

    acquire.sem_num = 1;
    if( semop( semid, &acquire, 1 ) == -1 ) {
      perror( "server:main: acquire: " );
      exit( 2 );
    }

    printf( "B Ready to consume: SEM %d Value: %d\n", 0, semctl(semid,
0, GETVAL, 0) );
    printf( "B Ready to consume: SEM %d Value: %d\n", 1, semctl(semid,
1, GETVAL, 0) );
    /*
    release.sem_num = 0;
    if( semop( semid, &release, 1 ) == -1 ) {
      perror( "server:main: release: " );
      exit( 2 );
    }
    */
  }

Quote:}

**************************************************************************

Client/producer source
**************************************************************************

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>

union semun {
 int val;
 struct semids_ds *buf;
 ushort *array;

Quote:};

static ushort start_val[2] = {6,0};

union semun arg;

struct sembuf acquire = {0, -1, SEM_UNDO};
struct sembuf release = {0, 1, SEM_UNDO};

int main( void ) {
  int semid;
  key_t SemKey = ftok( "/tmp/loggerd.sem", 'S' );

  if( (semid = semget( SemKey, 2, 0)) == -1 ) {
    perror( "client:main: semget: " );
    exit( 2 );
  }

  printf( "A Ready to consume: SEM %d Value: %d\n", 0, semctl(semid, 0,
GETVAL, 0) );
  printf( "A Ready to consume: SEM %d Value: %d\n", 1, semctl(semid, 1,
GETVAL, 0) );

  acquire.sem_num = 0;
  if( semop( semid, &acquire, 1 ) == -1 ) {
    perror( "client:main: release: " );
    exit( 2 );
  }

  printf( "B Ready to consume: SEM %d Value: %d\n", 0, semctl(semid, 0,
GETVAL, 0) );
  printf( "B Ready to consume: SEM %d Value: %d\n", 1, semctl(semid, 1,
GETVAL, 0) );

  release.sem_num = 1;
  if( semop( semid, &release, 1 ) == -1 ) {
    perror( "client:main: acquire: " );
    exit( 2 );
  }

Quote:}

***********************************************************************************
 
 
 

Semaphores on Solaris 7 with GCC 2.8.1

Post by Casper H.S. Dik - Network Security Engine » Fri, 02 Apr 1999 04:00:00


[[ PLEASE DON'T SEND ME EMAIL COPIES OF POSTINGS ]]


>buffer in a shared memory segment.  I am using two semaphores to
>represent the # of available slots, and the # of slots to consumer by
>the server (consumer).
>The apps follow this simple model.
>Producer:
>    decrement the available_slots semaphore
>    do something...
>    increment the to_consume semaphore.
>Consumer:
>    decrement the to_consume semaphore.
>    do something...
>    increment the available_slots semaphore.
>struct sembuf acquire = {0, -1, SEM_UNDO};
>struct sembuf release = {0, 1, SEM_UNDO};

The error is quite simple; you shouldnt' specify SEM_UNDO for
semaphores that are not incremented decremented by the same process.

SEM_UNDO should be used for a single process that increments and
decrements the semaphore.  WHen the process is killed, the net
effect of the process on the sermaphore will be NIL because of the
adjust value.

With SEM_UNDO, each decrement in the producer will cause the "semadj"
value associated with the "available_slots" semaphore to be increased
by one.  When the produced exits, the semaphore will be incremented by N,
not what you want in this case.

Solaris also puts a bound on teh semadj value; there is no good reason for
this bound, except that it catches programming errors like yours.

Casper
--
Expressed in this posting are my opinions.  They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

 
 
 

1. How to use "Semaphore" function under linux with gcc?

How to use "Semaphore" function under linux with gcc?
"Semaphore" function:sem_wait sem_open sem_unlink
sem_post...

And How to bulit it,run it?

sample:

struct     shared
{
    sem_t     mutex;
    int     count;

int
main(int argc,char** argv)
{
    int fd,i,nloop;
    struct     shared     *ptr;
    int     ret;

    if(argc!=3)
         err_quit("usage:incr3 <pathname> <#loops>");

    nloop=atoi(argv[2]);

    fd=open(argv[1],O_RDWR|O_CREAT,FILE_MODE);
    if(fd<0)
         err_quit("open error!");

    ret=write(fd,&shared,sizeof(struct shared));
    if(ret<0)
         err_quit("write error!");

    ptr=mmap(NULL,sizeof(struct
shared),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    if(ptr==NULL)
         err_quit("mmap error!");

    close(fd);

    ret=sem_init(&ptr->mutex,1,1);
    if(ret<0)
         err_quit("sem_init error!");

    setbuf(stdout,NULL);

    if(fork()==0)
    {
         for(i=0;i<nloop;i++)
         {
              ret=sem_wait(&ptr->mutex);
              if(ret<0)
                   err_quit("sem_wait error!");

              printf("child:%d\n",ptr->count++);

              ret=sem_post(&ptr->mutex);
              if(ret<0)
                   err_quit("sem_post error!");
         }
         exit(0);
    }

    for(i=0;i<nloop;i++)
    {
         ret=sem_wait(&ptr->mutex);
         if(ret<0)
              err_quit("sem_wait error!");

         printf("parent:%d\n",ptr->count++);

         ret=sem_post(&ptr->mutex);
         if(ret<0)
              err_quit("sem_post error!");
    }
    exit(0);

When i bulit and run the above sample porgram:
show this error:
err: Function not implemented
sem_unlink error!

WHY???

             Indy

2. Nimda etc??

3. Increasing # of semaphores in semaphore set?

4. setlinebuf

5. Sys V Semaphores vs. POSIX Semaphores??

6. Getting sound to work

7. gcc 4.1.1 build under Intel Solaris 10 does not build gcc

8. X without a graphical card

9. are semaphores working correctly on solaris 2.3?

10. ObjectSpace / Solaris / Waiting for semaphore OR timer at same time

11. semaphores in Solaris vs Linux

12. Semaphore On Solaris Machines

13. Solaris 2.4 semaphore problem?