SEMOP(3)                   POSIX Programmer's Manual                  SEMOP(3)



PPRROOLLOOGG
       This manual page is part of the POSIX Programmer's Manual.  The OS
       implementation of this interface may differ (consult the corresponding
       OS manual page for details of OS behavior), or the interface may not be
       implemented on OS.


NNAAMMEE
       semop -- XSI semaphore operations

SSYYNNOOPPSSIISS
       #include <sys/sem.h>

       int semop(int _s_e_m_i_d, struct sembuf *_s_o_p_s, size_t _n_s_o_p_s);

DDEESSCCRRIIPPTTIIOONN
       The _s_e_m_o_p() function operates on XSI semaphores (see the Base
       Definitions volume of POSIX.1-2008, _S_e_c_t_i_o_n _4_._1_6, _S_e_m_a_p_h_o_r_e).  It is
       unspecified whether this function interoperates with the realtime
       interprocess communication facilities defined in _S_e_c_t_i_o_n _2_._8, _R_e_a_l_t_i_m_e.

       The _s_e_m_o_p() function shall perform atomically a user-defined array of
       semaphore operations in array order on the set of semaphores associated
       with the semaphore identifier specified by the argument _s_e_m_i_d.

       The argument _s_o_p_s is a pointer to a user-defined array of semaphore
       operation structures. The implementation shall not modify elements of
       this array unless the application uses implementation-defined
       extensions.

       The argument _n_s_o_p_s is the number of such structures in the array.

       Each structure, sseemmbbuuff, includes the following members:

             +---------------+---------------+--------------------------+
             | MMeemmbbeerr TTyyppee   | MMeemmbbeerr NNaammee   |       DDeessccrriippttiioonn        |
             +---------------+---------------+--------------------------+
             |uunnssiiggnneedd sshhoorrtt | _s_e_m___n_u_m       |Semaphore number.         |
             |sshhoorrtt          | _s_e_m___o_p        |Semaphore operation.      |
             |sshhoorrtt          | _s_e_m___f_l_g       |Operation flags.          |
             +---------------+---------------+--------------------------+
       Each semaphore operation specified by _s_e_m___o_p is performed on the
       corresponding semaphore specified by _s_e_m_i_d and _s_e_m___n_u_m.

       The variable _s_e_m___o_p specifies one of three semaphore operations:

        1. If _s_e_m___o_p is a negative integer and the calling process has alter
           permission, one of the following shall occur:

            *  If _s_e_m_v_a_l(see _<_s_y_s_/_s_e_m_._h_>) is greater than or equal to the
               absolute value of _s_e_m___o_p, the absolute value of _s_e_m___o_p is
               subtracted from _s_e_m_v_a_l.  Also, if (_s_e_m___f_l_g &SEM_UNDO) is non-
               zero, the absolute value of _s_e_m___o_p shall be added to the _s_e_m_a_d_j
               value of the calling process for the specified semaphore.

            *  If _s_e_m_v_a_l is less than the absolute value of _s_e_m___o_p and
               (_s_e_m___f_l_g &IPC_NOWAIT) is non-zero, _s_e_m_o_p() shall return
               immediately.

            *  If _s_e_m_v_a_l is less than the absolute value of _s_e_m___o_p and
               (_s_e_m___f_l_g &IPC_NOWAIT) is 0, _s_e_m_o_p() shall increment the _s_e_m_n_c_n_t
               associated with the specified semaphore and suspend execution
               of the calling thread until one of the following conditions
               occurs:

               --  The value of _s_e_m_v_a_l becomes greater than or equal to the
                   absolute value of _s_e_m___o_p.  When this occurs, the value of
                   _s_e_m_n_c_n_t associated with the specified semaphore shall be
                   decremented, the absolute value of _s_e_m___o_p shall be
                   subtracted from _s_e_m_v_a_l and, if (_s_e_m___f_l_g &SEM_UNDO) is non-
                   zero, the absolute value of _s_e_m___o_p shall be added to the
                   _s_e_m_a_d_j value of the calling process for the specified
                   semaphore.

               --  The _s_e_m_i_d for which the calling thread is awaiting action
                   is removed from the system. When this occurs, _e_r_r_n_o shall
                   be set to [[EEIIDDRRMM]] and -1 shall be returned.

               --  The calling thread receives a signal that is to be caught.
                   When this occurs, the value of _s_e_m_n_c_n_t associated with the
                   specified semaphore shall be decremented, and the calling
                   thread shall resume execution in the manner prescribed in
                   _s_i_g_a_c_t_i_o_n().

        2. If _s_e_m___o_p is a positive integer and the calling process has alter
           permission, the value of _s_e_m___o_p shall be added to _s_e_m_v_a_l and, if
           (_s_e_m___f_l_g &SEM_UNDO) is non-zero, the value of _s_e_m___o_p shall be
           subtracted from the _s_e_m_a_d_j value of the calling process for the
           specified semaphore.

        3. If _s_e_m___o_p is 0 and the calling process has read permission, one of
           the following shall occur:

            *  If _s_e_m_v_a_l is 0, _s_e_m_o_p() shall return immediately.

            *  If _s_e_m_v_a_l is non-zero and (_s_e_m___f_l_g &IPC_NOWAIT) is non-zero,
               _s_e_m_o_p() shall return immediately.

            *  If _s_e_m_v_a_l is non-zero and (_s_e_m___f_l_g &IPC_NOWAIT) is 0, _s_e_m_o_p()
               shall increment the _s_e_m_z_c_n_t associated with the specified
               semaphore and suspend execution of the calling thread until one
               of the following occurs:

               --  The value of _s_e_m_v_a_l becomes 0, at which time the value of
                   _s_e_m_z_c_n_t associated with the specified semaphore shall be
                   decremented.

               --  The _s_e_m_i_d for which the calling thread is awaiting action
                   is removed from the system. When this occurs, _e_r_r_n_o shall
                   be set to [[EEIIDDRRMM]] and -1 shall be returned.

               --  The calling thread receives a signal that is to be caught.
                   When this occurs, the value of _s_e_m_z_c_n_t associated with the
                   specified semaphore shall be decremented, and the calling
                   thread shall resume execution in the manner prescribed in
                   _s_i_g_a_c_t_i_o_n().

       Upon successful completion, the value of _s_e_m_p_i_d for each semaphore
       specified in the array pointed to by _s_o_p_s shall be set to the process
       ID of the calling process. Also, the _s_e_m___o_t_i_m_e timestamp shall be set
       to the current time, as described in _S_e_c_t_i_o_n _2_._7_._1, _I_P_C _G_e_n_e_r_a_l
       _D_e_s_c_r_i_p_t_i_o_n.

RREETTUURRNN VVAALLUUEE
       Upon successful completion, _s_e_m_o_p() shall return 0; otherwise, it shall
       return -1 and set _e_r_r_n_o to indicate the error.

EERRRROORRSS
       The _s_e_m_o_p() function shall fail if:

       EE22BBIIGG  The value of _n_s_o_p_s is greater than the system-imposed maximum.

       EEAACCCCEESS Operation permission is denied to the calling process; see
              _S_e_c_t_i_o_n _2_._7, _X_S_I _I_n_t_e_r_p_r_o_c_e_s_s _C_o_m_m_u_n_i_c_a_t_i_o_n.

       EEAAGGAAIINN The operation would result in suspension of the calling process
              but (_s_e_m___f_l_g &IPC_NOWAIT) is non-zero.

       EEFFBBIIGG  The value of _s_e_m___n_u_m is greater than or equal to the number of
              semaphores in the set associated with _s_e_m_i_d.

       EEIIDDRRMM  The semaphore identifier _s_e_m_i_d is removed from the system.

       EEIINNTTRR  The _s_e_m_o_p() function was interrupted by a signal.

       EEIINNVVAALL The value of _s_e_m_i_d is not a valid semaphore identifier, or the
              number of individual semaphores for which the calling process
              requests a SEM_UNDO would exceed the system-imposed limit.

       EENNOOSSPPCC The limit on the number of individual processes requesting a
              SEM_UNDO would be exceeded.

       EERRAANNGGEE An operation would cause a _s_e_m_v_a_l to overflow the system-imposed
              limit, or an operation would cause a _s_e_m_a_d_j value to overflow
              the system-imposed limit.

       _T_h_e _f_o_l_l_o_w_i_n_g _s_e_c_t_i_o_n_s _a_r_e _i_n_f_o_r_m_a_t_i_v_e_.

EEXXAAMMPPLLEESS
   SSeettttiinngg VVaalluueess iinn SSeemmaapphhoorreess
       The following example sets the values of the two semaphores associated
       with the _s_e_m_i_d identifier to the values contained in the _s_b array.

           ##iinncclluuddee <<ssyyss//sseemm..hh>>
           ......
           iinntt sseemmiidd;;
           ssttrruucctt sseemmbbuuff ssbb[[22]];;
           iinntt nnssooppss == 22;;
           iinntt rreessuulltt;;

           /* Code to initialize semid. */
           ...

           /* Adjust value of semaphore in the semaphore array semid. */
           sb[0].sem_num = 0;
           sb[0].sem_op = -1;
           sb[0].sem_flg = SEM_UNDO | IPC_NOWAIT;
           sb[1].sem_num = 1;
           sb[1].sem_op = 1;
           sb[1].sem_flg = 0;

           result = semop(semid, sb, nsops);

   CCrreeaattiinngg aa SSeemmaapphhoorree IIddeennttiiffiieerr
       The following example gets a unique semaphore key using the _f_t_o_k()
       function, then gets a semaphore ID associated with that key using the
       _s_e_m_g_e_t() function (the first call also tests to make sure the semaphore
       exists).  If the semaphore does not exist, the program creates it, as
       shown by the second call to _s_e_m_g_e_t().  In creating the semaphore for
       the queuing process, the program attempts to create one semaphore with
       read/write permission for all. It also uses the IPC_EXCL flag, which
       forces _s_e_m_g_e_t() to fail if the semaphore already exists.

       After creating the semaphore, the program uses calls to _s_e_m_c_t_l() and
       _s_e_m_o_p() to initialize it to the values in the _s_b_u_f array. The number of
       processes that can execute concurrently without queuing is initially
       set to 2. The final call to _s_e_m_g_e_t() creates a semaphore identifier
       that can be used later in the program.

       Processes that obtain _s_e_m_i_d without creating it check that _s_e_m___o_t_i_m_e is
       non-zero, to ensure that the creating process has completed the _s_e_m_o_p()
       initialization.

       The final call to _s_e_m_o_p() acquires the semaphore and waits until it is
       free; the SEM_UNDO option releases the semaphore when the process
       exits, waiting until there are less than two processes running
       concurrently.

           ##iinncclluuddee <<ssttddiioo..hh>>
           ##iinncclluuddee <<ssyyss//sseemm..hh>>
           ##iinncclluuddee <<ssyyss//ssttaatt..hh>>
           ##iinncclluuddee <<eerrrrnnoo..hh>>
           ##iinncclluuddee <<ssttddlliibb..hh>>
           ......
           kkeeyy__tt sseemmkkeeyy;;
           iinntt sseemmiidd;;
           ssttrruucctt sseemmbbuuff ssbbuuff;;
           uunniioonn sseemmuunn {{
               iinntt vvaall;;
               ssttrruucctt sseemmiidd__ddss **bbuuff;;
               uunnssiiggnneedd sshhoorrtt **aarrrraayy;;
           }} aarrgg;;
           ssttrruucctt sseemmiidd__ddss ddss;;
           ......
           //** GGeett uunniiqquuee kkeeyy ffoorr sseemmaapphhoorree.. **//
           iiff ((((sseemmkkeeyy == ffttookk((""//ttmmpp"",, ''aa'')))) ==== ((kkeeyy__tt)) --11)) {{
               ppeerrrroorr((""IIPPCC eerrrroorr:: ffttookk""));; eexxiitt((11));;
           }}

           /* Get semaphore ID associated with this key. */
           if ((semid = semget(semkey, 0, 0)) == -1) {

               /* Semaphore does not exist - Create. */
               if ((semid = semget(semkey, 1, IPC_CREAT | IPC_EXCL | S_IRUSR |
                   S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != -1)
               {
                   /* Initialize the semaphore. */
                   arg.val = 0;
                   sbuf.sem_num = 0;
                   sbuf.sem_op = 2;  /* This is the number of runs without queuing. */
                   sbuf.sem_flg = 0;
                   if (semctl(semid, 0, SETVAL, arg) == -1
                       || semop(semid, &sbuf, 1) == -1) {
                       perror("IPC error: semop"); exit(1);
                   }
               }
               else if (errno == EEXIST) {
                   if ((semid = semget(semkey, 0, 0)) == -1) {
                       perror("IPC error 1: semget"); exit(1);
                   }
                   goto check_init;
               }
               else {
                   perror("IPC error 2: semget"); exit(1);
               }
           }
           else
           {
               /* Check that semid has completed initialization. */
               /* An application can use a retry loop at this point rather than
                  exiting. */
               check_init:
               arg.buf = &ds;
               if (semctl(semid, 0, IPC_STAT, arg) < 0) {
                   perror("IPC error 3: semctl"); exit(1);
               }
               if (ds.sem_otime == 0) {
                   perror("IPC error 4: semctl"); exit(1);
               }
           }
           ...
           sbuf.sem_num = 0;
           sbuf.sem_op = -1;
           sbuf.sem_flg = SEM_UNDO;
           if (semop(semid, &sbuf, 1) == -1) {
               perror("IPC Error: semop"); exit(1);
           }

AAPPPPLLIICCAATTIIOONN UUSSAAGGEE
       The POSIX Realtime Extension defines alternative interfaces for
       interprocess communication. Application developers who need to use IPC
       should design their applications so that modules using the IPC routines
       described in _S_e_c_t_i_o_n _2_._7, _X_S_I _I_n_t_e_r_p_r_o_c_e_s_s _C_o_m_m_u_n_i_c_a_t_i_o_n can be easily
       modified to use the alternative interfaces.

RRAATTIIOONNAALLEE
       None.

FFUUTTUURREE DDIIRREECCTTIIOONNSS
       None.

SSEEEE AALLSSOO
       _S_e_c_t_i_o_n _2_._7, _X_S_I _I_n_t_e_r_p_r_o_c_e_s_s _C_o_m_m_u_n_i_c_a_t_i_o_n, _S_e_c_t_i_o_n _2_._8, _R_e_a_l_t_i_m_e,
       _e_x_e_c, _e_x_i_t(), _f_o_r_k(), _s_e_m_c_t_l(), _s_e_m_g_e_t(), _s_e_m___c_l_o_s_e(), _s_e_m___d_e_s_t_r_o_y(),
       _s_e_m___g_e_t_v_a_l_u_e(), _s_e_m___i_n_i_t(), _s_e_m___o_p_e_n(), _s_e_m___p_o_s_t(), _s_e_m___t_r_y_w_a_i_t(),
       _s_e_m___u_n_l_i_n_k()

       The Base Definitions volume of POSIX.1-2008, _S_e_c_t_i_o_n _4_._1_6, _S_e_m_a_p_h_o_r_e,
       <<ssyyss__iippcc..hh>>, <<ssyyss__sseemm..hh>>, <<ssyyss__ttyyppeess..hh>>

CCOOPPYYRRIIGGHHTT
       Portions of this text are reprinted and reproduced in electronic form
       from IEEE Std 1003.1, 2013 Edition, Standard for Information Technology
       -- Portable Operating System Interface (POSIX), The Open Group Base
       Specifications Issue 7, Copyright (C) 2013 by the Institute of
       Electrical and Electronics Engineers, Inc and The Open Group.  (This is
       POSIX.1-2008 with the 2013 Technical Corrigendum 1 applied.) In the
       event of any discrepancy between this version and the original IEEE and
       The Open Group Standard, the original IEEE and The Open Group Standard
       is the referee document. The original Standard can be obtained online
       at http://www.unix.org/online.html .

       Any typographical or formatting errors that appear in this page are
       most likely to have been introduced during the conversion of the source
       files to man page format. To report such errors, see
       https://www.kernel.org/doc/man-pages/reporting_bugs.html .



IEEE/The Open Group                  2013                             SEMOP(3)
