+/*
+ *
+ * The Storage daemon has three locking concepts that must be
+ * understood:
+ *
+ * 1. dblock blocking the device, which means that the device
+ * is "marked" in use. When setting and removing the
+ block, the device is locked, but after dblock is
+ called the device is unlocked.
+ * 2. dlock() simple mutex that locks the device structure. A dlock
+ * can be acquired while a device is blocked if it is not
+ * locked.
+ * 3. r_dlock "recursive" dlock, when means that a dlock (mutex)
+ * will be acquired on the device if it is not blocked
+ * by some other thread. If the device was blocked by
+ * the current thread, it will acquire the lock.
+ * If some other thread has set a block on the device,
+ * this call will wait until the device is unblocked.
+ *
+ * A lock is normally set when modifying the device structure.
+ * A r_lock is normally acquired when you want to block the device
+ * i.e. it will wait until the device is not blocked.
+ * A block is normally set during long operations like writing to
+ * the device.
+ * If you are writing the device, you will normally block and
+ * lock it.
+ * A lock cannot be violated. No other thread can touch the
+ * device while a lock is set.
+ * When a block is set, every thread accept the thread that set
+ * the block will block if r_dlock is called.
+ * A device can be blocked for multiple reasons, labeling, writing,
+ * acquiring (opening) the device, waiting for the operator, unmounted,
+ * ...
+ * Under certain conditions the block that is set on a device can be
+ * stolen and the device can be used by another thread. For example,
+ * a device is blocked because it is waiting for the operator to
+ * mount a tape. The operator can then unmount the device, and label
+ * a tape, re-mount it, give back the block, and the job will continue.
+ *
+ *
+ * Functions:
+ *
+ * DEVICE::dlock() does P(m_mutex) (in dev.h)
+ * DEVICE::dunlock() does V(m_mutex)
+ *
+ * DEVICE::r_dlock() allows locking the device when this thread
+ already has the device blocked.
+ * dlock()
+ * if blocked and not same thread that locked
+ * pthread_cond_wait
+ * leaves device locked
+ *
+ * DEVICE::r_dunlock() unlocks but does not unblock
+ * same as dunlock();
+ *
+ * DEVICE::dblock(why) does
+ * r_dlock(); (recursive device lock)
+ * block_device(this, why)
+ * r_dunlock()
+ *
+ * DEVICE::dunblock does
+ * dlock()
+ * unblock_device()
+ * dunlock()
+ *
+ * block_device() does (must be locked and not blocked at entry)
+ * set blocked status
+ * set our pid
+ *
+ * unblock_device() does (must be blocked at entry)
+ * (locked on entry)
+ * (locked on exit)
+ * set unblocked status
+ * clear pid
+ * if waiting threads
+ * pthread_cond_broadcast
+ *
+ * steal_device_lock() does (must be locked and blocked at entry)
+ * save status
+ * set new blocked status
+ * set new pid
+ * unlock()
+ *
+ * give_back_device_lock() does (must be blocked but not locked)
+ * dlock()
+ * reset blocked status
+ * save previous blocked
+ * reset pid
+ * if waiting threads
+ * pthread_cond_broadcast
+ *
+ */
+
+
+void DEVICE::dblock(int why)