blob: 60c01fa024845c0dadb6aaf73461ea8436fffe8a [file] [log] [blame]
Damjan Marion94100532020-11-06 23:25:57 +01001/*
2 * Copyright (c) 2020 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef included_clib_interrupt_h
17#define included_clib_interrupt_h
18
19#include <vppinfra/clib.h>
20#include <vppinfra/bitops.h> /* for count_set_bits */
21#include <vppinfra/vec.h>
22
23typedef struct
24{
25 CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
26 int n_int;
27 uword n_uword_alloc;
28} clib_interrupt_header_t;
29
30void clib_interrupt_init (void **data, uword n_interrupts);
31void clib_interrupt_resize (void **data, uword n_interrupts);
32
33static_always_inline void
34clib_interrupt_free (void **data)
35{
36 if (data[0])
37 {
38 clib_mem_free (data[0]);
39 data[0] = 0;
40 }
41}
42
43static_always_inline int
44clib_interrupt_get_n_int (void *d)
45{
46 clib_interrupt_header_t *h = d;
47 if (h)
48 return h->n_int;
49 return 0;
50}
51
52static_always_inline uword *
53clib_interrupt_get_bitmap (void *d)
54{
55 return d + sizeof (clib_interrupt_header_t);
56}
57
58static_always_inline uword *
59clib_interrupt_get_atomic_bitmap (void *d)
60{
61 clib_interrupt_header_t *h = d;
62 return clib_interrupt_get_bitmap (d) + h->n_uword_alloc;
63}
64
65static_always_inline void
66clib_interrupt_set (void *in, int int_num)
67{
68 uword *bmp = clib_interrupt_get_bitmap (in);
69 uword mask = 1ULL << (int_num & (uword_bits - 1));
70 bmp += int_num >> log2_uword_bits;
71
72 ASSERT (int_num < ((clib_interrupt_header_t *) in)->n_int);
73
74 *bmp |= mask;
75}
76
77static_always_inline void
78clib_interrupt_set_atomic (void *in, int int_num)
79{
80 uword *bmp = clib_interrupt_get_atomic_bitmap (in);
81 uword mask = 1ULL << (int_num & (uword_bits - 1));
82 bmp += int_num >> log2_uword_bits;
83
84 ASSERT (int_num < ((clib_interrupt_header_t *) in)->n_int);
85
86 __atomic_fetch_or (bmp, mask, __ATOMIC_RELAXED);
87}
88
89static_always_inline void
90clib_interrupt_clear (void *in, int int_num)
91{
92 uword *bmp = clib_interrupt_get_bitmap (in);
93 uword *abm = clib_interrupt_get_atomic_bitmap (in);
94 uword mask = 1ULL << (int_num & (uword_bits - 1));
95 uword off = int_num >> log2_uword_bits;
96
97 ASSERT (int_num < ((clib_interrupt_header_t *) in)->n_int);
98
99 bmp[off] |= __atomic_exchange_n (abm + off, 0, __ATOMIC_SEQ_CST);
100 bmp[off] &= ~mask;
101}
102
103static_always_inline int
104clib_interrupt_get_next (void *in, int last)
105{
106 uword *bmp = clib_interrupt_get_bitmap (in);
107 uword *abm = clib_interrupt_get_atomic_bitmap (in);
108 clib_interrupt_header_t *h = in;
109 uword bmp_uword, off;
110
111 ASSERT (last >= -1 && last < h->n_int);
112
113 off = (last + 1) >> log2_uword_bits;
114
115 last -= off << log2_uword_bits;
116 bmp[off] |= __atomic_exchange_n (abm + off, 0, __ATOMIC_SEQ_CST);
117 bmp_uword = bmp[off] & ~pow2_mask (last + 1);
118
119next:
120 if (bmp_uword)
121 return (off << log2_uword_bits) + count_trailing_zeros (bmp_uword);
122
123 off++;
124
125 if (off > h->n_int >> log2_uword_bits)
126 return -1;
127
128 bmp[off] |= __atomic_exchange_n (abm + off, 0, __ATOMIC_SEQ_CST);
129 bmp_uword = bmp[off];
130
131 goto next;
132}
133
134#endif /* included_clib_interrupt_h */
135
136/*
137 * fd.io coding-style-patch-verification: ON
138 *
139 * Local Variables:
140 * eval: (c-set-style "gnu")
141 * End:
142 */