blob: b0d7dde272a1d67348f430f673f468bc181558bc [file] [log] [blame]
Damjan Marion7f75e802023-11-03 21:57:42 +00001/* SPDX-License-Identifier: Apache-2.0
2 * Copyright (c) 2023 Cisco Systems, Inc.
Damjan Marion94100532020-11-06 23:25:57 +01003 */
4
5#ifndef included_clib_interrupt_h
6#define included_clib_interrupt_h
7
8#include <vppinfra/clib.h>
Damjan Marion94100532020-11-06 23:25:57 +01009#include <vppinfra/vec.h>
10
11typedef struct
12{
13 CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
Damjan Marion7f75e802023-11-03 21:57:42 +000014 u32 n_int;
15 u32 uwords_allocated;
16 u32 uwords_used;
17 uword *local;
18 uword *remote;
Damjan Marion94100532020-11-06 23:25:57 +010019} clib_interrupt_header_t;
20
Damjan Marion7f75e802023-11-03 21:57:42 +000021void clib_interrupt_init (void **data, u32 n_interrupts);
22void clib_interrupt_resize (void **data, u32 n_interrupts);
Damjan Marion94100532020-11-06 23:25:57 +010023
24static_always_inline void
25clib_interrupt_free (void **data)
26{
27 if (data[0])
28 {
29 clib_mem_free (data[0]);
30 data[0] = 0;
31 }
32}
33
34static_always_inline int
35clib_interrupt_get_n_int (void *d)
36{
37 clib_interrupt_header_t *h = d;
38 if (h)
39 return h->n_int;
40 return 0;
41}
42
Damjan Marion94100532020-11-06 23:25:57 +010043static_always_inline void
44clib_interrupt_set (void *in, int int_num)
45{
Damjan Marion7f75e802023-11-03 21:57:42 +000046 clib_interrupt_header_t *h = in;
47 u32 off = int_num >> log2_uword_bits;
48 uword bit = 1ULL << (int_num & pow2_mask (log2_uword_bits));
Damjan Marion94100532020-11-06 23:25:57 +010049
Damjan Marion7f75e802023-11-03 21:57:42 +000050 ASSERT (int_num < h->n_int);
Damjan Marion94100532020-11-06 23:25:57 +010051
Damjan Marion7f75e802023-11-03 21:57:42 +000052 h->local[off] |= bit;
Damjan Marion94100532020-11-06 23:25:57 +010053}
54
55static_always_inline void
56clib_interrupt_set_atomic (void *in, int int_num)
57{
Damjan Marion7f75e802023-11-03 21:57:42 +000058 clib_interrupt_header_t *h = in;
59 u32 off = int_num >> log2_uword_bits;
60 uword bit = 1ULL << (int_num & pow2_mask (log2_uword_bits));
Damjan Marion94100532020-11-06 23:25:57 +010061
Damjan Marion7f75e802023-11-03 21:57:42 +000062 ASSERT (int_num < h->n_int);
Damjan Marion94100532020-11-06 23:25:57 +010063
Damjan Marion7f75e802023-11-03 21:57:42 +000064 __atomic_fetch_or (h->remote + off, bit, __ATOMIC_RELAXED);
Damjan Marion94100532020-11-06 23:25:57 +010065}
66
67static_always_inline void
68clib_interrupt_clear (void *in, int int_num)
69{
Damjan Marion7f75e802023-11-03 21:57:42 +000070 clib_interrupt_header_t *h = in;
71 u32 off = int_num >> log2_uword_bits;
72 uword bit = 1ULL << (int_num & pow2_mask (log2_uword_bits));
73 uword *loc = h->local;
74 uword *rem = h->remote;
75 uword v;
Damjan Marion94100532020-11-06 23:25:57 +010076
Damjan Marion7f75e802023-11-03 21:57:42 +000077 ASSERT (int_num < h->n_int);
Damjan Marion94100532020-11-06 23:25:57 +010078
Damjan Marion7f75e802023-11-03 21:57:42 +000079 v = loc[off] | __atomic_exchange_n (rem + off, 0, __ATOMIC_SEQ_CST);
80 loc[off] = v & ~bit;
Damjan Marion94100532020-11-06 23:25:57 +010081}
82
83static_always_inline int
Damjan Marion7f75e802023-11-03 21:57:42 +000084clib_interrupt_get_next_and_clear (void *in, int last)
Damjan Marion94100532020-11-06 23:25:57 +010085{
Damjan Marion94100532020-11-06 23:25:57 +010086 clib_interrupt_header_t *h = in;
Damjan Marion7f75e802023-11-03 21:57:42 +000087 uword bit, v;
88 uword *loc = h->local;
89 uword *rem = h->remote;
90 u32 off, n_uwords = h->uwords_used;
Damjan Marion94100532020-11-06 23:25:57 +010091
Damjan Marion7f75e802023-11-03 21:57:42 +000092 ASSERT (last >= -1 && last < (int) h->n_int);
Damjan Marion94100532020-11-06 23:25:57 +010093
94 off = (last + 1) >> log2_uword_bits;
Damjan Marion7f75e802023-11-03 21:57:42 +000095
96 if (off >= n_uwords)
Paul Atkinsdfc43162022-04-06 14:51:21 +010097 return -1;
Damjan Marion94100532020-11-06 23:25:57 +010098
Damjan Marion7f75e802023-11-03 21:57:42 +000099 v = loc[off] | __atomic_exchange_n (rem + off, 0, __ATOMIC_SEQ_CST);
100 loc[off] = v;
Damjan Marion94100532020-11-06 23:25:57 +0100101
Damjan Marion7f75e802023-11-03 21:57:42 +0000102 v &= ~pow2_mask ((last + 1) & pow2_mask (log2_uword_bits));
Damjan Marion94100532020-11-06 23:25:57 +0100103
Damjan Marion7f75e802023-11-03 21:57:42 +0000104 while (v == 0)
105 {
106 if (++off == n_uwords)
107 return -1;
Damjan Marion94100532020-11-06 23:25:57 +0100108
Damjan Marion7f75e802023-11-03 21:57:42 +0000109 v = loc[off] | __atomic_exchange_n (rem + off, 0, __ATOMIC_SEQ_CST);
110 loc[off] = v;
111 }
Damjan Marion94100532020-11-06 23:25:57 +0100112
Damjan Marion7f75e802023-11-03 21:57:42 +0000113 bit = get_lowest_set_bit (v);
114 loc[off] &= ~bit;
115 return get_lowest_set_bit_index (bit) + (int) (off << log2_uword_bits);
116}
Damjan Marion94100532020-11-06 23:25:57 +0100117
Damjan Marion7f75e802023-11-03 21:57:42 +0000118static_always_inline int
119clib_interrupt_is_any_pending (void *in)
120{
121 clib_interrupt_header_t *h = in;
122 u32 n_uwords = h->uwords_used;
123 uword *loc = h->local;
124 uword *rem = h->remote;
125
126 for (u32 i = 0; i < n_uwords; i++)
127 if (loc[i])
128 return 1;
129
130 for (u32 i = 0; i < n_uwords; i++)
131 if (rem[i])
132 return 1;
133
134 return 0;
Damjan Marion94100532020-11-06 23:25:57 +0100135}
136
137#endif /* included_clib_interrupt_h */