1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2000-2001 Silicon Graphics, Inc.  All rights reserved
7 *
8 * This implemenation of synchronization variables is heavily based on
9 * one done by Steve Lord <lord@sgi.com>
10 *
11 * Paul Cassella <pwc@sgi.com>
12 */
13
14#ifndef _ASM_IA64_SN_SV_H
15#define _ASM_IA64_SN_SV_H
16
17#include <linux/spinlock.h>
18#include <asm/semaphore.h>
19
20#ifndef ASSERT
21
22#define ASSERT(x) do {							  \
23                    if(!(x)) {						  \
24		      printk(KERN_ERR "%s\n", "Assertion failed: " # x);  \
25		      BUG();						  \
26		    }							  \
27                  } while(0)
28#define _SV_ASSERT
29#endif
30
31typedef void sv_mon_lock_t;
32typedef void (*sv_mon_unlock_func_t)(sv_mon_lock_t *lock);
33
34/* sv_flags values: */
35
36#define SV_ORDER_FIFO        0x001
37#define SV_ORDER_FILO        0x002
38#define SV_ORDER_LIFO        SV_ORDER_FILO
39
40/* If at some point one order becomes preferable to others, we can
41   switch to it if the caller of sv_init doesn't specify. */
42#define SV_ORDER_DEFAULT     SV_ORDER_FIFO
43
44#define SV_ORDER_MASK        0x00f
45
46
47#define SV_MON_SEMA          0x010
48#define SV_MON_SPIN          0x020
49
50#define SV_MON_MASK          0x0f0
51
52
53/*
54   If the monitor lock can be aquired from interrupts.  Note that this
55   is a superset of the cases in which the sv can be touched from
56   interrupts.
57
58   This is currently only valid when the monitor lock is a spinlock.
59
60   If this is used, sv_wait, sv_signal, and sv_broadcast must all be
61   called with interrupts disabled, which has to happen anyway to have
62   acquired the monitor spinlock.
63 */
64#define SV_INTS              0x100
65
66/* ditto for bottom halves */
67#define SV_BHS               0x200
68
69
70
71/* sv_wait_flag values: */
72#define SV_WAIT_SIG          0x001 /* Allow sv_wait to be interrupted by a signal */
73
74typedef struct sv_s {
75	wait_queue_head_t sv_waiters;
76	sv_mon_lock_t *sv_mon_lock;   /* Lock held for exclusive access to monitor. */
77	sv_mon_unlock_func_t sv_mon_unlock_func;
78	spinlock_t sv_lock;  /* Spinlock protecting the sv itself. */
79	int sv_flags;
80} sv_t;
81
82#define DECLARE_SYNC_VARIABLE(sv, l, f) sv_t sv = sv_init(&sv, l, f)
83
84/*
85 * @sv the sync variable to initialize
86 * @monitor_lock the lock enforcing exclusive running in the monitor
87 * @flags one of
88 *   SV_MON_SEMA monitor_lock is a semaphore
89 *   SV_MON_SPIN monitor_lock is a spinlock
90 * and a bitwise or of some subset of
91 *   SV_INTS - the monitor lock can be acquired from interrupts (and
92 *             hence, whenever we hold it, interrupts are disabled or
93 *             we're in an interrupt.)  This is only valid when
94 *             SV_MON_SPIN is set.
95 */
96void sv_init(sv_t *sv, sv_mon_lock_t *monitor_lock, int flags);
97
98/*
99 * Set SV_WAIT_SIG in sv_wait_flags to let the sv_wait be interrupted by signals.
100 *
101 * timeout is how long to wait before giving up, or 0 to wait
102 * indefinately.  It is given in jiffies, and is relative.
103 *
104 * The associated lock must be locked on entry.  It is unlocked on return.
105 *
106 * Return values:
107 *
108 * n < 0 : interrupted,  -n jiffies remaining on timeout, or -1 if timeout == 0
109 * n = 0 : timeout expired
110 * n > 0 : sv_signal()'d, n jiffies remaining on timeout, or 1 if timeout == 0
111 */
112extern signed long sv_wait(sv_t *sv, int sv_wait_flags,
113			   unsigned long timeout /* relative jiffies */);
114
115static inline int sv_wait_compat(sv_t *sv, sv_mon_lock_t *lock, int sv_wait_flags,
116				 unsigned long timeout, int sv_mon_type)
117{
118	ASSERT(sv_mon_type == (sv->sv_flags & SV_MON_MASK));
119	if(sv->sv_mon_lock)
120		ASSERT(lock == sv->sv_mon_lock);
121	else
122		sv->sv_mon_lock = lock;
123
124	return sv_wait(sv, sv_wait_flags, timeout);
125}
126
127
128/* These work like Irix's sv_wait() and sv_wait_sig(), except the
129   caller must call the one correpsonding to the type of the monitor
130   lock. */
131#define sv_spin_wait(sv, lock)                              \
132        sv_wait_compat(sv, lock, 0, 0, SV_MON_SPIN)
133#define sv_spin_wait_sig(sv, lock)                          \
134        sv_wait_compat(sv, lock, SV_WAIT_SIG, 0, SV_MON_SPIN)
135
136#define sv_sema_wait(sv, lock)                              \
137        sv_wait_compat(sv, lock, 0, 0, SV_MON_SEMA)
138#define sv_sema_wait_sig(sv, lock)                          \
139        sv_wait_compat(sv, lock, SV_WAIT_SIG, 0, SV_MON_SEMA)
140
141/* These work as in Irix. */
142void sv_signal(sv_t *sv);
143void sv_broadcast(sv_t *sv);
144
145/* This works as in Irix. */
146void sv_destroy(sv_t *sv);
147
148#ifdef _SV_ASSERT
149#undef ASSERT
150#undef _SV_ASSERT
151#endif
152
153#endif /* _ASM_IA64_SN_SV_H */
154