EVE 1.0
work.h
Go to the documentation of this file.
1 #ifndef EVE_WORK_H_INCLUDED
2 #define EVE_WORK_H_INCLUDED
3 
4 /**********************************************************************/
5 /*
6  * Copyright (c) 2013-2015, Jetro AS
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modification,
10  * are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  * derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONRIBUTORS ``AS IS'' AND ANY EXPRESS
21  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
23  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
25  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
29  * OF SUCH DAMAGE.
30  *
31  * This file is part of the EVE platform.
32  */
33 
34 /**
35  * \file
36  * \brief Header file for the EVE work scheduling.
37  *
38  * \author DT, Jetro AS
39  */ /******************************************************************/
40 
41 #include <stdbool.h>
42 #include <lib/dlist.h>
43 
44 /**
45  * \defgroup eve_work Generic work scheduler
46  * \ingroup eve_scheduling
47  * \{
48  */
49 
50 /**********************************************************************/
51 /**
52  * Initializes a work structure.
53  *
54  * The macro is used to initialize a work structure instance.
55  *
56  * \param work work structure
57  * \param callback work callback
58  *
59  * Usage:
60  * \code
61  static void MyWorkCallback(struct work_t *Work);
62  struct work_t MyWork = WORK_INIT(MyWork, MyWorkCallback);
63  * \endcode
64  */
65 #define WORK_INIT(work, callback) \
66  { \
67  .link.next = &work.link, \
68  .link.prev = &work.link, \
69  .cb = callback, \
70  }
71 
72 /**********************************************************************/
73 /**
74  * Initializes a work structure. Typed version of \ref WORK_INIT
75  */
76 #define WORK_INIT_TYPED(work, callback) \
77  (struct work_t) WORK_INIT(work, callback)
78 
79 /**********************************************************************/
80 /**
81  * Instantiates a work structure.
82  *
83  * The macro is used to instantiate a work structure.
84  *
85  * \param work name of the work structure
86  * \param callback the work callback
87  *
88  * Usage:
89  * \code
90  static void MyWorkCallback(struct work_t *Work);
91  DECLARE_WORK(MyWork, MyWorkCallback);
92  * \endcode
93  */
94 #define DECLARE_WORK(work, callback) \
95  struct work_t work = WORK_INIT(work, callback)
96 
97 /**********************************************************************/
98 /**
99  * Declares an anonymous software interrupt lock, which disables
100  * software interrupts in scope of the the auto variable visibility block
101  *
102  * Usage:
103  * \code
104  {
105  SWINT_AUTO_LOCK();
106  // Do something protected by the lock
107  }
108  // The lock is released here
109  * \endcode
110  *
111  * Note: taking in mind lazy nature of releasing the clock locks, use of auto clock locks is negligible.
112  */
113 #define SWINT_AUTO_LOCK() \
114  swint_state_t swint_auto_lock_state __attribute__((cleanup(swint_enable_indirect_adapter))); \
115  do { swint_auto_lock_state = swint_disable(); } while (0)
116 
117 /* Forward declaration */
118 struct work_t;
119 
120 /**********************************************************************/
121 /**
122  * Work callback type.
123  *
124  * \param work pointer to the work structure
125  */
126 typedef void (*work_cb_t)(struct work_t *work);
127 
128 /**********************************************************************/
129 /**
130  * Work structure.
131  *
132  * EVE `work item` is a function with an associated data structure,
133  * which can be executed at the software interrupt execution level.
134  *
135  * The structure represents the work item instance.
136  *
137  * The structure must be instantiated in the RAM memory using
138  * one of \ref WORK_INIT() or \ref DECLARE_WORK().
139  */
140 struct work_t {
141  struct dlist_t link; /**< Linked list of all scheduled work items */
142  work_cb_t cb; /**< Callback function to be called for the work */
143 };
144 
145 /**********************************************************************/
146 /**
147  * Software interrupt state.
148  *
149  * The structure holds state if the software interrupts are enabled.
150  */
151 typedef struct {
152  bool disabled; /**< true if software interrupt processing is disabled */
153 } swint_state_t;
154 
155 /**********************************************************************/
156 /**
157  * Schedules a work.
158  *
159  * The function schedules a work item for execution at the software interrupt level.
160  * Depending on the current interrupt level and the software interrupt enable status,
161  * the work item callback may be called immediately or be queued until the software
162  * interrupt level is available.
163  *
164  * Framework keeps order of execution of the scheduled work items. First scheduled work
165  * is executed first.
166  *
167  * Is the work structure, pointed by the `work` parameter is already scheduled for execution,
168  * then it is re-scheduled at the tail of the work queue.
169  *
170  * \param work pointer to the work structure
171  */
172 void work_schedule(struct work_t *work);
173 
174 /**********************************************************************/
175 /**
176  * Removes a work from the work queue.
177  *
178  * The function removes a previously scheduled work from the work queue.
179  *
180  * \param work pointer to the work structure
181  */
182 void work_cancel(struct work_t *work);
183 
184 /**********************************************************************/
185 /**
186  * Checks if the work is scheduled and pending execution.
187  *
188  * The function checks if the work is scheduled for execution.
189  *
190  * \param work pointer to the work structure
191  * \return true if the work is scheduled for execution
192  * \return false if the work is not scheduled
193  * \return false if the work is being executed
194  */
195 static inline bool work_pending(struct work_t *work)
196 {
197  return !dlist_is_empty(&work->link);
198 }
199 
200 /**********************************************************************/
201 /**
202  * Disables software interrupt processing
203  *
204  * The function disables software interrupt processing
205  *
206  * Usage:
207  * \code
208  swint_state_t swint_state = swint_disable();
209  // Do something atomically
210  swint_enable(swint_state);
211  * \endcode
212  *
213  * \return previous software interrupt status
214  */
216 
217 /**********************************************************************/
218 /**
219  * Restores software interrupt processing
220  *
221  * The function conditionally enables software interrupt processing
222  *
223  * Usage:
224  * \code
225  swint_state_t swint_state = swint_disable();
226  // Do something atomically
227  swint_enable(swint_state);
228  * \endcode
229  *
230  * \param state state, obtained by corresponding swint_disable() call
231  */
232 void swint_enable(swint_state_t state);
233 
234 /**********************************************************************/
235 /**
236  * \internal
237  *
238  */ /******************************************************************/
239 
240 
241 /**********************************************************************/
242 /**
243  * Cleanup adapter for SWINT_AUTO_LOCK()
244  */
245 __attribute__((always_inline))
246 static inline void swint_enable_indirect_adapter(swint_state_t *state)
247 {
248  swint_enable(*state);
249 }
250 
251 /** \} eve_work */
252 
253 #endif /* EVE_WORK_H_INCLUDED */
struct dlist_t link
Definition: work.h:141
void work_cancel(struct work_t *work)
void(* work_cb_t)(struct work_t *work)
Definition: work.h:126
The code implements Dummy Headed Doubly Linked Circularlist (DHDLC) primitive.
work_cb_t cb
Definition: work.h:142
void work_schedule(struct work_t *work)
static int dlist_is_empty(struct dlist_t *list)
Definition: dlist.h:125
__attribute__((always_inline)) static inline void swint_enable_indirect_adapter(swint_state_t *state)
Definition: work.h:245
bool disabled
Definition: work.h:152
static bool work_pending(struct work_t *work)
Definition: work.h:195
Definition: dlist.h:66
void swint_enable(swint_state_t state)
swint_state_t swint_disable(void)
Definition: work.h:140