1 /* 2 * Copyright (c) 2008-2013 Zmanda, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * for more details. 13 * 14 * You should have received a copy of the GNU General Public License along 15 * with this program; if not, write to the Free Software Foundation, Inc., 16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 * 18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300 19 * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com 20 */ 21 22 /* GLib does not provide semaphores, which are useful in queue.c. 23 So, we implement it here. */ 24 25 #include <glib.h> 26 27 #ifndef SEMAPHORE_H 28 29 typedef struct { 30 int value; 31 GMutex *mutex; 32 GCond * decrement_cond; 33 GCond * zero_cond; 34 } amsemaphore_t; 35 36 /* Create a new semaphore object with the given value. 37 * 38 * @param value: new value 39 * @returns: newly allocated amsemaphore_t 40 */ 41 amsemaphore_t* amsemaphore_new_with_value(int value); 42 43 /* Shortcut to make a new semaphore with value 1. 44 */ 45 #define amsemaphore_new() amsemaphore_new_with_value(1) 46 47 /* Free a semaphore allocated by amsemaphore_with_new_value(). Be sure the 48 * semaphore is no longer in use by any threads. 49 * 50 * @param sem: the semaphore to free 51 */ 52 void amsemaphore_free(amsemaphore_t *sem); 53 54 /* Increment the value of the semaphore by incr. This corresponds to 55 * Dijkstra's V(), or the typical semaphore's release(). 56 * 57 * This function will not block, but may wake other threads waiting 58 * on amsemaphore_decrement(). 59 * 60 * @param sem: the semaphore 61 * @param incr: added to the semaphore's value 62 */ 63 void amsemaphore_increment(amsemaphore_t *sem, unsigned int incr); 64 65 /* Shortcut to increment the semaphore by 1. 66 */ 67 #define amsemaphore_up(semaphore) amsemaphore_increment(semaphore,1) 68 69 /* Decrement the value of the semaphore by incr. If this operation 70 * would make the semaphore negative, block until the semaphore 71 * value is large enough, then perform the decerement operation. Threads 72 * waiting on amsemaphore_wait_empty() may be awakened if the value 73 * reaches 0. 74 * 75 * @param sem: the semaphore 76 * @param decr: subtracted from the semaphore's value 77 */ 78 void amsemaphore_decrement(amsemaphore_t *sem, unsigned int decr); 79 80 /* Shortcut to decrement the semaphore by 1. 81 */ 82 #define amsemaphore_down(semaphore) amsemaphore_decrement(semaphore, 1) 83 84 /* Increment or decrement (with a negative incr) the value without 85 * blocking. Threads waiting on amsemaphore_decrement() or 86 * amsemaphore_wait_empty() will be awakened if necessary. 87 * 88 * @param sem: the semaphore 89 * @param incr: added to the semaphore's value 90 */ 91 void amsemaphore_force_adjust(amsemaphore_t *sem, int incr); 92 93 /* Set the semaphore to a given value without blocking. Threads 94 * waiting on amsemaphore_decrement() or amsemaphore_wait_empty() 95 * will be awakened if necessary. 96 * 97 * @param sem: the semaphore 98 * @param value: the new value 99 */ 100 void amsemaphore_force_set(amsemaphore_t *sem, int value); 101 102 /* Block until the semaphore's value is zero. 103 * 104 * @param sem: the semaphore 105 */ 106 void amsemaphore_wait_empty(amsemaphore_t *sem); 107 108 #endif /* SEMAPHORE_H */ 109