sl@0: /** @file  ../include/sys/sem.h
sl@0: @internalComponent
sl@0: */
sl@0: 
sl@0: /** @fn  semget(key_t key, int nsems, int semflg)
sl@0: @param key
sl@0: @param nsems
sl@0: @param semflg
sl@0: @return   The semget call
sl@0: returns the id of a semaphore set if successful; otherwise, -1
sl@0: is returned and errno is set to indicate the error.
sl@0: 
sl@0: @code
sl@0:  SEM_R Read access for user.
sl@0:  SEM_A Alter access for user.
sl@0:  ( SEM_R>>3 )
sl@0:   Read access for group.
sl@0:  ( SEM_A>>3 )
sl@0:   Alter access for group.
sl@0:  ( SEM_R>>6 )
sl@0:   Read access for other.
sl@0:  ( SEM_A>>6 )
sl@0:   Alter access for other.
sl@0: 
sl@0: Note:The 'group' flags (SEM_R >> 3 and SEM_A >> 3) are ignored in Symbian OS.
sl@0: @endcode
sl@0:   Based on the values of key and semflg, semget returns the identifier of a newly created or previously existing
sl@0: set of semaphores. The key
sl@0: is analogous to a filename: it provides a handle that names an
sl@0: IPC object.
sl@0: There are three ways to specify a key: IPC_PRIVATE may be specified, in which case a new IPC object
sl@0: will be created. An integer constant may be specified.
sl@0: If no IPC object corresponding
sl@0: to key is specified and the IPC_CREAT bit is set in semflg, a new one will be created. The ftok function
sl@0: may be used to generate a key from a pathname.
sl@0: 
sl@0: @code
sl@0: 
sl@0:  The mode of a newly created IPC object is determined by OR 'ing the following constants into the semflg argument: SEM_R Read access for user. SEM_A Alter access for user. ( SEM_R>>3 )  Read access for group. ( SEM_A>>3 )  Alter access for group. ( SEM_R>>6 )  Read access for other. ( SEM_A>>6 )  Alter access for other.
sl@0: @endcode
sl@0: 
sl@0: 
sl@0:  If a new set of semaphores is being created, nsems is used to indicate the number of semaphores the set should contain.
sl@0: Otherwise, nsems may be specified as 0.
sl@0: 
sl@0: Examples:
sl@0: @code
sl@0: #include <sys/ipc.h>
sl@0: #include <sys/sem.h>
sl@0: #include <stdio.h>
sl@0: #include <errno.h>
sl@0: 
sl@0: #define SEM_SET_KEY 1000
sl@0: #define NO_OF_SEMAPHORES 2
sl@0: 
sl@0: int main(void)
sl@0: {
sl@0:     int sem_set_id;
sl@0:     int perm;
sl@0:     /*
sl@0:      * Create 2 semaphores in a set, with access only to
sl@0:      * the owner
sl@0:      */
sl@0:     perm = SEM_R | SEM_A;
sl@0:     if((sem_set_id = semget(SEM_SET_KEY, NO_OF_SEMAPHORES, IPC_CREAT | perm))
sl@0:         == -1) {
sl@0:        printf("Semaphore creation failed with errno %d", errno);
sl@0:        return -1;
sl@0:     }
sl@0:     return 0;
sl@0: }
sl@0: @endcode
sl@0: 
sl@0: @code
sl@0: Note :If the user need to create a semaphore which can be accessed from a different process, the 'other' flags (SEM_R >> 6 and SEM_A >> 6) must be added in parameter of shmflg.
sl@0: e.g The value of the variable perm used in the above example code should be as below
sl@0: perm = SEM_R | SEM_A | SEM_R >> 6 | SEM_A >> 6
sl@0: @endcode
sl@0: 
sl@0: @see semctl()
sl@0: @see semop()
sl@0: @see ftok()
sl@0: 
sl@0: 
sl@0:  
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @fn  semop(int semid, struct sembuf *sops, unsigned nsops)
sl@0: @param semid
sl@0: @param sops
sl@0: @param nsops
sl@0: @return   The semop function returns 0 if successful; otherwise the
sl@0: value -1 is returned and errno is set to indicate the error.
sl@0: 
sl@0:   The semop system call
sl@0: atomically performs the array of operations indicated by array on the semaphore set indicated by semid. The length of array is indicated by nops. Each operation is encoded in a struct sembuf ,
sl@0: which is defined as follows: 
sl@0: 
sl@0: @code
sl@0: struct sembuf {
sl@0:         u_short sem_num;        /* semaphore # */
sl@0:         short   sem_op;         /* semaphore operation */
sl@0:         short   sem_flg;        /* operation flags */
sl@0: };
sl@0: @endcode
sl@0: 
sl@0:  For each element in array, sem_op and sem_flg determine an operation to be performed on semaphore number sem_num in the set.
sl@0: The values SEM_UNDO and IPC_NOWAIT may be ORed into the sem_flg member in order to modify the behavior of the given operation.
sl@0: 
sl@0:  The operation performed depends as follows on the value of sem_op: When sem_op is positive and the process has alter permission,
sl@0: the semaphore's value is incremented by sem_op's value.
sl@0: If SEM_UNDO is specified, the semaphore's adjust on exit value is decremented by sem_op's value.
sl@0: A positive value for sem_op generally corresponds to a process releasing a resource
sl@0: associated with the semaphore. The behavior when sem_op is negative and the process has alter permission,
sl@0: depends on the current value of the semaphore: If the current value of the semaphore is greater than or equal to
sl@0: the absolute value of sem_op, then the value is decremented by the absolute value of sem_op. If SEM_UNDO is specified, the semaphore's adjust on exit
sl@0: value is incremented by the absolute value of sem_op. If the current value of the semaphore is less than the absolute value of sem_op, one of the following happens: If IPC_NOWAIT was specified, then semop returns immediately with a return value of EAGAIN. Otherwise, the calling process is put to sleep until one of the following
sl@0: conditions is satisfied: Some other process removes the semaphore with the IPC_RMID option of semctl .
sl@0: In this case, semop returns immediately with a return value of EIDRM. The semaphore's
sl@0: value is greater than or equal to the absolute value of sem_op. When this condition becomes true, the semaphore's value is decremented
sl@0: by the absolute value of sem_op, the semaphore's adjust on exit value is incremented by the
sl@0: absolute value of sem_op.
sl@0: 
sl@0:  A negative value for sem_op generally means that a process is waiting for a resource to become
sl@0: available. When sem_op is zero and the process has read permission,
sl@0: one of the following will occur: If the current value of the semaphore is equal to zero
sl@0: then semop can return immediately. If IPC_NOWAIT was specified, then semop returns immediately with a return value of EAGAIN. Otherwise, the calling process is put to sleep until one of the following
sl@0: conditions is satisfied: Some other process removes the semaphore with the IPC_RMID option of semctl .
sl@0: In this case, semop returns immediately with a return value of EIDRM. The semaphore's value becomes zero.
sl@0: 
sl@0:  For each semaphore a process has in use, an "adjust on exit"
sl@0: value is maintained, as alluded to earlier.
sl@0: When a process
sl@0: exits, either voluntarily or involuntarily, the adjust on exit value
sl@0: for each semaphore is added to the semaphore's value.
sl@0: This can
sl@0: be used to insure that a resource is released if a process terminates
sl@0: unexpectedly.
sl@0: 
sl@0: Examples:
sl@0: @code
sl@0: #include <sys/ipc.h>
sl@0: #include <sys/sem.h>
sl@0: #include <stdio.h>
sl@0: 
sl@0: void File_Update(char* path, int val)
sl@0: {
sl@0:     struct sembuf sem_op;
sl@0:     FILE* fp;
sl@0:     /*
sl@0:      * Wait on the semaphore till the value is non-negative.
sl@0:      */
sl@0:     sem_op.sem_num = 0;
sl@0:     sem_op.sem_op = -1;
sl@0:     sem_op.sem_flg = 0;
sl@0:     semop(sem_set_id, &sem;_op, 1);
sl@0:     /*
sl@0:      * If we are here, then We have locked the semaphore,
sl@0:      * and are assured exclusive access to file.
sl@0:      * We can now manipulate the file
sl@0:      */
sl@0:     fp = fopen(path, "w");
sl@0:     if (fp) {
sl@0:         fprintf(fp, "%d", val);
sl@0:         fclose(fp);
sl@0:     }
sl@0:     /*
sl@0:      * Increase the value of the semaphore by 1 so that others blocked on
sl@0:      * this semaphore get awakened.
sl@0:      */
sl@0:     sem_op.sem_num = 0;
sl@0:     sem_op.sem_op = 1;
sl@0:     sem_op.sem_flg = 0;
sl@0:     semop(sem_set_id, &sem;_op, 1);
sl@0: }
sl@0: 
sl@0: @endcode
sl@0: @see semctl()
sl@0: @see semget()
sl@0: 
sl@0: 
sl@0: Bugs:
sl@0: 
sl@0:  The semop system call
sl@0: may block waiting for memory even if IPC_NOWAIT was specified. 
sl@0: 
sl@0:  
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @fn  semctl(int semid, int semnum, int cmd, ...)
sl@0: @param semid
sl@0: @param semnum
sl@0: @param cmd
sl@0: @param ...
sl@0: @return   On success, when cmd is one of GETVAL, GETPID, GETNCNT or GETZCNT, semctl returns the corresponding value; otherwise, 0 is returned.
sl@0: On failure, -1 is returned, and errno is set to indicate the error.
sl@0: 
sl@0: @code
sl@0:  IPC_STAT Fetch the semaphore sets struct semid_ds ,
sl@0:  storing it in the memory pointed to by arg.buf .
sl@0:  IPC_SET Changes the sem_perm.uid, sem_perm.gid, and sem_perm.mode members of the semaphore sets struct semid_ds to match those of the struct pointed to by arg.buf.
sl@0:  IPC_RMID Immediately removes the semaphore set from the system.
sl@0:  The calling
sl@0:  processe'ss uid must equal the semaphore sets sem_perm.uid or sem_perm.cuid,
sl@0:  GETVAL Return the value of semaphore number semnum.
sl@0:  SETVAL Set the value of semaphore number semnum to arg.val. Outstanding adjust on exit values for this semaphore in any process
sl@0:  are cleared.
sl@0:  GETPID Return the pid of the last process to perform an operation on
sl@0:  semaphore number semnum.
sl@0:  GETNCNT Return the number of processes waiting for semaphore number semnum's value to become greater than its current value.
sl@0:  GETZCNT Return the number of processes waiting for semaphore number semnum's value to become 0.
sl@0:  GETALL Fetch the value of all of the semaphores in the set into the
sl@0:  array pointed to by arg.array.
sl@0:  SETALL Set the values of all of the semaphores in the set to the values
sl@0:  in the array pointed to by arg.array. Outstanding adjust on exit values for all semaphores in this set,
sl@0:  in any process are cleared.
sl@0: 
sl@0: @endcode
sl@0:   The semctl system call
sl@0: performs the operation indicated by cmd on the semaphore set indicated by semid. A fourth argument, a union semun arg ,
sl@0: is required for certain values of cmd. For the commands that use the arg argument, union semun is defined as follows: 
sl@0: @code
sl@0: union semun {
sl@0:         int     val;            /* value for SETVAL */
sl@0:         struct  semid_ds *buf;  /* buffer for IPC_STAT & IPC_SET */
sl@0:         u_short *array;         /* array for GETALL & SETALL */
sl@0: };
sl@0: @endcode
sl@0: 
sl@0:  Commands are performed as follows: 
sl@0:  
sl@0:  @code
sl@0:  
sl@0: IPC_STAT Fetch the semaphore sets struct semid_ds ,
sl@0: storing it in the memory pointed to by arg.buf . 
sl@0: IPC_SET Changes the sem_perm.uid, sem_perm.gid, and sem_perm.mode members of the semaphore sets struct semid_ds to match those of the struct pointed to by arg.buf. 
sl@0: IPC_RMID Immediately removes the semaphore set from the system.
sl@0: 
sl@0: @endcode
sl@0: 
sl@0: The calling process's uid must equal the semaphore sets sem_perm.uid or sem_perm.cuid, GETVAL Return the value of semaphore number semnum. SETVAL Set the value of semaphore number semnum to arg.val. Outstanding adjust on exit values for this semaphore in any process
sl@0: are cleared. 
sl@0: 
sl@0: @code
sl@0: 
sl@0: GETPID Return the pid of the last process to perform an operation on
sl@0: semaphore number semnum. 
sl@0: GETNCNT Return the number of processes waiting for semaphore number semnum's value to become greater than its current value. 
sl@0: GETZCNT Return the number of processes waiting for semaphore number semnum s value to become 0. 
sl@0: GETALL Fetch the value of all of the semaphores in the set into the
sl@0: array pointed to by arg.array. 
sl@0: SETALL Set the values of all of the semaphores in the set to the values
sl@0: in the array pointed to by arg.array. Outstanding adjust on exit values for all semaphores in this set,
sl@0: in any process are cleared.
sl@0: 
sl@0: @endcode
sl@0: 
sl@0:  The struct semid_ds
sl@0: is defined as follows: 
sl@0: @code
sl@0: struct semid_ds {
sl@0:         struct  ipc_perm sem_perm;      /* operation permission struct */
sl@0:         struct  sem *sem_base;  /* pointer to first semaphore in set */
sl@0:         u_short sem_nsems;      /* number of sems in set */
sl@0:         time_t  sem_otime;      /* last operation time */
sl@0:         long    sem_pad1;       /* SVABI/386 says I need this here */
sl@0:         time_t  sem_ctime;      /* last change time */
sl@0:                                 /* Times measured in secs since */
sl@0:                                 /* 00:00:00 GMT, Jan. 1, 1970 */
sl@0:         long    sem_pad2;       /* SVABI/386 says I need this here */
sl@0:         long    sem_pad3[4];    /* SVABI/386 says I need this here */
sl@0: };
sl@0: @endcode
sl@0: 
sl@0: Examples:
sl@0: @code
sl@0: #include <sys/ipc.h>
sl@0: #include <sys/sem.h>
sl@0: #include <stdio.h>
sl@0: #include <errno.h>
sl@0: 
sl@0: #define SEM_SET_KEY 1000
sl@0: #define NO_OF_SEMAPHORES 2
sl@0: 
sl@0: int main(void)
sl@0: {
sl@0:     int sem_set_id;
sl@0:     union semun sem_val;
sl@0:     /*
sl@0:      * Create 2 semaphores in a set, with access only to
sl@0:      * the owner
sl@0:      */
sl@0:     if((sem_set_id = semget(SEM_SET_KEY, NO_OF_SEMAPHORES, IPC_CREAT | 0600))
sl@0:         == -1) {
sl@0:        printf("Semaphore creation failed with errno %d", errno);
sl@0:        return -1;
sl@0:     }
sl@0:     /*
sl@0:      * Initialize the first semaphore in our set to 1
sl@0:      */
sl@0:     sem_val.array = NULL;
sl@0:     sem_val.buf = NULL;
sl@0:     sem_val.val = 1;
sl@0:     if(semctl(sem_set_id, 0, SETVAL, sem_val) == -1) {
sl@0:        printf("Could not initialize first semaphore (errno %d)", errno);
sl@0:        return -1;
sl@0:     }
sl@0:     /*
sl@0:      * Initialize the second semaphore in our set to 0
sl@0:      */
sl@0:     sem_val.val = 0;
sl@0:     if(semctl(sem_set_id, 1, SETVAL, sem_val) == -1) {
sl@0:        printf("Could not initialize second semaphore (errno %d)", errno);
sl@0:        return -1;
sl@0:     }
sl@0:     /*
sl@0:      * Delete the semaphore set
sl@0:      */
sl@0:     if(semctl(sem_set_id, NO_OF_SEMAPHORES, IPC_RMID) == -1) {
sl@0:        printf("Could not delete semaphore set (errno %d)", errno);
sl@0:        return -1;
sl@0:     }
sl@0:     return 0;
sl@0: }
sl@0: 
sl@0: @endcode
sl@0: @see semget()
sl@0: @see semop()
sl@0: 
sl@0: 
sl@0:  
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: 
sl@0: 
sl@0: /** @struct semid_ds
sl@0: 
sl@0: Contains following members,
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @var semid_ds::sem_perm
sl@0: operation permission struct
sl@0: */
sl@0: 
sl@0: /** @var semid_ds::sem_base
sl@0: pointer to first semaphore in set
sl@0: */
sl@0: 
sl@0: /** @var semid_ds::sem_nsems
sl@0: number of sems in set
sl@0: */
sl@0: 
sl@0: /** @var semid_ds::sem_otime
sl@0: last operation time
sl@0: */
sl@0: 
sl@0: /** @var semid_ds::sem_pad1
sl@0: SVABI or 386 says I need this here 
sl@0: */
sl@0: 
sl@0: /** @var semid_ds::sem_ctime
sl@0: last change time
sl@0: */
sl@0: 
sl@0: /** @var semid_ds::sem_pad2
sl@0: SVABI or 386 says I need this here
sl@0: */
sl@0: 
sl@0: /** @var semid_ds::sem_pad3
sl@0: SVABI or 386 says I need this here
sl@0: */
sl@0: 
sl@0: 
sl@0: /** @struct sembuf
sl@0: 
sl@0: semop's sops parameter structure
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @var sembuf::sem_num
sl@0: semaphore X
sl@0: */
sl@0: 
sl@0: /** @var sembuf::sem_op
sl@0: semaphore operation
sl@0: */
sl@0: 
sl@0: /** @var sembuf::sem_flg
sl@0: operation flags
sl@0: */
sl@0: 
sl@0: /** @struct sem
sl@0: 
sl@0: sem includes following members,
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @var sem::semval
sl@0: semaphore value
sl@0: */
sl@0: 
sl@0: /** @var sem::sempid
sl@0: process ID of last operation
sl@0: */
sl@0: 
sl@0: /** @var sem::semncnt
sl@0: number of processes waiting for semval to become greater than current value 
sl@0: */
sl@0: 
sl@0: /** @var sem::semzcnt
sl@0: number of processes waiting for semval to become 0 
sl@0: */
sl@0: 
sl@0: 
sl@0: /** @def GETNCNT
sl@0: 
sl@0: commands for semctl. Return the value of semncnt.
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @def GETPID
sl@0: 
sl@0: commands for semctl. Return the value of sempid
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @def GETVAL
sl@0: 
sl@0: commands for semctl. Return the value of semval.
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @def GETALL
sl@0: 
sl@0: commands for semctl. Return semvals into arg.array 
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @def GETZCNT
sl@0: 
sl@0: commands for semctl. Return the value of semzcnt.
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @def SETVAL
sl@0: 
sl@0: commands for semctl. Set the value of semval to arg.val.
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: /** @def SETALL
sl@0: 
sl@0: commands for semctl. Set semvals from arg.array.
sl@0: 
sl@0: @publishedAll
sl@0: @externallyDefinedApi
sl@0: */
sl@0: 
sl@0: