summaryrefslogtreecommitdiff
path: root/src/lock.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lock.cc')
-rw-r--r--src/lock.cc206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/lock.cc b/src/lock.cc
new file mode 100644
index 0000000..9c78783
--- /dev/null
+++ b/src/lock.cc
@@ -0,0 +1,206 @@
+/*
+ * ip tunnel/ethertap device for MacOSX.
+ *
+ * Locking implementation.
+ */
+/*
+ * Copyright (c) 2011 Mattias Nissler <mattias.nissler@gmx.de>
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted
+ * provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this list of
+ * conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "lock.h"
+
+extern "C" {
+
+#include <kern/clock.h>
+
+#include <sys/syslog.h>
+#include <sys/proc.h>
+
+}
+
+#if 0
+#define dprintf(...) log(LOG_INFO, __VA_ARGS__)
+#else
+#define dprintf(...)
+#endif
+
+/* class tt_lock */
+lck_grp_t *tt_lock::tt_lck_grp = NULL;
+
+bool
+tt_lock::initialize()
+{
+ /* init if necessary */
+ if (tt_lck_grp == NULL) {
+ dprintf("initing lock group\n");
+ tt_lck_grp = lck_grp_alloc_init("tuntap locks", LCK_GRP_ATTR_NULL);
+
+ if (tt_lck_grp == NULL) {
+ /* if something fails, the lock won't work */
+ log(LOG_ERR, "tuntap: could not allocate locking group\n");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void
+tt_lock::shutdown()
+{
+ /* free the locking group */
+ if (tt_lck_grp != NULL) {
+ dprintf("freeing lock group\n");
+ lck_grp_free(tt_lck_grp);
+ tt_lck_grp = NULL;
+ }
+}
+
+/* tt_mutex */
+tt_mutex::tt_mutex()
+{
+ /* fail if locking group not initialized */
+ if (tt_lck_grp == NULL)
+ return;
+
+ /* allocate the lock */
+ lck = lck_rw_alloc_init(tt_lck_grp, NULL);
+
+ if (lck == NULL)
+ log(LOG_ERR, "tuntap: could not allocate mutex\n");
+}
+
+tt_mutex::~tt_mutex()
+{
+ /* if the lock doesn't exist, this will be a no-op */
+ if (lck == NULL)
+ return;
+
+ /* free the lock */
+ lck_rw_free(lck, tt_lck_grp);
+}
+
+void
+tt_mutex::lock()
+{
+ if (lck != NULL)
+ lck_rw_lock_exclusive(lck);
+}
+
+void
+tt_mutex::unlock()
+{
+ if (lck != NULL)
+ lck_rw_unlock_exclusive(lck);
+}
+
+void
+tt_mutex::sleep(void *cond)
+{
+ if (lck != NULL)
+ lck_rw_sleep(lck, LCK_SLEEP_DEFAULT, cond, THREAD_INTERRUPTIBLE);
+}
+
+void
+tt_mutex::sleep(void *cond, uint64_t nanoseconds)
+{
+ if (lck != NULL) {
+ uint64_t abstime;
+ nanoseconds_to_absolutetime(nanoseconds, &abstime);
+ lck_rw_sleep_deadline(lck, LCK_SLEEP_DEFAULT, cond, THREAD_INTERRUPTIBLE, abstime);
+ }
+}
+
+void
+tt_mutex::wakeup(void *cond)
+{
+ if (lck != NULL)
+ ::wakeup(cond);
+}
+
+/* tt_gate */
+tt_gate::tt_gate()
+ : ticket_number(0),
+ population(0)
+{
+}
+
+void
+tt_gate::enter()
+{
+ /* just try to grab the lock, increase the ticket number and the population */
+ auto_lock l(&slock);
+ ticket_number++;
+ population++;
+}
+
+void
+tt_gate::exit()
+{
+ auto_lock l(&slock);
+ ticket_number--;
+ population--;
+}
+
+bool
+tt_gate::is_anyone_in()
+{
+ return population != 0;
+}
+
+unsigned int
+tt_gate::get_ticket_number()
+{
+ return ticket_number;
+}
+
+void
+tt_gate::lock()
+{
+ slock.lock();
+}
+
+void
+tt_gate::unlock()
+{
+ slock.unlock();
+}
+
+void
+tt_gate::sleep(void* cond)
+{
+ slock.sleep(cond);
+}
+
+void
+tt_gate::sleep(void* cond, uint64_t nanoseconds)
+{
+ slock.sleep(cond, nanoseconds);
+}
+
+void
+tt_gate::wakeup(void* cond)
+{
+ slock.wakeup(cond);
+}
+