Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[pandora-kernel.git] / drivers / staging / tidspbridge / services / sync.c
1 /*
2  * sync.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Synchronization services.
7  *
8  * Copyright (C) 2005-2006 Texas Instruments, Inc.
9  *
10  * This package is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18
19 /*  ----------------------------------- Host OS */
20 #include <dspbridge/host_os.h>
21
22 /*  ----------------------------------- This */
23 #include <dspbridge/sync.h>
24
25 DEFINE_SPINLOCK(sync_lock);
26
27 /**
28  * sync_set_event() - set or signal and specified event
29  * @event:      Event to be set..
30  *
31  * set the @event, if there is an thread waiting for the event
32  * it will be waken up, this function only wakes one thread.
33  */
34
35 void sync_set_event(struct sync_object *event)
36 {
37         spin_lock_bh(&sync_lock);
38         complete(&event->comp);
39         if (event->multi_comp)
40                 complete(event->multi_comp);
41         spin_unlock_bh(&sync_lock);
42 }
43
44 /**
45  * sync_wait_on_multiple_events() - waits for multiple events to be set.
46  * @events:     Array of events to wait for them.
47  * @count:      number of elements of the array.
48  * @timeout     timeout on waiting for the evetns.
49  * @pu_index    index of the event set.
50  *
51  * This functios will wait until any of the array element is set or until
52  * timeout. In case of success the function will return 0 and
53  * @pu_index will store the index of the array element set or in case
54  * of timeout the function will return -ETIME or in case of
55  * interrupting by a signal it will return -EPERM.
56  */
57
58 int sync_wait_on_multiple_events(struct sync_object **events,
59                                      unsigned count, unsigned timeout,
60                                      unsigned *index)
61 {
62         unsigned i;
63         int status = -EPERM;
64         struct completion m_comp;
65
66         init_completion(&m_comp);
67
68         if (SYNC_INFINITE == timeout)
69                 timeout = MAX_SCHEDULE_TIMEOUT;
70
71         spin_lock_bh(&sync_lock);
72         for (i = 0; i < count; i++) {
73                 if (completion_done(&events[i]->comp)) {
74                         INIT_COMPLETION(events[i]->comp);
75                         *index = i;
76                         spin_unlock_bh(&sync_lock);
77                         status = 0;
78                         goto func_end;
79                 }
80         }
81
82         for (i = 0; i < count; i++)
83                 events[i]->multi_comp = &m_comp;
84
85         spin_unlock_bh(&sync_lock);
86
87         if (!wait_for_completion_interruptible_timeout(&m_comp,
88                                         msecs_to_jiffies(timeout)))
89                 status = -ETIME;
90
91         spin_lock_bh(&sync_lock);
92         for (i = 0; i < count; i++) {
93                 if (completion_done(&events[i]->comp)) {
94                         INIT_COMPLETION(events[i]->comp);
95                         *index = i;
96                         status = 0;
97                 }
98                 events[i]->multi_comp = NULL;
99         }
100         spin_unlock_bh(&sync_lock);
101 func_end:
102         return status;
103 }
104