]> git.proxmox.com Git - mirror_spl-debian.git/blobdiff - include/sys/condvar.h
New upstream version 0.7.11
[mirror_spl-debian.git] / include / sys / condvar.h
index fd845d9c1995574aa917ac62d98a3c213b57deaf..ce3149aa19f25cfa5f63c506b1bd6f50aad658ca 100644 (file)
-#ifndef _SPL_CONDVAR_H
-#define _SPL_CONDVAR_H
+/*
+ *  Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
+ *  Copyright (C) 2007 The Regents of the University of California.
+ *  Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
+ *  Written by Brian Behlendorf <behlendorf1@llnl.gov>.
+ *  UCRL-CODE-235197
+ *
+ *  This file is part of the SPL, Solaris Porting Layer.
+ *  For details, see <http://zfsonlinux.org/>.
+ *
+ *  The SPL is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  The SPL 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 General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with the SPL.  If not, see <http://www.gnu.org/licenses/>.
+ */
 
-#ifdef  __cplusplus
-extern "C" {
-#endif
+#ifndef _SPL_CONDVAR_H
+#define        _SPL_CONDVAR_H
 
 #include <linux/module.h>
-#include <linux/wait.h>
-
-/* The kcondvar_t struct is protected by mutex taken externally before
+#include <linux/wait_compat.h>
+#include <linux/delay_compat.h>
+#include <sys/kmem.h>
+#include <sys/mutex.h>
+#include <sys/callo.h>
+#include <sys/time.h>
+
+/*
+ * The kcondvar_t struct is protected by mutex taken externally before
  * calling any of the wait/signal funs, and passed into the wait funs.
  */
-#define CV_MAGIC                       0x346545f4
-#define CV_POISON                      0x95
+#define        CV_MAGIC                        0x346545f4
+#define        CV_DESTROY                      0x346545f5
 
 typedef struct {
        int cv_magic;
-       char *cv_name;
-       wait_queue_head_t cv_event;
+       spl_wait_queue_head_t cv_event;
+       spl_wait_queue_head_t cv_destroy;
+       atomic_t cv_refs;
        atomic_t cv_waiters;
-       kmutex_t *cv_mutex; /* only for verification purposes */
-       spinlock_t cv_lock;
+       kmutex_t *cv_mutex;
 } kcondvar_t;
 
-typedef enum { CV_DEFAULT=0, CV_DRIVER } kcv_type_t;
-
-static __inline__ void
-cv_init(kcondvar_t *cvp, char *name, kcv_type_t type, void *arg)
-{
-       ASSERT(cvp);
-       ASSERT(type == CV_DEFAULT);
-       ASSERT(arg == NULL);
-
-       cvp->cv_magic = CV_MAGIC;
-       init_waitqueue_head(&cvp->cv_event);
-       spin_lock_init(&cvp->cv_lock);
-       atomic_set(&cvp->cv_waiters, 0);
-       cvp->cv_mutex = NULL;
-       cvp->cv_name = NULL;
-
-       if (name) {
-               cvp->cv_name = kmalloc(strlen(name) + 1, GFP_KERNEL);
-               if (cvp->cv_name)
-                       strcpy(cvp->cv_name, name);
-       }
-}
-
-static __inline__ void
-cv_destroy(kcondvar_t *cvp)
-{
-       ASSERT(cvp);
-       ASSERT(cvp->cv_magic == CV_MAGIC);
-       spin_lock(&cvp->cv_lock);
-       ASSERT(atomic_read(&cvp->cv_waiters) == 0);
-       ASSERT(!waitqueue_active(&cvp->cv_event));
-
-       if (cvp->cv_name)
-               kfree(cvp->cv_name);
-
-       memset(cvp, CV_POISON, sizeof(*cvp));
-       spin_unlock(&cvp->cv_lock);
-}
-
-static __inline__ void
-cv_wait(kcondvar_t *cvp, kmutex_t *mtx)
-{
-       DEFINE_WAIT(wait);
-
-       ASSERT(cvp);
-        ASSERT(mtx);
-       ASSERT(cvp->cv_magic == CV_MAGIC);
-       spin_lock(&cvp->cv_lock);
-       ASSERT(mutex_owned(mtx));
-
-       if (cvp->cv_mutex == NULL)
-               cvp->cv_mutex = mtx;
-
-       /* Ensure the same mutex is used by all callers */
-       ASSERT(cvp->cv_mutex == mtx);
-       spin_unlock(&cvp->cv_lock);
-
-       prepare_to_wait_exclusive(&cvp->cv_event, &wait,
-                                 TASK_UNINTERRUPTIBLE);
-       atomic_inc(&cvp->cv_waiters);
-
-       /* Mutex should be dropped after prepare_to_wait() this
-        * ensures we're linked in to the waiters list and avoids the
-        * race where 'cvp->cv_waiters > 0' but the list is empty. */
-       mutex_exit(mtx);
-       schedule();
-       mutex_enter(mtx);
-
-       atomic_dec(&cvp->cv_waiters);
-       finish_wait(&cvp->cv_event, &wait);
-}
-
-/* 'expire_time' argument is an absolute wall clock time in jiffies.
- * Return value is time left (expire_time - now) or -1 if timeout occurred.
- */
-static __inline__ clock_t
-cv_timedwait(kcondvar_t *cvp, kmutex_t *mtx, clock_t expire_time)
-{
-       DEFINE_WAIT(wait);
-       clock_t time_left;
-
-       ASSERT(cvp);
-        ASSERT(mtx);
-       ASSERT(cvp->cv_magic == CV_MAGIC);
-       spin_lock(&cvp->cv_lock);
-       ASSERT(mutex_owned(mtx));
-
-       if (cvp->cv_mutex == NULL)
-               cvp->cv_mutex = mtx;
-
-       /* Ensure the same mutex is used by all callers */
-       ASSERT(cvp->cv_mutex == mtx);
-       spin_unlock(&cvp->cv_lock);
-
-       /* XXX - Does not handle jiffie wrap properly */
-       time_left = expire_time - jiffies;
-       if (time_left <= 0)
-               return -1;
-
-       prepare_to_wait_exclusive(&cvp->cv_event, &wait,
-                                 TASK_UNINTERRUPTIBLE);
-       atomic_inc(&cvp->cv_waiters);
-
-       /* Mutex should be dropped after prepare_to_wait() this
-        * ensures we're linked in to the waiters list and avoids the
-        * race where 'cvp->cv_waiters > 0' but the list is empty. */
-       mutex_exit(mtx);
-       time_left = schedule_timeout(time_left);
-       mutex_enter(mtx);
-
-       atomic_dec(&cvp->cv_waiters);
-       finish_wait(&cvp->cv_event, &wait);
-
-       return (time_left > 0 ? time_left : -1);
-}
-
-static __inline__ void
-cv_signal(kcondvar_t *cvp)
-{
-       ASSERT(cvp);
-       ASSERT(cvp->cv_magic == CV_MAGIC);
-
-       /* All waiters are added with WQ_FLAG_EXCLUSIVE so only one
-        * waiter will be set runable with each call to wake_up().
-        * Additionally wake_up() holds a spin_lock assoicated with
-        * the wait queue to ensure we don't race waking up processes. */
-       if (atomic_read(&cvp->cv_waiters) > 0)
-               wake_up(&cvp->cv_event);
-}
-
-static __inline__ void
-cv_broadcast(kcondvar_t *cvp)
-{
-       ASSERT(cvp);
-       ASSERT(cvp->cv_magic == CV_MAGIC);
+typedef enum { CV_DEFAULT = 0, CV_DRIVER } kcv_type_t;
+
+extern void __cv_init(kcondvar_t *, char *, kcv_type_t, void *);
+extern void __cv_destroy(kcondvar_t *);
+extern void __cv_wait(kcondvar_t *, kmutex_t *);
+extern void __cv_wait_io(kcondvar_t *, kmutex_t *);
+extern void __cv_wait_sig(kcondvar_t *, kmutex_t *);
+extern clock_t __cv_timedwait(kcondvar_t *, kmutex_t *, clock_t);
+extern clock_t __cv_timedwait_io(kcondvar_t *, kmutex_t *, clock_t);
+extern clock_t __cv_timedwait_sig(kcondvar_t *, kmutex_t *, clock_t);
+extern clock_t cv_timedwait_hires(kcondvar_t *, kmutex_t *, hrtime_t,
+    hrtime_t res, int flag);
+extern clock_t cv_timedwait_sig_hires(kcondvar_t *, kmutex_t *, hrtime_t,
+    hrtime_t res, int flag);
+extern void __cv_signal(kcondvar_t *);
+extern void __cv_broadcast(kcondvar_t *c);
+
+#define        cv_init(cvp, name, type, arg)           __cv_init(cvp, name, type, arg)
+#define        cv_destroy(cvp)                         __cv_destroy(cvp)
+#define        cv_wait(cvp, mp)                        __cv_wait(cvp, mp)
+#define        cv_wait_io(cvp, mp)                     __cv_wait_io(cvp, mp)
+#define        cv_wait_sig(cvp, mp)                    __cv_wait_sig(cvp, mp)
+#define        cv_wait_interruptible(cvp, mp)          cv_wait_sig(cvp, mp)
+#define        cv_timedwait(cvp, mp, t)                __cv_timedwait(cvp, mp, t)
+#define        cv_timedwait_io(cvp, mp, t)             __cv_timedwait_io(cvp, mp, t)
+#define        cv_timedwait_sig(cvp, mp, t)            __cv_timedwait_sig(cvp, mp, t)
+#define        cv_timedwait_interruptible(cvp, mp, t)  cv_timedwait_sig(cvp, mp, t)
+#define        cv_signal(cvp)                          __cv_signal(cvp)
+#define        cv_broadcast(cvp)                       __cv_broadcast(cvp)
 
-       /* Wake_up_all() will wake up all waiters even those which
-        * have the WQ_FLAG_EXCLUSIVE flag set. */
-       if (atomic_read(&cvp->cv_waiters) > 0)
-               wake_up_all(&cvp->cv_event);
-}
 #endif /* _SPL_CONDVAR_H */