aboutsummaryrefslogtreecommitdiff
path: root/include/linux/kds.h
blob: 73168657b3c26642e4ecdb14c7e68f6d7ca58831 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*
 *
 * (C) COPYRIGHT 2012 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * A copy of the licence is included with the program, and can also be obtained
 * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 *
 */



#ifndef _KDS_H_
#define _KDS_H_

#include <linux/list.h>
#include <linux/workqueue.h>

#define KDS_WAIT_BLOCKING (ULONG_MAX)

struct kds_resource_set;

typedef void (*kds_callback_fn) (void *callback_parameter, void *callback_extra_parameter);

struct kds_callback
{
	kds_callback_fn  user_cb; /* real cb */
	int direct;               /* do direct or queued call? */
	struct workqueue_struct *wq;
};

struct kds_link
{
	struct kds_resource_set *parent;
	struct list_head         link;
	unsigned long            state;
};

struct kds_resource
{
	struct kds_link waiters;
};

/* callback API */

/* Initialize a callback object.
 *
 * Typically created per context or per hw resource.
 *
 * Callbacks can be performed directly if no nested locking can
 * happen in the client.
 *
 * Nested locking can occur when a lock is held during the kds_async_waitall or
 * kds_resource_set_release call. If the callback needs to take the same lock
 * nested locking will happen.
 *
 * If nested locking could happen non-direct callbacks can be requested.
 * Callbacks will then be called asynchronous to the triggering call.
 */
int kds_callback_init(struct kds_callback *cb, int direct, kds_callback_fn user_cb);

/* Terminate the use of a callback object.
 *
 * If the callback object was set up as non-direct
 * any pending callbacks will be flushed first.
 * Note that to avoid a deadlock the lock callbacks needs
 * can't be held when a callback object is terminated.
 */
void kds_callback_term(struct kds_callback *cb);


/* resource object API */

/* initialize a resource handle for a shared resource */
void kds_resource_init(struct kds_resource * const resource);

/*
 * Will return 0 on success.
 * If the resource is being used or waited -EBUSY is returned.
 * The caller should NOT try to terminate a resource that could still have clients.
 * After the function returns the resource is no longer known by kds.
 */
int kds_resource_term(struct kds_resource *resource);

/* Asynchronous wait for a set of resources.
 * Callback will be called when all resources are available.
 * If all the resources was available the callback will be called before kds_async_waitall returns.
 * So one must not hold any locks the callback code-flow can take when calling kds_async_waitall.
 * Caller considered to own/use the resources until \a kds_rset_release is called.
 * exclusive_access_bitmap is a bitmap where a high bit means exclusive access while a low bit means shared access.
 * Use the Linux __set_bit API, where the index of the buffer to control is used as the bit index.
 *
 * Standard Linux error return value.
 */
int kds_async_waitall(
		struct kds_resource_set ** const pprset,
		struct kds_callback      *cb,
		void                     *callback_parameter,
		void                     *callback_extra_parameter,
		int                       number_resources,
		unsigned long            *exclusive_access_bitmap,
		struct kds_resource     **resource_list);

/* Synchronous wait for a set of resources.
 * Function will return when one of these have happened:
 * - all resources have been obtained
 * - timeout lapsed while waiting
 * - a signal was received while waiting
 *
 * To wait without a timeout, specify KDS_WAIT_BLOCKING for \a jifies_timeout, otherwise
 * the timeout in jiffies. A zero timeout attempts to obtain all resources and returns
 * immediately with a timeout if all resources could not be obtained.
 *
 * Caller considered to own/use the resources when the function returns.
 * Caller must release the resources using \a kds_rset_release.
 *
 * Calling this function while holding already locked resources or other locking primitives is dangerous.
 * One must if this is needed decide on a lock order of the resources and/or the other locking primitives
 * and always take the resources/locking primitives in the specific order.
 *
 * Use the ERR_PTR framework to decode the return value.
 * NULL = time out
 * If IS_ERR then PTR_ERR gives:
 *  ERESTARTSYS = signal received, retry call after signal
 *  all other values = internal error, lock failed
 * Other values  = successful wait, now the owner, must call kds_resource_set_release
 */
struct kds_resource_set *kds_waitall(
		int                   number_resources,
		unsigned long        *exclusive_access_bitmap,
		struct kds_resource **resource_list,
		unsigned long         jifies_timeout);

/* Release resources after use.
 * Caller must handle that other async callbacks will trigger,
 * so must avoid holding any locks a callback will take.
 *
 * The function takes a pointer to your poiner to handle a race
 * between a cancelation and a completion.
 *
 * If the caller can't guarantee that a race can't occur then
 * the passed in pointer must be the same in both call paths
 * to allow kds to manage the potential race.
 */
void kds_resource_set_release(struct kds_resource_set **pprset);

/* Release resources after use and wait callbacks to complete.
 * Caller must handle that other async callbacks will trigger,
 * so must avoid holding any locks a callback will take.
 *
 * The function takes a pointer to your poiner to handle a race
 * between a cancelation and a completion.
 *
 * If the caller can't guarantee that a race can't occur then
 * the passed in pointer must be the same in both call paths
 * to allow kds to manage the potential race.
 *
 * This should be used to cancel waits which are pending on a kds
 * resource.
 *
 * It is a bug to call this from atomic contexts and from within
 * a kds callback that now owns the kds_rseource.
 */

void kds_resource_set_release_sync(struct kds_resource_set **pprset);
#endif /* _KDS_H_ */