@ -154,12 +154,15 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
# define SEMOPM_FAST 64 /* ~ 372 bytes on stack */
/*
* linked list protection :
* Locking :
* sem_undo . id_next ,
* sem_array . complex_count ,
* sem_array . pending { _alter , _cont } ,
* sem_array . sem_undo : sem_lock ( ) for read / write
* sem_array . sem_undo : global sem_lock ( ) for read / write
* sem_undo . proc_next : only " current " is allowed to read / write that field .
*
* sem_array . sem_base [ i ] . pending_ { const , alter } :
* global or semaphore sem_lock ( ) for read / write
*/
# define sc_semmsl sem_ctls[0]
@ -536,12 +539,19 @@ SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg)
return ipcget ( ns , & sem_ids ( ns ) , & sem_ops , & sem_params ) ;
}
/*
* Determine whether a sequence of semaphore operations would succeed
* all at once . Return 0 if yes , 1 if need to sleep , else return error code .
/** perform_atomic_semop - Perform (if possible) a semaphore operation
* @ sma : semaphore array
* @ sops : array with operations that should be checked
* @ nsems : number of sops
* @ un : undo array
* @ pid : pid that did the change
*
* Returns 0 if the operation was possible .
* Returns 1 if the operation is impossible , the caller must sleep .
* Negative values are error codes .
*/
static int try_atomic_semop ( struct sem_array * sma , struct sembuf * sops ,
static int perform_atomic_semop ( struct sem_array * sma , struct sembuf * sops ,
int nsops , struct sem_undo * un , int pid )
{
int result , sem_op ;
@ -724,8 +734,8 @@ static int wake_const_ops(struct sem_array *sma, int semnum,
q = container_of ( walk , struct sem_queue , list ) ;
walk = walk - > next ;
error = try _atomic_semop( sma , q - > sops , q - > nsops ,
q - > undo , q - > pid ) ;
error = perform _atomic_semop( sma , q - > sops , q - > nsops ,
q - > undo , q - > pid ) ;
if ( error < = 0 ) {
/* operation completed, remove from queue & wakeup */
@ -838,7 +848,7 @@ again:
if ( semnum ! = - 1 & & sma - > sem_base [ semnum ] . semval = = 0 )
break ;
error = try _atomic_semop( sma , q - > sops , q - > nsops ,
error = perform _atomic_semop( sma , q - > sops , q - > nsops ,
q - > undo , q - > pid ) ;
/* Does q->sleeper still need to sleep? */
@ -1686,7 +1696,6 @@ static int get_queue_result(struct sem_queue *q)
return error ;
}
SYSCALL_DEFINE4 ( semtimedop , int , semid , struct sembuf __user * , tsops ,
unsigned , nsops , const struct timespec __user * , timeout )
{
@ -1784,7 +1793,8 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
if ( un & & un - > semid = = - 1 )
goto out_unlock_free ;
error = try_atomic_semop ( sma , sops , nsops , un , task_tgid_vnr ( current ) ) ;
error = perform_atomic_semop ( sma , sops , nsops , un ,
task_tgid_vnr ( current ) ) ;
if ( error < = 0 ) {
if ( alter & & error = = 0 )
do_smart_update ( sma , sops , nsops , 1 , & tasks ) ;