Update ia64 patch to 2.5.72-030619
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / sn / kernel / sv.c
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-2003 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 #include <linux/kernel.h>
15 #include <linux/sched.h>
16 #include <linux/init.h>
17 #include <linux/interrupt.h>
18
19 #include <asm/semaphore.h>
20 #include <asm/hardirq.h>
21 #include <asm/current.h>
22
23 #include <asm/sn/sv.h>
24
25 /* Define this to have sv_test() run some simple tests.
26    kernel_thread() must behave as expected when this is called.  */
27 #undef RUN_SV_TEST
28
29 #define DEBUG
30
31 /* Set up some macros so sv_wait(), sv_signal(), and sv_broadcast()
32    can sanity check interrupt state on architectures where we know
33    how. */
34 #ifdef DEBUG
35  #define SV_DEBUG_INTERRUPT_STATE
36  #ifdef __mips64
37   #define SV_TEST_INTERRUPTS_ENABLED(flags) ((flags & 0x1) != 0)
38   #define SV_TEST_INTERRUPTS_DISABLED(flags) ((flags & 0x1) == 0)
39   #define SV_INTERRUPT_TEST_WORKERS 31
40  #elif defined(__ia64)
41   #define SV_TEST_INTERRUPTS_ENABLED(flags) ((flags & 0x4000) != 0)
42   #define SV_TEST_INTERRUPTS_DISABLED(flags) ((flags & 0x4000) == 0)
43   #define SV_INTERRUPT_TEST_WORKERS 4 /* simulator's slow */
44  #else
45   #undef  SV_DEBUG_INTERRUPT_STATE
46   #define SV_INTERRUPT_TEST_WORKERS 4 /* reasonable? default. */
47  #endif /* __mips64 */
48 #endif /* DEBUG */
49
50
51 /* XXX FIXME hack hack hack.  Our mips64 tree is from before the
52    switch to WQ_FLAG_EXCLUSIVE, and our ia64 tree is from after it. */
53 #ifdef TASK_EXCLUSIVE
54   #undef EXCLUSIVE_IN_QUEUE
55 #else
56   #define EXCLUSIVE_IN_QUEUE
57   #define TASK_EXCLUSIVE 0 /* for the set_current_state() in sv_wait() */
58 #endif
59
60
61 static inline void sv_lock(sv_t *sv) {
62         spin_lock(&sv->sv_lock);
63 }
64
65 static inline void sv_unlock(sv_t *sv) {
66         spin_unlock(&sv->sv_lock);
67 }
68
69 /* up() is "extern inline", so we can't pass its address to sv_wait.
70    Use this function's address instead. */
71 static void up_wrapper(struct semaphore *sem) {
72         up(sem);
73 }
74
75 /* spin_unlock() is sometimes a macro. */
76 static void spin_unlock_wrapper(spinlock_t *s) {
77         spin_unlock(s);
78 }
79
80 /* XXX Perhaps sv_wait() should do the switch() each time and avoid
81    the extra indirection and the need for the _wrapper functions? */
82
83 static inline void sv_set_mon_type(sv_t *sv, int type) {
84         switch (type) {
85         case SV_MON_SPIN:
86                 sv->sv_mon_unlock_func =
87                   (sv_mon_unlock_func_t)spin_unlock_wrapper;
88                 break;
89         case SV_MON_SEMA:
90                 sv->sv_mon_unlock_func =
91                   (sv_mon_unlock_func_t)up_wrapper;
92                 if(sv->sv_flags & SV_INTS) {
93                         printk(KERN_ERR "sv_set_mon_type: The monitor lock "
94                                "cannot be shared with interrupts if it is a "
95                                "semaphore!\n");
96                         BUG();
97                 }
98                 if(sv->sv_flags & SV_BHS) {
99                         printk(KERN_ERR "sv_set_mon_type: The monitor lock "
100                                "cannot be shared with bottom-halves if it is "
101                                "a semaphore!\n");
102                         BUG();
103                 }
104                 break;
105 #if 0 
106         /*
107          * If needed, and will need to think about interrupts.  This
108          * may be needed, for example, if someone wants to use sv's
109          * with something like dev_base; writers need to hold two
110          * locks. 
111          */
112         case SV_MON_CUSTOM: 
113                 {
114                 struct sv_mon_custom *c = lock;
115                 sv->sv_mon_unlock_func = c->sv_mon_unlock_func;
116                 sv->sv_mon_lock        = c->sv_mon_lock;
117                 break;
118                 }
119 #endif
120                 
121         default:
122                 printk(KERN_ERR "sv_set_mon_type: unknown type %d (0x%x)! "
123                        "(flags 0x%x)\n", type, type, sv->sv_flags);
124                 BUG();
125                 break;
126         }
127         sv->sv_flags |= type;
128 }
129
130 static inline void sv_set_ord(sv_t *sv, int ord) {
131         if (!ord)
132                 ord = SV_ORDER_DEFAULT;
133
134         if (ord != SV_ORDER_FIFO && ord != SV_ORDER_LIFO) {
135                 printk(KERN_EMERG "sv_set_ord: unknown order %d (0x%x)! ",
136                        ord, ord);
137                 BUG();
138         }
139
140         sv->sv_flags |= ord;
141 }
142
143 void sv_init(sv_t *sv, sv_mon_lock_t *lock, int flags) 
144 {
145         int ord = flags & SV_ORDER_MASK;
146         int type = flags & SV_MON_MASK;
147
148         /* Copy all non-order, non-type flags */
149         sv->sv_flags = (flags & ~(SV_ORDER_MASK | SV_MON_MASK));
150
151         if((sv->sv_flags & (SV_INTS | SV_BHS)) == (SV_INTS | SV_BHS)) {
152           printk(KERN_ERR "sv_init: do not set both SV_INTS and SV_BHS, only SV_INTS.\n");
153           BUG();
154         }
155
156         sv_set_ord(sv, ord);
157         sv_set_mon_type(sv, type);
158
159         /* If lock is NULL, we'll get it from sv_wait_compat() (and
160            ignore it in sv_signal() and sv_broadcast()). */
161         sv->sv_mon_lock = lock;
162
163         spin_lock_init(&sv->sv_lock);
164         init_waitqueue_head(&sv->sv_waiters);
165 }
166
167 /*
168  * The associated lock must be locked on entry.  It is unlocked on return.
169  *
170  * Return values:
171  *
172  * n < 0 : interrupted,  -n jiffies remaining on timeout, or -1 if timeout == 0
173  * n = 0 : timeout expired
174  * n > 0 : sv_signal()'d, n jiffies remaining on timeout, or 1 if timeout == 0
175  */
176 signed long sv_wait(sv_t *sv, int sv_wait_flags, unsigned long timeout) 
177 {
178         DECLARE_WAITQUEUE( wait, current );
179         unsigned long flags;
180         signed long ret = 0;
181
182 #ifdef SV_DEBUG_INTERRUPT_STATE
183         {
184         unsigned long flags;
185         local_save_flags(flags);
186
187         if(sv->sv_flags & SV_INTS) {
188                 if(SV_TEST_INTERRUPTS_ENABLED(flags)) {
189                         printk(KERN_ERR "sv_wait: SV_INTS and interrupts "
190                                "enabled (flags: 0x%lx)\n", flags);
191                         BUG();
192                 }
193         } else {
194                 if (SV_TEST_INTERRUPTS_DISABLED(flags)) {
195                         printk(KERN_WARNING "sv_wait: !SV_INTS and interrupts "
196                                "disabled! (flags: 0x%lx)\n", flags);
197                 }
198         }
199         }
200 #endif  /* SV_DEBUG_INTERRUPT_STATE */
201
202         sv_lock(sv);
203
204         sv->sv_mon_unlock_func(sv->sv_mon_lock);
205
206         /* Add ourselves to the wait queue and set the state before
207          * releasing the sv_lock so as to avoid racing with the
208          * wake_up() in sv_signal() and sv_broadcast(). 
209          */
210
211         /* don't need the _irqsave part, but there is no wq_write_lock() */
212         write_lock_irqsave(&sv->sv_waiters.lock, flags);
213
214 #ifdef EXCLUSIVE_IN_QUEUE
215         wait.flags |= WQ_FLAG_EXCLUSIVE;
216 #endif
217
218         switch(sv->sv_flags & SV_ORDER_MASK) {
219         case SV_ORDER_FIFO:
220                 __add_wait_queue_tail(&sv->sv_waiters, &wait);
221                 break;
222         case SV_ORDER_FILO:
223                 __add_wait_queue(&sv->sv_waiters, &wait);
224                 break;
225         default:
226                 printk(KERN_ERR "sv_wait: unknown order!  (sv: 0x%p, flags: 0x%x)\n",
227                                         (void *)sv, sv->sv_flags);
228                 BUG();
229         }
230         write_unlock_irqrestore(&sv->sv_waiters.lock, flags);
231
232         if(sv_wait_flags & SV_WAIT_SIG)
233                 set_current_state(TASK_EXCLUSIVE | TASK_INTERRUPTIBLE  );
234         else
235                 set_current_state(TASK_EXCLUSIVE | TASK_UNINTERRUPTIBLE);
236
237         spin_unlock(&sv->sv_lock);
238
239         if(sv->sv_flags & SV_INTS)
240                 local_irq_enable();
241         else if(sv->sv_flags & SV_BHS)
242                 local_bh_enable();
243
244         if (timeout)
245                 ret = schedule_timeout(timeout);
246         else
247                 schedule();
248
249         if(current->state != TASK_RUNNING) /* XXX Is this possible? */ {
250                 printk(KERN_ERR "sv_wait: state not TASK_RUNNING after "
251                        "schedule().\n");
252                 set_current_state(TASK_RUNNING);
253         }
254
255         remove_wait_queue(&sv->sv_waiters, &wait);
256
257         /* Return cases:
258            - woken by a sv_signal/sv_broadcast
259            - woken by a signal
260            - woken by timeout expiring
261         */
262
263         /* XXX This isn't really accurate; we may have been woken
264            before the signal anyway.... */
265         if(signal_pending(current))
266                 return timeout ? -ret : -1;
267         return timeout ? ret : 1;
268 }
269
270
271 void sv_signal(sv_t *sv) 
272 {
273         /* If interrupts can acquire this lock, they can also acquire the
274            sv_mon_lock, which we must already have to have called this, so
275            interrupts must be disabled already.  If interrupts cannot
276            contend for this lock, we don't have to worry about it. */
277
278 #ifdef SV_DEBUG_INTERRUPT_STATE
279         if(sv->sv_flags & SV_INTS) {
280                 unsigned long flags;
281                 local_save_flags(flags);
282                 if(SV_TEST_INTERRUPTS_ENABLED(flags))
283                         printk(KERN_ERR "sv_signal: SV_INTS and "
284                         "interrupts enabled! (flags: 0x%lx)\n", flags);
285         }
286 #endif /* SV_DEBUG_INTERRUPT_STATE */
287
288         sv_lock(sv);
289         wake_up(&sv->sv_waiters);
290         sv_unlock(sv);
291 }
292
293 void sv_broadcast(sv_t *sv) 
294 {
295 #ifdef SV_DEBUG_INTERRUPT_STATE
296         if(sv->sv_flags & SV_INTS) {
297                 unsigned long flags;
298                 local_save_flags(flags);
299                 if(SV_TEST_INTERRUPTS_ENABLED(flags))
300                         printk(KERN_ERR "sv_broadcast: SV_INTS and "
301                                "interrupts enabled! (flags: 0x%lx)\n", flags);
302         }
303 #endif /* SV_DEBUG_INTERRUPT_STATE */
304
305         sv_lock(sv);
306         wake_up_all(&sv->sv_waiters);
307         sv_unlock(sv);
308 }
309
310 void sv_destroy(sv_t *sv) 
311 {
312         if(!spin_trylock(&sv->sv_lock)) {
313                 printk(KERN_ERR "sv_destroy: someone else has sv 0x%p locked!\n", (void *)sv);
314                 BUG();
315         }
316
317         /* XXX Check that the waitqueue is empty? 
318                Mark the sv destroyed?
319         */
320 }
321
322
323 #ifdef RUN_SV_TEST
324
325 static DECLARE_MUTEX_LOCKED(talkback);
326 static DECLARE_MUTEX_LOCKED(sem);
327 sv_t sv;
328 sv_t sv_filo;
329
330 static int sv_test_1_w(void *arg) 
331 {
332         printk("sv_test_1_w: acquiring spinlock 0x%p...\n", arg);
333
334         spin_lock((spinlock_t*)arg);
335         printk("sv_test_1_w: spinlock acquired, waking sv_test_1_s.\n");
336
337         up(&sem);
338
339         printk("sv_test_1_w: sv_spin_wait()'ing.\n");
340
341         sv_spin_wait(&sv, arg);
342
343         printk("sv_test_1_w: talkback.\n");
344         up(&talkback);
345
346         printk("sv_test_1_w: exiting.\n");
347         return 0;
348 }
349
350 static int sv_test_1_s(void *arg) 
351 {
352         printk("sv_test_1_s: waiting for semaphore.\n");
353         down(&sem);
354         printk("sv_test_1_s: semaphore acquired.  Acquiring spinlock.\n");
355         spin_lock((spinlock_t*)arg);
356         printk("sv_test_1_s: spinlock acquired.  sv_signaling.\n");
357         sv_signal(&sv);
358         printk("sv_test_1_s: talkback.\n");
359         up(&talkback);
360         printk("sv_test_1_s: exiting.\n");
361         return 0;
362
363 }
364
365 static int count;
366 static DECLARE_MUTEX(monitor);
367
368 static int sv_test_2_w(void *arg) 
369 {
370         int dummy = count++;
371         sv_t *sv = (sv_t *)arg;
372
373         down(&monitor);
374         up(&talkback);
375         printk("sv_test_2_w: thread %d started, sv_waiting.\n", dummy);
376         sv_sema_wait(sv, &monitor);
377         printk("sv_test_2_w: thread %d woken, exiting.\n", dummy);
378         up(&sem);
379         return 0;
380 }
381
382 static int sv_test_2_s_1(void *arg) 
383 {
384         int i;
385         sv_t *sv = (sv_t *)arg;
386
387         down(&monitor);
388         for(i = 0; i < 3; i++) {
389                 printk("sv_test_2_s_1: waking one thread.\n");
390                 sv_signal(sv);
391                 down(&sem);
392         }
393
394         printk("sv_test_2_s_1: signaling and broadcasting again.  Nothing should happen.\n");
395         sv_signal(sv);
396         sv_broadcast(sv);
397         sv_signal(sv);
398         sv_broadcast(sv);
399
400         printk("sv_test_2_s_1: talkbacking.\n");
401         up(&talkback);
402         up(&monitor);
403         return 0;
404 }
405
406 static int sv_test_2_s(void *arg) 
407 {
408         int i;
409         sv_t *sv = (sv_t *)arg;
410
411         down(&monitor);
412         for(i = 0; i < 3; i++) {
413                 printk("sv_test_2_s: waking one thread (should be %d.)\n", i);
414                 sv_signal(sv);
415                 down(&sem);
416         }
417
418         printk("sv_test_3_s: waking remaining threads with broadcast.\n");
419         sv_broadcast(sv);
420         for(; i < 10; i++)
421                 down(&sem);
422
423         printk("sv_test_3_s: sending talkback.\n");
424         up(&talkback);
425
426         printk("sv_test_3_s: exiting.\n");
427         up(&monitor);
428         return 0;
429 }
430
431
432 static void big_test(sv_t *sv) 
433 {
434         int i;
435
436         count = 0;
437
438         for(i = 0; i < 3; i++) {
439                 printk("big_test: spawning thread %d.\n", i);
440                 kernel_thread(sv_test_2_w, sv, 0);
441                 down(&talkback);
442         }
443
444         printk("big_test: spawning first wake-up thread.\n");
445         kernel_thread(sv_test_2_s_1, sv, 0);
446
447         down(&talkback);
448         printk("big_test: talkback happened.\n");
449
450
451         for(i = 3; i < 13; i++) {
452                 printk("big_test: spawning thread %d.\n", i);
453                 kernel_thread(sv_test_2_w, sv, 0);
454                 down(&talkback);
455         }
456
457         printk("big_test: spawning wake-up thread.\n");
458         kernel_thread(sv_test_2_s, sv, 0);
459
460         down(&talkback);
461 }
462
463 sv_t int_test_sv;
464 spinlock_t int_test_spin = SPIN_LOCK_UNLOCKED;
465 int int_test_ready;
466 static int irqtestcount;
467
468 static int interrupt_test_worker(void *unused) 
469 {
470         int id = ++irqtestcount;
471         int it = 0;
472                         unsigned long flags, flags2;
473
474         printk("ITW: thread %d started.\n", id);
475
476         while(1) {
477                 local_save_flags(flags2);
478                 if(jiffies % 3) {
479                         printk("ITW %2d %5d: irqsaving          (%lx)\n", id, it, flags2);
480                         spin_lock_irqsave(&int_test_spin, flags);
481                 } else {
482                         printk("ITW %2d %5d: spin_lock_irqing   (%lx)\n", id, it, flags2);
483                         spin_lock_irq(&int_test_spin);
484                 }
485
486                 local_save_flags(flags2);
487                 printk("ITW %2d %5d: locked, sv_waiting (%lx).\n", id, it, flags2);
488                 sv_wait(&int_test_sv, 0, 0);
489
490                 local_save_flags(flags2);
491                 printk("ITW %2d %5d: wait finished      (%lx), pausing\n", id, it, flags2);
492                 set_current_state(TASK_INTERRUPTIBLE);
493                 schedule_timeout(jiffies & 0xf);
494                 if(current->state != TASK_RUNNING)
495                   printk("ITW:  current->state isn't RUNNING after schedule!\n");
496                 it++;
497         }
498 }
499
500 static void interrupt_test(void) 
501 {
502         int i;
503
504         printk("interrupt_test: initing sv.\n");
505         sv_init(&int_test_sv, &int_test_spin, SV_MON_SPIN | SV_INTS);
506
507         for(i = 0; i < SV_INTERRUPT_TEST_WORKERS; i++) {
508                 printk("interrupt_test: starting test thread %d.\n", i);
509                 kernel_thread(interrupt_test_worker, 0, 0);
510         }
511         printk("interrupt_test: done with init part.\n");
512         int_test_ready = 1;
513 }
514
515 int sv_test(void) 
516 {
517         spinlock_t s = SPIN_LOCK_UNLOCKED;
518
519         sv_init(&sv, &s, SV_MON_SPIN);
520         printk("sv_test: starting sv_test_1_w.\n");
521         kernel_thread(sv_test_1_w, &s, 0);
522         printk("sv_test: starting sv_test_1_s.\n");
523         kernel_thread(sv_test_1_s, &s, 0);
524
525         printk("sv_test: waiting for talkback.\n");
526         down(&talkback); down(&talkback);
527         printk("sv_test: talkback happened, sv_destroying.\n");
528         sv_destroy(&sv);
529
530         count = 0;
531
532         printk("sv_test: beginning big_test on sv.\n");
533
534         sv_init(&sv, &monitor, SV_MON_SEMA);
535         big_test(&sv);
536         sv_destroy(&sv);
537
538         printk("sv_test: beginning big_test on sv_filo.\n");
539         sv_init(&sv_filo, &monitor, SV_MON_SEMA | SV_ORDER_FILO);
540         big_test(&sv_filo);
541         sv_destroy(&sv_filo);
542
543         interrupt_test();
544
545         printk("sv_test: done.\n");
546         return 0;
547 }
548
549 __initcall(sv_test);
550
551 #endif /* RUN_SV_TEST */