File: /usr/src/linux/arch/ia64/sn/sn1/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 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     
18     #include <asm/semaphore.h>
19     #include <asm/hardirq.h>
20     #include <asm/softirq.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     	__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     	wq_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     					sv, sv->sv_flags);
228     		BUG();
229     	}
230     	wq_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     		__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     		__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", 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     		__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     		__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     		__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 */
552