Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Examples  

sem.c

Go to the documentation of this file.
00001 /*! \file sem.c
00002     This file implements basic synchronosation toolkit.
00003  */
00004 
00005 #include "my_sem.h"
00006 
00007 /*! \brief System identifier for the set of semaphores. */
00008 static int      semaphore_set = -1;
00009 
00010 /*! \brief Number of semaphores in the set of semaphores. */
00011 static int      set_size      = -1;
00012 
00013 /*! \brief Default semaphores' permission used at creation time. */
00014 static int      permission    = SEM_PERMISSION;
00015 
00016 
00017 /*! \brief Set default access permissions for the set of semaphores.
00018     \param new_permission New permissions.
00019     \warning By default, the set of semaphores is created with the persmission mask 0x000001C0, that is, in binary:
00020              111 000 000. This grants all right to the process' user but nothing for other users (just like file permissions).
00021  */
00022 
00023 void change_sem_access_permission (int new_permission) { permission = new_permission; }
00024 
00025 /*! \brief Create a set of semaphores.
00026     \param ipc_key IPC key for the semaphore set. If you have a well known key (it should be a number greater or equal to
00027            zero), then you can specify it. Otherwise, if you want the kernel to find the first available key, then you must
00028            specify the value (key_t)-1.
00029     \param number_of_sem Number of semaphores in the set.
00030     \return This function may return one of the followinf values:
00031             <ul>
00032               <li>CREATE_SEMAPHORE_OK: The operation was successful.
00033               <li>CREATE_SEMAPHORE_CREATE_ERROR: A system error occured while creating the set of semaphores.
00034               <li>CREATE_SEMAPHORE_SET_VAL_ERROR: A system error occured while setting semaphores' values to 1.
00035             </ul>
00036     \warning By default, semaphores are created with the value 1 (like mutexes). You can change that later by using the
00037              function change_sem_access_permission().
00038  */
00039 
00040 int create_semaphore_set (key_t ipc_key, int number_of_sem)
00041 {
00042     int          i;
00043     union semun  sem_def;
00044 
00045     set_size = number_of_sem;
00046 
00047     /* =============================================================== */
00048     /* Create the set of semaphores                                    */
00049     /* =============================================================== */
00050 
00051     if (ipc_key != (key_t)-1) { semaphore_set = semget (ipc_key, number_of_sem, IPC_CREAT | permission); }
00052     else { semaphore_set = semget (IPC_PRIVATE, number_of_sem, IPC_CREAT | permission); }
00053 
00054     if (semaphore_set == (key_t)-1) { return CREATE_SEMAPHORE_CREATE_ERROR; }
00055 
00056     /* =============================================================== */
00057     /* Set all semaphore values to 1 (can be change later)             */
00058     /* =============================================================== */
00059 
00060     for (i=0; i<number_of_sem; i++)
00061     {
00062       sem_def.val = 1;
00063       if (semctl (semaphore_set, i, SETVAL, sem_def) == -1)
00064       { return CREATE_SEMAPHORE_SET_VAL_ERROR; }
00065     }
00066 
00067     return CREATE_SEMAPHORE_OK;
00068 }
00069 
00070 /*! \example test_shm.c
00071     This file shows how to use the function create_semaphore_set().
00072  */
00073 
00074 /*! \brief Get a already created (by another process) set of semaphores.
00075     \param ipc_key Well known IPC key that identifies the set of semaphores.
00076     \param number_of_sem Number of semaphores in the set.
00077     \return The function may return one of the following value:
00078             <UL>
00079                <li>GET_SEM_OK: The operation was successful.
00080                <li>GET_SEM_ALREADY_GET: The process already got the set of semaphores.
00081                <li>GET_SEM_ERROR: An error occured while getting the semaphores.
00082             </UL>
00083     \warning Since you get a semaphores set created by another process, you should know the <b>well known</b> IPC key that
00084              represents the set of semaphores.
00085  */
00086 
00087 int get_semaphore_set (key_t ipc_key, int number_of_sem)
00088 {
00089 
00090   if (semaphore_set != -1) { return GET_SEM_ALREADY_GET; }
00091 
00092   semaphore_set = semaphore_set = semget (ipc_key, number_of_sem, 0);
00093   set_size = number_of_sem;
00094 
00095   if (semaphore_set == -1) { return GET_SEM_ERROR; }
00096 
00097   return GET_SEM_OK;
00098 }
00099 
00100 /*! \example test_shm.c
00101     This file shows how to use the function get_semaphore_set().
00102  */
00103 
00104 /*! \brief Set semaphores' values (this update the entire set of semaphores).
00105     \param values Pointer to an array of integers that represents semaphores values.
00106     \return The function may return one of the followinf values:
00107             <ul>
00108               <li>SET_SEM_VALUES_OK: The operation was sucessful.
00109               <li>SET_SEM_VALUES_SEM_NOT_CREATED: You did not create (or get) the set of semaphores.
00110               <li>SET_SEM_VALUES_SET_ERROR: An error occured while setting the semaphores' values.
00111             </ul>
00112     \warning The number of elements of the array pointed by 'values' must be equal to the number of semaphores in the
00113              set.
00114  */
00115 
00116 int set_semaphore_values (int *values)
00117 {
00118    int          i;
00119    union semun  sem_def;
00120 
00121    if ((set_size == -1) || (semaphore_set == -1)) { return SET_SEM_VALUES_SEM_NOT_CREATED; }
00122 
00123    for (i=0; i<set_size; i++)
00124    {
00125      sem_def.val = values[i];
00126      if (semctl (semaphore_set, i, SETVAL, sem_def) == -1)
00127      { return SET_SEM_VALUES_SET_ERROR; }
00128    }
00129 
00130    return SET_SEM_VALUES_OK;
00131 }
00132 
00133 /*! \example test_shm.c
00134     This file shows how to use the function set_semaphore_values().
00135  */
00136 
00137 /*! \brief Set the value of one semaphore (and only one of the set).
00138     \param value Integer that represents the semaphore's new value.
00139     \sem_number Integer that represents the semaphore's index (within the set of semaphores).
00140     \return The function may return one of the followinf values:
00141             <ul>
00142               <li>SET_SEM_VALUES_OK: The operation was sucessful.
00143               <li>SET_SEM_VALUES_SEM_NOT_CREATED: You did not create (or get) the set of semaphores.
00144               <li>SET_SEM_VALUES_SET_ERROR: An error occured while setting the semaphores' values.
00145             </ul>
00146     Please note that the functions set_semaphore_value() and set_semaphore_values() share the same set of return values.
00147  */
00148 
00149 int set_semaphore_value (int value, int sem_number)
00150 {
00151    union semun  sem_def;
00152 
00153    if ((set_size == -1) || (semaphore_set == -1)) { return SET_SEM_VALUES_SEM_NOT_CREATED; }
00154 
00155    sem_def.val = value;
00156    if (semctl (semaphore_set, sem_number, SETVAL, sem_def) == -1)
00157    { return SET_SEM_VALUES_SET_ERROR; }
00158 
00159    return SET_SEM_VALUES_OK;
00160 }
00161 
00162 /*! \example test_shm.c
00163     This file shows how to use the function set_semaphore_value().
00164  */
00165 
00166 /*! \brief Take one semaphore. This action decrements the semaphore's counter by 1.
00167     \param sem_idx Index of the semaphore to take. The index of the first semaphore is 0.
00168     \return Upon successful completion, 0 is returned. Otherwise, -1 is returned.
00169     \warning If the set of semaphores you created contains N semaphores, then &quot;0 &lt;= sem_idx &lt; N&quot;.
00170  */
00171 
00172 int take_sem (int sem_idx)
00173 {
00174   struct sembuf   Operation;
00175 
00176   Operation.sem_num = sem_idx;
00177   Operation.sem_flg = SEM_UNDO;
00178   Operation.sem_op  = -1;
00179 
00180   return (semop(semaphore_set, &Operation, 1));
00181 }
00182 
00183 /*! \example test_shm.c
00184     This file shows how to use the function take_sem().
00185  */
00186 
00187 /*! \brief Release one semaphore. This action increments the semaphore's counter by 1.
00188     \param sem_idx Index of the semaphore to take. The index of the first semaphore is 0.
00189     \return Upon successful completion, 0 is returned. Otherwise, -1 is returned.
00190     \warning If the set of semaphores you created contains N semaphores, then &quot;0 &lt;= sem_idx &lt; N&quot;.
00191              Please note that we do <B>NOT</B> specify the semaphore's flag <U>SEM_UNDO</U>. If you specify this flag,
00192              then you will have the following behaviour: when the program exits, the operation will be canceled. 
00193              Here the operation is &quot;release the semaphore&quot;. So, if we set SEM_UNDO, and if the process exists,
00194              then the operation will be canceled: in other words, the semaphore will be taken (the oposite of released). 
00195  */
00196 
00197 int release_sem (int sem_idx)
00198 {
00199   struct sembuf   Operation;
00200 
00201   Operation.sem_num = sem_idx;
00202   Operation.sem_op  = +1;
00203 
00204   return (semop(semaphore_set, &Operation, 1));
00205 }
00206 
00207 /*! \example test_shm.c
00208     This file shows how to use the function release_sem().
00209  */
00210 
00211 /*! \brief Destroy the set of semaphores.
00212     \return Upon successful completion, a positive value is returned. Otherwise, -1 is returned.
00213  */
00214 
00215 int destroy_semaphore_set()
00216 { return (semctl (semaphore_set, 0, IPC_RMID, 0)); }
00217 
00218 /*! \example test_shm.c
00219     This file shows how to use the function destroy_semaphore_set().
00220  */

Generated on Thu Apr 3 16:23:43 2003 for Common_C_libraries by doxygen1.3-rc1