Factor out lwkt_serialize_array_{enter,try,exit}()
[dragonfly.git] / sys / sys / serialize.h
1 /*
2  * Provides a fast serialization facility that will serialize across blocking
3  * conditions.  This facility is very similar to a lock but much faster for
4  * the common case.  It utilizes the atomic_intr_*() functions to acquire
5  * and release the serializer and token functions to block.
6  *
7  * This API is designed to be used whenever low level serialization is
8  * required.  Unlike tokens this serialization is not safe from deadlocks
9  * nor is it recursive, and care must be taken when using it. 
10  *
11  * $DragonFly: src/sys/sys/serialize.h,v 1.9 2008/05/14 11:59:24 sephe Exp $
12  */
13
14 #ifndef _SYS_SERIALIZE_H_
15 #define _SYS_SERIALIZE_H_
16
17 #ifndef _KERNEL
18 #error "kernel only header file"
19 #endif
20
21 #ifndef _SYS_PARAM_H_
22 #include <sys/param.h>
23 #endif
24
25 #ifndef _SYS_SYSTM_H_
26 #include <sys/systm.h>
27 #endif
28
29 #ifndef _MACHINE_STDINT_H_
30 #include <machine/stdint.h>
31 #endif
32
33 struct thread;
34
35 struct lwkt_serialize {
36     __atomic_intr_t     interlock;
37     struct thread       *last_td;
38     unsigned int        sleep_cnt;
39     unsigned int        tryfail_cnt;
40     unsigned int        enter_cnt;
41     unsigned int        try_cnt;
42 };
43
44 #ifdef INVARIANTS
45 /*
46  * Note that last_td is only maintained when INVARIANTS is turned on,
47  * so this check is only useful as part of a [K]KASSERT.
48  */
49 #define IS_SERIALIZED(ss)               ((ss)->last_td == curthread)
50 #endif
51
52 #define ASSERT_SERIALIZED(ss)           KKASSERT(IS_SERIALIZED((ss)))
53 #define ASSERT_NOT_SERIALIZED(ss)       KKASSERT(!IS_SERIALIZED((ss)))
54
55 typedef struct lwkt_serialize *lwkt_serialize_t;
56
57 void lwkt_serialize_init(lwkt_serialize_t);
58 void lwkt_serialize_enter(lwkt_serialize_t);
59 #ifdef SMP
60 void lwkt_serialize_adaptive_enter(lwkt_serialize_t);
61 #endif
62 int lwkt_serialize_try(lwkt_serialize_t);
63 void lwkt_serialize_exit(lwkt_serialize_t);
64 void lwkt_serialize_handler_disable(lwkt_serialize_t);
65 void lwkt_serialize_handler_enable(lwkt_serialize_t);
66 void lwkt_serialize_handler_call(lwkt_serialize_t, void (*)(void *, void *), void *, void *);
67 int lwkt_serialize_handler_try(lwkt_serialize_t, void (*)(void *, void *), void *, void *);
68
69 static __inline void
70 lwkt_serialize_array_enter(lwkt_serialize_t *_arr, int _arrcnt, int _s)
71 {
72         KASSERT(_s < _arrcnt, ("nothing to be serialized\n"));
73         while (_s < _arrcnt)
74                 lwkt_serialize_enter(_arr[_s++]);
75 }
76
77 static __inline int
78 lwkt_serialize_array_try(lwkt_serialize_t *_arr, int _arrcnt, int _s)
79 {
80         int _i;
81
82         KASSERT(_s < _arrcnt, ("nothing to be serialized\n"));
83         for (_i = _s; _i < _arrcnt; ++_i) {
84                 if (!lwkt_serialize_try(_arr[_i])) {
85                         while (--_i >= _s)
86                                 lwkt_serialize_exit(_arr[_i]);
87                         return 0;
88                 }
89         }
90         return 1;
91 }
92
93 static __inline void
94 lwkt_serialize_array_exit(lwkt_serialize_t *_arr, int _arrcnt, int _s)
95 {
96         KASSERT(_arrcnt > _s, ("nothing to be deserialized\n"));
97         while (--_arrcnt >= _s)
98                 lwkt_serialize_exit(_arr[_arrcnt]);
99 }
100
101 #endif  /* !_SYS_SERIALIZE_H_ */