home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-parisc / semaphore.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  3.8 KB  |  145 lines

  1. /*    SMP- and interrupt-safe semaphores.
  2.  *    PA-RISC version by Matthew Wilcox
  3.  *
  4.  *    Linux/PA-RISC Project (http://www.parisc-linux.org/)
  5.  *    Copyright (C) 1996 Linus Torvalds
  6.  *    Copyright (C) 1999-2001 Matthew Wilcox < willy at debian d0T org >
  7.  *    Copyright (C) 2000 Grant Grundler < grundler a debian org >
  8.  *
  9.  *    This program is free software; you can redistribute it and/or modify
  10.  *    it under the terms of the GNU General Public License as published by
  11.  *    the Free Software Foundation; either version 2 of the License, or
  12.  *    (at your option) any later version.
  13.  *
  14.  *    This program is distributed in the hope that it will be useful,
  15.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  *    GNU General Public License for more details.
  18.  *
  19.  *    You should have received a copy of the GNU General Public License
  20.  *    along with this program; if not, write to the Free Software
  21.  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22.  */
  23.  
  24. #ifndef _ASM_PARISC_SEMAPHORE_H
  25. #define _ASM_PARISC_SEMAPHORE_H
  26.  
  27. #include <linux/spinlock.h>
  28. #include <linux/wait.h>
  29. #include <linux/rwsem.h>
  30.  
  31. #include <asm/system.h>
  32.  
  33. /*
  34.  * The `count' is initialised to the number of people who are allowed to
  35.  * take the lock.  (Normally we want a mutex, so this is `1').  if
  36.  * `count' is positive, the lock can be taken.  if it's 0, no-one is
  37.  * waiting on it.  if it's -1, at least one task is waiting.
  38.  */
  39. struct semaphore {
  40.     spinlock_t    sentry;
  41.     int        count;
  42.     wait_queue_head_t wait;
  43. };
  44.  
  45. #define __SEMAPHORE_INITIALIZER(name, n)                \
  46. {                                    \
  47.     .sentry        = SPIN_LOCK_UNLOCKED,                \
  48.     .count        = n,                        \
  49.     .wait        = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
  50. }
  51.  
  52. #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
  53.     struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
  54.  
  55. #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
  56. #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
  57.  
  58. extern inline void sema_init (struct semaphore *sem, int val)
  59. {
  60.     *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
  61. }
  62.  
  63. static inline void init_MUTEX (struct semaphore *sem)
  64. {
  65.     sema_init(sem, 1);
  66. }
  67.  
  68. static inline void init_MUTEX_LOCKED (struct semaphore *sem)
  69. {
  70.     sema_init(sem, 0);
  71. }
  72.  
  73. static inline int sem_getcount(struct semaphore *sem)
  74. {
  75.     return sem->count;
  76. }
  77.  
  78. asmlinkage void __down(struct semaphore * sem);
  79. asmlinkage int  __down_interruptible(struct semaphore * sem);
  80. asmlinkage void __up(struct semaphore * sem);
  81.  
  82. /* Semaphores can be `tried' from irq context.  So we have to disable
  83.  * interrupts while we're messing with the semaphore.  Sorry.
  84.  */
  85.  
  86. extern __inline__ void down(struct semaphore * sem)
  87. {
  88.     might_sleep();
  89.     spin_lock_irq(&sem->sentry);
  90.     if (sem->count > 0) {
  91.         sem->count--;
  92.     } else {
  93.         __down(sem);
  94.     }
  95.     spin_unlock_irq(&sem->sentry);
  96. }
  97.  
  98. extern __inline__ int down_interruptible(struct semaphore * sem)
  99. {
  100.     int ret = 0;
  101.     might_sleep();
  102.     spin_lock_irq(&sem->sentry);
  103.     if (sem->count > 0) {
  104.         sem->count--;
  105.     } else {
  106.         ret = __down_interruptible(sem);
  107.     }
  108.     spin_unlock_irq(&sem->sentry);
  109.     return ret;
  110. }
  111.  
  112. /*
  113.  * down_trylock returns 0 on success, 1 if we failed to get the lock.
  114.  * May not sleep, but must preserve irq state
  115.  */
  116. extern __inline__ int down_trylock(struct semaphore * sem)
  117. {
  118.     int flags, count;
  119.  
  120.     spin_lock_irqsave(&sem->sentry, flags);
  121.     count = sem->count - 1;
  122.     if (count >= 0)
  123.         sem->count = count;
  124.     spin_unlock_irqrestore(&sem->sentry, flags);
  125.     return (count < 0);
  126. }
  127.  
  128. /*
  129.  * Note! This is subtle. We jump to wake people up only if
  130.  * the semaphore was negative (== somebody was waiting on it).
  131.  */
  132. extern __inline__ void up(struct semaphore * sem)
  133. {
  134.     int flags;
  135.     spin_lock_irqsave(&sem->sentry, flags);
  136.     if (sem->count < 0) {
  137.         __up(sem);
  138.     } else {
  139.         sem->count++;
  140.     }
  141.     spin_unlock_irqrestore(&sem->sentry, flags);
  142. }
  143.  
  144. #endif /* _ASM_PARISC_SEMAPHORE_H */
  145.