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: