Subversion Repositories Kolibri OS

Rev

Rev 6082 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5270 serge 1
/* Atomic operations usable in machine independent code */
2
#ifndef _LINUX_ATOMIC_H
3
#define _LINUX_ATOMIC_H
4
#include 
6082 serge 5
#include 
5270 serge 6
 
6082 serge 7
/*
8
 * Relaxed variants of xchg, cmpxchg and some atomic operations.
9
 *
10
 * We support four variants:
11
 *
12
 * - Fully ordered: The default implementation, no suffix required.
13
 * - Acquire: Provides ACQUIRE semantics, _acquire suffix.
14
 * - Release: Provides RELEASE semantics, _release suffix.
15
 * - Relaxed: No ordering guarantees, _relaxed suffix.
16
 *
17
 * For compound atomics performing both a load and a store, ACQUIRE
18
 * semantics apply only to the load and RELEASE semantics only to the
19
 * store portion of the operation. Note that a failed cmpxchg_acquire
20
 * does -not- imply any memory ordering constraints.
21
 *
22
 * See Documentation/memory-barriers.txt for ACQUIRE/RELEASE definitions.
23
 */
24
 
25
#ifndef atomic_read_acquire
26
#define  atomic_read_acquire(v)		smp_load_acquire(&(v)->counter)
27
#endif
28
 
29
#ifndef atomic_set_release
30
#define  atomic_set_release(v, i)	smp_store_release(&(v)->counter, (i))
31
#endif
32
 
33
/*
34
 * The idea here is to build acquire/release variants by adding explicit
35
 * barriers on top of the relaxed variant. In the case where the relaxed
36
 * variant is already fully ordered, no additional barriers are needed.
7143 serge 37
 *
38
 * Besides, if an arch has a special barrier for acquire/release, it could
39
 * implement its own __atomic_op_* and use the same framework for building
40
 * variants
6082 serge 41
 */
7143 serge 42
#ifndef __atomic_op_acquire
6082 serge 43
#define __atomic_op_acquire(op, args...)				\
44
({									\
45
	typeof(op##_relaxed(args)) __ret  = op##_relaxed(args);		\
46
	smp_mb__after_atomic();						\
47
	__ret;								\
48
})
7143 serge 49
#endif
6082 serge 50
 
7143 serge 51
#ifndef __atomic_op_release
6082 serge 52
#define __atomic_op_release(op, args...)				\
53
({									\
54
	smp_mb__before_atomic();					\
55
	op##_relaxed(args);						\
56
})
7143 serge 57
#endif
6082 serge 58
 
7143 serge 59
#ifndef __atomic_op_fence
6082 serge 60
#define __atomic_op_fence(op, args...)					\
61
({									\
62
	typeof(op##_relaxed(args)) __ret;				\
63
	smp_mb__before_atomic();					\
64
	__ret = op##_relaxed(args);					\
65
	smp_mb__after_atomic();						\
66
	__ret;								\
67
})
7143 serge 68
#endif
6082 serge 69
 
70
/* atomic_add_return_relaxed */
71
#ifndef atomic_add_return_relaxed
72
#define  atomic_add_return_relaxed	atomic_add_return
73
#define  atomic_add_return_acquire	atomic_add_return
74
#define  atomic_add_return_release	atomic_add_return
75
 
76
#else /* atomic_add_return_relaxed */
77
 
78
#ifndef atomic_add_return_acquire
79
#define  atomic_add_return_acquire(...)					\
80
	__atomic_op_acquire(atomic_add_return, __VA_ARGS__)
81
#endif
82
 
83
#ifndef atomic_add_return_release
84
#define  atomic_add_return_release(...)					\
85
	__atomic_op_release(atomic_add_return, __VA_ARGS__)
86
#endif
87
 
88
#ifndef atomic_add_return
89
#define  atomic_add_return(...)						\
90
	__atomic_op_fence(atomic_add_return, __VA_ARGS__)
91
#endif
92
#endif /* atomic_add_return_relaxed */
93
 
94
/* atomic_inc_return_relaxed */
95
#ifndef atomic_inc_return_relaxed
96
#define  atomic_inc_return_relaxed	atomic_inc_return
97
#define  atomic_inc_return_acquire	atomic_inc_return
98
#define  atomic_inc_return_release	atomic_inc_return
99
 
100
#else /* atomic_inc_return_relaxed */
101
 
102
#ifndef atomic_inc_return_acquire
103
#define  atomic_inc_return_acquire(...)					\
104
	__atomic_op_acquire(atomic_inc_return, __VA_ARGS__)
105
#endif
106
 
107
#ifndef atomic_inc_return_release
108
#define  atomic_inc_return_release(...)					\
109
	__atomic_op_release(atomic_inc_return, __VA_ARGS__)
110
#endif
111
 
112
#ifndef atomic_inc_return
113
#define  atomic_inc_return(...)						\
114
	__atomic_op_fence(atomic_inc_return, __VA_ARGS__)
115
#endif
116
#endif /* atomic_inc_return_relaxed */
117
 
118
/* atomic_sub_return_relaxed */
119
#ifndef atomic_sub_return_relaxed
120
#define  atomic_sub_return_relaxed	atomic_sub_return
121
#define  atomic_sub_return_acquire	atomic_sub_return
122
#define  atomic_sub_return_release	atomic_sub_return
123
 
124
#else /* atomic_sub_return_relaxed */
125
 
126
#ifndef atomic_sub_return_acquire
127
#define  atomic_sub_return_acquire(...)					\
128
	__atomic_op_acquire(atomic_sub_return, __VA_ARGS__)
129
#endif
130
 
131
#ifndef atomic_sub_return_release
132
#define  atomic_sub_return_release(...)					\
133
	__atomic_op_release(atomic_sub_return, __VA_ARGS__)
134
#endif
135
 
136
#ifndef atomic_sub_return
137
#define  atomic_sub_return(...)						\
138
	__atomic_op_fence(atomic_sub_return, __VA_ARGS__)
139
#endif
140
#endif /* atomic_sub_return_relaxed */
141
 
142
/* atomic_dec_return_relaxed */
143
#ifndef atomic_dec_return_relaxed
144
#define  atomic_dec_return_relaxed	atomic_dec_return
145
#define  atomic_dec_return_acquire	atomic_dec_return
146
#define  atomic_dec_return_release	atomic_dec_return
147
 
148
#else /* atomic_dec_return_relaxed */
149
 
150
#ifndef atomic_dec_return_acquire
151
#define  atomic_dec_return_acquire(...)					\
152
	__atomic_op_acquire(atomic_dec_return, __VA_ARGS__)
153
#endif
154
 
155
#ifndef atomic_dec_return_release
156
#define  atomic_dec_return_release(...)					\
157
	__atomic_op_release(atomic_dec_return, __VA_ARGS__)
158
#endif
159
 
160
#ifndef atomic_dec_return
161
#define  atomic_dec_return(...)						\
162
	__atomic_op_fence(atomic_dec_return, __VA_ARGS__)
163
#endif
164
#endif /* atomic_dec_return_relaxed */
165
 
166
/* atomic_xchg_relaxed */
167
#ifndef atomic_xchg_relaxed
168
#define  atomic_xchg_relaxed		atomic_xchg
169
#define  atomic_xchg_acquire		atomic_xchg
170
#define  atomic_xchg_release		atomic_xchg
171
 
172
#else /* atomic_xchg_relaxed */
173
 
174
#ifndef atomic_xchg_acquire
175
#define  atomic_xchg_acquire(...)					\
176
	__atomic_op_acquire(atomic_xchg, __VA_ARGS__)
177
#endif
178
 
179
#ifndef atomic_xchg_release
180
#define  atomic_xchg_release(...)					\
181
	__atomic_op_release(atomic_xchg, __VA_ARGS__)
182
#endif
183
 
184
#ifndef atomic_xchg
185
#define  atomic_xchg(...)						\
186
	__atomic_op_fence(atomic_xchg, __VA_ARGS__)
187
#endif
188
#endif /* atomic_xchg_relaxed */
189
 
190
/* atomic_cmpxchg_relaxed */
191
#ifndef atomic_cmpxchg_relaxed
192
#define  atomic_cmpxchg_relaxed		atomic_cmpxchg
193
#define  atomic_cmpxchg_acquire		atomic_cmpxchg
194
#define  atomic_cmpxchg_release		atomic_cmpxchg
195
 
196
#else /* atomic_cmpxchg_relaxed */
197
 
198
#ifndef atomic_cmpxchg_acquire
199
#define  atomic_cmpxchg_acquire(...)					\
200
	__atomic_op_acquire(atomic_cmpxchg, __VA_ARGS__)
201
#endif
202
 
203
#ifndef atomic_cmpxchg_release
204
#define  atomic_cmpxchg_release(...)					\
205
	__atomic_op_release(atomic_cmpxchg, __VA_ARGS__)
206
#endif
207
 
208
#ifndef atomic_cmpxchg
209
#define  atomic_cmpxchg(...)						\
210
	__atomic_op_fence(atomic_cmpxchg, __VA_ARGS__)
211
#endif
212
#endif /* atomic_cmpxchg_relaxed */
213
 
214
#ifndef atomic64_read_acquire
215
#define  atomic64_read_acquire(v)	smp_load_acquire(&(v)->counter)
216
#endif
217
 
218
#ifndef atomic64_set_release
219
#define  atomic64_set_release(v, i)	smp_store_release(&(v)->counter, (i))
220
#endif
221
 
222
/* atomic64_add_return_relaxed */
223
#ifndef atomic64_add_return_relaxed
224
#define  atomic64_add_return_relaxed	atomic64_add_return
225
#define  atomic64_add_return_acquire	atomic64_add_return
226
#define  atomic64_add_return_release	atomic64_add_return
227
 
228
#else /* atomic64_add_return_relaxed */
229
 
230
#ifndef atomic64_add_return_acquire
231
#define  atomic64_add_return_acquire(...)				\
232
	__atomic_op_acquire(atomic64_add_return, __VA_ARGS__)
233
#endif
234
 
235
#ifndef atomic64_add_return_release
236
#define  atomic64_add_return_release(...)				\
237
	__atomic_op_release(atomic64_add_return, __VA_ARGS__)
238
#endif
239
 
240
#ifndef atomic64_add_return
241
#define  atomic64_add_return(...)					\
242
	__atomic_op_fence(atomic64_add_return, __VA_ARGS__)
243
#endif
244
#endif /* atomic64_add_return_relaxed */
245
 
246
/* atomic64_inc_return_relaxed */
247
#ifndef atomic64_inc_return_relaxed
248
#define  atomic64_inc_return_relaxed	atomic64_inc_return
249
#define  atomic64_inc_return_acquire	atomic64_inc_return
250
#define  atomic64_inc_return_release	atomic64_inc_return
251
 
252
#else /* atomic64_inc_return_relaxed */
253
 
254
#ifndef atomic64_inc_return_acquire
255
#define  atomic64_inc_return_acquire(...)				\
256
	__atomic_op_acquire(atomic64_inc_return, __VA_ARGS__)
257
#endif
258
 
259
#ifndef atomic64_inc_return_release
260
#define  atomic64_inc_return_release(...)				\
261
	__atomic_op_release(atomic64_inc_return, __VA_ARGS__)
262
#endif
263
 
264
#ifndef atomic64_inc_return
265
#define  atomic64_inc_return(...)					\
266
	__atomic_op_fence(atomic64_inc_return, __VA_ARGS__)
267
#endif
268
#endif /* atomic64_inc_return_relaxed */
269
 
270
 
271
/* atomic64_sub_return_relaxed */
272
#ifndef atomic64_sub_return_relaxed
273
#define  atomic64_sub_return_relaxed	atomic64_sub_return
274
#define  atomic64_sub_return_acquire	atomic64_sub_return
275
#define  atomic64_sub_return_release	atomic64_sub_return
276
 
277
#else /* atomic64_sub_return_relaxed */
278
 
279
#ifndef atomic64_sub_return_acquire
280
#define  atomic64_sub_return_acquire(...)				\
281
	__atomic_op_acquire(atomic64_sub_return, __VA_ARGS__)
282
#endif
283
 
284
#ifndef atomic64_sub_return_release
285
#define  atomic64_sub_return_release(...)				\
286
	__atomic_op_release(atomic64_sub_return, __VA_ARGS__)
287
#endif
288
 
289
#ifndef atomic64_sub_return
290
#define  atomic64_sub_return(...)					\
291
	__atomic_op_fence(atomic64_sub_return, __VA_ARGS__)
292
#endif
293
#endif /* atomic64_sub_return_relaxed */
294
 
295
/* atomic64_dec_return_relaxed */
296
#ifndef atomic64_dec_return_relaxed
297
#define  atomic64_dec_return_relaxed	atomic64_dec_return
298
#define  atomic64_dec_return_acquire	atomic64_dec_return
299
#define  atomic64_dec_return_release	atomic64_dec_return
300
 
301
#else /* atomic64_dec_return_relaxed */
302
 
303
#ifndef atomic64_dec_return_acquire
304
#define  atomic64_dec_return_acquire(...)				\
305
	__atomic_op_acquire(atomic64_dec_return, __VA_ARGS__)
306
#endif
307
 
308
#ifndef atomic64_dec_return_release
309
#define  atomic64_dec_return_release(...)				\
310
	__atomic_op_release(atomic64_dec_return, __VA_ARGS__)
311
#endif
312
 
313
#ifndef atomic64_dec_return
314
#define  atomic64_dec_return(...)					\
315
	__atomic_op_fence(atomic64_dec_return, __VA_ARGS__)
316
#endif
317
#endif /* atomic64_dec_return_relaxed */
318
 
319
/* atomic64_xchg_relaxed */
320
#ifndef atomic64_xchg_relaxed
321
#define  atomic64_xchg_relaxed		atomic64_xchg
322
#define  atomic64_xchg_acquire		atomic64_xchg
323
#define  atomic64_xchg_release		atomic64_xchg
324
 
325
#else /* atomic64_xchg_relaxed */
326
 
327
#ifndef atomic64_xchg_acquire
328
#define  atomic64_xchg_acquire(...)					\
329
	__atomic_op_acquire(atomic64_xchg, __VA_ARGS__)
330
#endif
331
 
332
#ifndef atomic64_xchg_release
333
#define  atomic64_xchg_release(...)					\
334
	__atomic_op_release(atomic64_xchg, __VA_ARGS__)
335
#endif
336
 
337
#ifndef atomic64_xchg
338
#define  atomic64_xchg(...)						\
339
	__atomic_op_fence(atomic64_xchg, __VA_ARGS__)
340
#endif
341
#endif /* atomic64_xchg_relaxed */
342
 
343
/* atomic64_cmpxchg_relaxed */
344
#ifndef atomic64_cmpxchg_relaxed
345
#define  atomic64_cmpxchg_relaxed	atomic64_cmpxchg
346
#define  atomic64_cmpxchg_acquire	atomic64_cmpxchg
347
#define  atomic64_cmpxchg_release	atomic64_cmpxchg
348
 
349
#else /* atomic64_cmpxchg_relaxed */
350
 
351
#ifndef atomic64_cmpxchg_acquire
352
#define  atomic64_cmpxchg_acquire(...)					\
353
	__atomic_op_acquire(atomic64_cmpxchg, __VA_ARGS__)
354
#endif
355
 
356
#ifndef atomic64_cmpxchg_release
357
#define  atomic64_cmpxchg_release(...)					\
358
	__atomic_op_release(atomic64_cmpxchg, __VA_ARGS__)
359
#endif
360
 
361
#ifndef atomic64_cmpxchg
362
#define  atomic64_cmpxchg(...)						\
363
	__atomic_op_fence(atomic64_cmpxchg, __VA_ARGS__)
364
#endif
365
#endif /* atomic64_cmpxchg_relaxed */
366
 
367
/* cmpxchg_relaxed */
368
#ifndef cmpxchg_relaxed
369
#define  cmpxchg_relaxed		cmpxchg
370
#define  cmpxchg_acquire		cmpxchg
371
#define  cmpxchg_release		cmpxchg
372
 
373
#else /* cmpxchg_relaxed */
374
 
375
#ifndef cmpxchg_acquire
376
#define  cmpxchg_acquire(...)						\
377
	__atomic_op_acquire(cmpxchg, __VA_ARGS__)
378
#endif
379
 
380
#ifndef cmpxchg_release
381
#define  cmpxchg_release(...)						\
382
	__atomic_op_release(cmpxchg, __VA_ARGS__)
383
#endif
384
 
385
#ifndef cmpxchg
386
#define  cmpxchg(...)							\
387
	__atomic_op_fence(cmpxchg, __VA_ARGS__)
388
#endif
389
#endif /* cmpxchg_relaxed */
390
 
391
/* cmpxchg64_relaxed */
392
#ifndef cmpxchg64_relaxed
393
#define  cmpxchg64_relaxed		cmpxchg64
394
#define  cmpxchg64_acquire		cmpxchg64
395
#define  cmpxchg64_release		cmpxchg64
396
 
397
#else /* cmpxchg64_relaxed */
398
 
399
#ifndef cmpxchg64_acquire
400
#define  cmpxchg64_acquire(...)						\
401
	__atomic_op_acquire(cmpxchg64, __VA_ARGS__)
402
#endif
403
 
404
#ifndef cmpxchg64_release
405
#define  cmpxchg64_release(...)						\
406
	__atomic_op_release(cmpxchg64, __VA_ARGS__)
407
#endif
408
 
409
#ifndef cmpxchg64
410
#define  cmpxchg64(...)							\
411
	__atomic_op_fence(cmpxchg64, __VA_ARGS__)
412
#endif
413
#endif /* cmpxchg64_relaxed */
414
 
415
/* xchg_relaxed */
416
#ifndef xchg_relaxed
417
#define  xchg_relaxed			xchg
418
#define  xchg_acquire			xchg
419
#define  xchg_release			xchg
420
 
421
#else /* xchg_relaxed */
422
 
423
#ifndef xchg_acquire
424
#define  xchg_acquire(...)		__atomic_op_acquire(xchg, __VA_ARGS__)
425
#endif
426
 
427
#ifndef xchg_release
428
#define  xchg_release(...)		__atomic_op_release(xchg, __VA_ARGS__)
429
#endif
430
 
431
#ifndef xchg
432
#define  xchg(...)			__atomic_op_fence(xchg, __VA_ARGS__)
433
#endif
434
#endif /* xchg_relaxed */
435
 
5270 serge 436
/**
437
 * atomic_add_unless - add unless the number is already a given value
438
 * @v: pointer of type atomic_t
439
 * @a: the amount to add to v...
440
 * @u: ...unless v is equal to u.
441
 *
442
 * Atomically adds @a to @v, so long as @v was not already @u.
443
 * Returns non-zero if @v was not @u, and zero otherwise.
444
 */
445
static inline int atomic_add_unless(atomic_t *v, int a, int u)
446
{
447
	return __atomic_add_unless(v, a, u) != u;
448
}
449
 
450
/**
451
 * atomic_inc_not_zero - increment unless the number is zero
452
 * @v: pointer of type atomic_t
453
 *
454
 * Atomically increments @v by 1, so long as @v is non-zero.
455
 * Returns non-zero if @v was non-zero, and zero otherwise.
456
 */
457
#ifndef atomic_inc_not_zero
458
#define atomic_inc_not_zero(v)		atomic_add_unless((v), 1, 0)
459
#endif
460
 
6082 serge 461
#ifndef atomic_andnot
462
static inline void atomic_andnot(int i, atomic_t *v)
463
{
464
	atomic_and(~i, v);
465
}
466
#endif
467
 
468
static inline __deprecated void atomic_clear_mask(unsigned int mask, atomic_t *v)
469
{
470
	atomic_andnot(mask, v);
471
}
472
 
473
static inline __deprecated void atomic_set_mask(unsigned int mask, atomic_t *v)
474
{
475
	atomic_or(mask, v);
476
}
477
 
5270 serge 478
/**
479
 * atomic_inc_not_zero_hint - increment if not null
480
 * @v: pointer of type atomic_t
481
 * @hint: probable value of the atomic before the increment
482
 *
483
 * This version of atomic_inc_not_zero() gives a hint of probable
484
 * value of the atomic. This helps processor to not read the memory
485
 * before doing the atomic read/modify/write cycle, lowering
486
 * number of bus transactions on some arches.
487
 *
488
 * Returns: 0 if increment was not done, 1 otherwise.
489
 */
490
#ifndef atomic_inc_not_zero_hint
491
static inline int atomic_inc_not_zero_hint(atomic_t *v, int hint)
492
{
493
	int val, c = hint;
494
 
495
	/* sanity test, should be removed by compiler if hint is a constant */
496
	if (!hint)
497
		return atomic_inc_not_zero(v);
498
 
499
	do {
500
		val = atomic_cmpxchg(v, c, c + 1);
501
		if (val == c)
502
			return 1;
503
		c = val;
504
	} while (c);
505
 
506
	return 0;
507
}
508
#endif
509
 
510
#ifndef atomic_inc_unless_negative
511
static inline int atomic_inc_unless_negative(atomic_t *p)
512
{
513
	int v, v1;
514
	for (v = 0; v >= 0; v = v1) {
515
		v1 = atomic_cmpxchg(p, v, v + 1);
516
		if (likely(v1 == v))
517
			return 1;
518
	}
519
	return 0;
520
}
521
#endif
522
 
523
#ifndef atomic_dec_unless_positive
524
static inline int atomic_dec_unless_positive(atomic_t *p)
525
{
526
	int v, v1;
527
	for (v = 0; v <= 0; v = v1) {
528
		v1 = atomic_cmpxchg(p, v, v - 1);
529
		if (likely(v1 == v))
530
			return 1;
531
	}
532
	return 0;
533
}
534
#endif
535
 
536
/*
537
 * atomic_dec_if_positive - decrement by 1 if old value positive
538
 * @v: pointer of type atomic_t
539
 *
540
 * The function returns the old value of *v minus 1, even if
541
 * the atomic variable, v, was not decremented.
542
 */
543
#ifndef atomic_dec_if_positive
544
static inline int atomic_dec_if_positive(atomic_t *v)
545
{
546
	int c, old, dec;
547
	c = atomic_read(v);
548
	for (;;) {
549
		dec = c - 1;
550
		if (unlikely(dec < 0))
551
			break;
552
		old = atomic_cmpxchg((v), c, dec);
553
		if (likely(old == c))
554
			break;
555
		c = old;
556
	}
557
	return dec;
558
}
559
#endif
560
 
7143 serge 561
/**
562
 * atomic_fetch_or - perform *p |= mask and return old value of *p
563
 * @p: pointer to atomic_t
564
 * @mask: mask to OR on the atomic_t
565
 */
566
#ifndef atomic_fetch_or
567
static inline int atomic_fetch_or(atomic_t *p, int mask)
568
{
569
	int old, val = atomic_read(p);
570
 
571
	for (;;) {
572
		old = atomic_cmpxchg(p, val, val | mask);
573
		if (old == val)
574
			break;
575
		val = old;
576
	}
577
 
578
	return old;
579
}
580
#endif
581
 
6082 serge 582
#ifdef CONFIG_GENERIC_ATOMIC64
583
#include 
584
#endif
585
 
586
#ifndef atomic64_andnot
587
static inline void atomic64_andnot(long long i, atomic64_t *v)
5270 serge 588
{
6082 serge 589
	atomic64_and(~i, v);
5270 serge 590
}
6082 serge 591
#endif
5270 serge 592
 
593
#include 
6082 serge 594
 
5270 serge 595
#endif /* _LINUX_ATOMIC_H */