diff options
Diffstat (limited to 'src/microhttpd/mhd_sem.c')
-rw-r--r-- | src/microhttpd/mhd_sem.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/microhttpd/mhd_sem.c b/src/microhttpd/mhd_sem.c new file mode 100644 index 00000000..fdd5dbe4 --- /dev/null +++ b/src/microhttpd/mhd_sem.c @@ -0,0 +1,138 @@ +/* + This file is part of libmicrohttpd + Copyright (C) 2016 Christian Grothoff + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +*/ + +/** + * @file microhttpd/mhd_sem.c + * @brief implementation of semaphores + * @author Christian Grothoff + */ +#include "internal.h" +#include "mhd_locks.h" + +/** + * A semaphore. + */ +struct MHD_Semaphore +{ + /** + * Mutex we use internally. + */ + pthread_mutex_t mutex; + + /** + * Condition variable used to implement the semaphore. + */ + pthread_cond_t cv; + + /** + * Current value of the semaphore. + */ + unsigned int counter; +}; + + +/** + * Create a semaphore with an initial counter of @a init + * + * @param init initial counter + * @return the semaphore, NULL on error + */ +struct MHD_Semaphore * +MHD_semaphore_create (unsigned int init) +{ + struct MHD_Semaphore *sem; + + sem = malloc (sizeof (struct MHD_Semaphore)); + if (NULL == sem) + return NULL; + sem->counter = init; + if (0 != pthread_mutex_init (&sem->mutex, + NULL)) + { + free (sem); + return NULL; + } + if (0 != pthread_cond_init (&sem->cv, + NULL)) + { + (void) pthread_mutex_destroy (&sem->mutex); + free (sem); + return NULL; + } + return sem; +} + + +/** + * Count down the semaphore, block if necessary. + * + * @param sem semaphore to count down. + */ +void +MHD_semaphore_down (struct MHD_Semaphore *sem) +{ + if (! pthread_mutex_lock (&sem->mutex)) + MHD_PANIC ("pthread_mutex_lock for semaphore failed\n"); + while (0 == sem->counter) + { + if (0 != pthread_cond_wait (&sem->cv, + &sem->mutex)) + MHD_PANIC ("pthread_cond_wait failed\n"); + } + sem->counter--; + if (! pthread_mutex_unlock (&sem->mutex)) + MHD_PANIC ("pthread_mutex_unlock for semaphore failed\n"); +} + + +/** + * Increment the semaphore. + * + * @param sem semaphore to increment. + */ +void +MHD_semaphore_up (struct MHD_Semaphore *sem) +{ + if (! pthread_mutex_lock (&sem->mutex)) + MHD_PANIC ("pthread_mutex_lock for semaphore failed\n"); + sem->counter++; + pthread_cond_signal (&sem->cv); + if (! pthread_mutex_unlock (&sem->mutex)) + MHD_PANIC ("pthread_mutex_unlock for semaphore failed\n"); +} + + +/** + * Destroys the semaphore. + * + * @param sem semaphore to destroy. + */ +void +MHD_semaphore_destroy (struct MHD_Semaphore *sem) +{ + if (0 != pthread_cond_destroy (&sem->cv)) + MHD_PANIC ("pthread_cond_destroy failed\n"); + if (0 != pthread_mutex_destroy (&sem->mutex)) + MHD_PANIC ("pthread_mutex_destroy failed\n"); + free (sem); +} + + +/* end of mhd_sem.c */ |