• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-
2  * Copyright (c) 2010 Isilon Systems, Inc.
3  * Copyright (c) 2010 iX Systems, Inc.
4  * Copyright (c) 2010 Panasas, Inc.
5  * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice unmodified, this list of conditions, and the following
13  *    disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 #ifndef	_LINUXKPI_LINUX_WORKQUEUE_H_
30 #define	_LINUXKPI_LINUX_WORKQUEUE_H_
31 
32 #include "pthread.h"
33 #include "los_task.h"
34 #include "semaphore.h"
35 #include "los_memory.h"
36 #include "los_event.h"
37 #include "linux/list.h"
38 #include "linux/timer.h"
39 
40 #ifdef __cplusplus
41 #if __cplusplus
42 extern "C" {
43 #endif /* __cplusplus */
44 #endif /* __cplusplus */
45 
46 
47 struct lock_class_key {
48 };
49 
50 #ifdef WORKQUEUE_SUPPORT_PRIORITY
51 /**
52  * @ingroup los_task
53  * Define a usable work priority.
54  *
55  * Highest task priority.
56  */
57 #define OS_WORK_PRIORITY_HIGHEST                    0
58 
59 /**
60  * @ingroup los_task
61  * Define a usable work priority.
62  *
63  * Lowest task priority.
64  */
65 #define OS_WORK_PRIORITY_LOWEST                     31
66 
67 
68 /**
69  * @ingroup los_task
70  * Define a usable work priority.
71  *
72  * Default task priority.
73  */
74 #define OS_WORK_PRIORITY_DEFAULT                     OS_WORK_PRIORITY_LOWEST
75 #endif
76 
77 /**
78  * @ingroup workqueue
79  * System default workqueue.
80  */
81 extern struct workqueue_struct *g_pstSystemWq;
82 
83 /**
84  * @ingroup workqueue
85  * Workqueue task control block structure.
86  */
87 typedef struct LosTaskCB task_struct;
88 
89 /**
90  * @ingroup workqueue
91  * Define atomic_long_t as a signed integer.
92  *
93  */
94 typedef long atomic_long_t;
95 
96 struct work_struct;
97 
98 /**
99  * @ingroup workqueue
100  * Workqueue handling function.
101  */
102 typedef void (*work_func_t)(struct work_struct *);
103 
104 /**
105  * @ingroup workqueue
106  * Work structure.
107  * A work is a node in a workqueue.
108  */
109 struct work_struct {
110     atomic_long_t data;        /**< Input parameter of the work handling function. */
111     struct list_head entry;    /**< Pointer to a doubly linked list of a work. */
112     work_func_t func;          /**< Work handling function. */
113     unsigned int work_status;  /**< Work status. */
114 #ifdef WORKQUEUE_SUPPORT_PRIORITY
115     unsigned int work_pri;
116 #endif
117 };
118 
119 /**
120  * @ingroup workqueue
121  * delayed_work structure.
122  * A delayed_work is a work that is delayed to be mounted to a workqueue.
123  */
124 struct delayed_work {
125     struct work_struct work;        /**< Work structure. */
126     struct timer_list timer;        /**< Delay control block parameter structure. */
127     struct workqueue_struct *wq;    /**< Workqueue that contains the delayed_work structure. */
128     int cpu;                        /**< Number of CPUs. Not in use temporarily. */
129 };
130 
131 /**
132  * @ingroup workqueue
133  * Workqueue control structure.
134  * It awakes a workqueue or makes a workqueue sleep.
135  */
136 typedef struct tag_cpu_workqueue_struct {
137     struct list_head worklist;         /**< Pointer to a work doubly linked list. */
138     struct work_struct *current_work;  /**< Work that is being executed. */
139     struct workqueue_struct *wq;       /**< Workqueue that contains the workqueue control structure. */
140     task_struct *thread;               /**< Workqueue handling thread. */
141 } cpu_workqueue_struct;
142 
143 /**
144  * @ingroup workqueue
145  * Definition of a workqueue structure.
146  */
147 struct workqueue_struct {
148     cpu_workqueue_struct *cpu_wq;   /**< Workqueue control structure. */
149     struct list_head list;          /**< Pointer to a workqueue doubly linked list. */
150     EVENT_CB_S wq_event;            /**< Event of a workqueue. */
151     unsigned int wq_id;             /**< Workqueue ID. */
152     int delayed_work_count;         /**< Number of delayed works in a workqueue. */
153     char *name;                     /**< Workqueue name. */
154     int singlethread;               /**< Whether to create a new working task. 0 indicates that
155                                          the default working task will be used. */
156     int wq_status;                  /**< Workqueue status. */
157     int freezeable;                 /**< Not in use temporarily. */
158     int rt;                         /**< Not in use temporarily. */
159 };
160 
161 /**
162  * @ingroup workqueue
163  * Work status enumeration.
164  */
165 enum work_status {
166     WORK_BUSY_PENDING   = 1U << 0,    /**< The status of work item is pending execution. */
167     WORK_BUSY_RUNNING   = 1U << 1,    /**< The status of work item is running. */
168     WORK_STRUCT_PENDING = 1U << 0,    /**< Work item is pending execution. */
169     WORK_STRUCT_RUNNING = 1U << 1,    /**< Work item is running. */
170 };
171 
172 /**
173  * @ingroup workqueue
174  * Initialize a work.
175  */
176 #ifdef WORKQUEUE_SUPPORT_PRIORITY
177 #define INIT_WORK(work, callbackFunc)  do {      \
178     INIT_LIST_HEAD(&((work)->entry));            \
179     (work)->func = (callbackFunc);               \
180     (work)->data = (atomic_long_t)(0);           \
181     (work)->work_status = 0;                     \
182     (work)->work_pri = OS_WORK_PRIORITY_DEFAULT; \
183 } while (0)
184 #else
185 #define INIT_WORK(work, callbackFunc)  do { \
186     INIT_LIST_HEAD(&((work)->entry));       \
187     (work)->func = (callbackFunc);          \
188     (work)->data = (atomic_long_t)(0);      \
189     (work)->work_status = 0;                \
190 } while (0)
191 #endif
192 
193 /**
194  * @ingroup workqueue
195  * Initialize a delayed work.
196  */
197 #define INIT_DELAYED_WORK(work, func) \
198     linux_init_delayed_work(work, func)
199 
200 #define create_singlethread_workqueue(name) \
201     linux_create_singlethread_workqueue(name)
202 
203 #define create_workqueue(name) \
204     linux_create_singlethread_workqueue(name)
205 
206 #define destroy_workqueue(wq) \
207     linux_destroy_workqueue(wq)
208 
209 #define queue_work(wq, work) \
210     linux_queue_work(wq, work)
211 
212 #define queue_delayed_work(wq, dwork, delayTime) \
213     linux_queue_delayed_work(wq, dwork, delayTime)
214 
215 #define schedule_work(work) \
216     linux_schedule_work(work)
217 
218 #define schedule_delayed_work(dwork, delayTime) \
219     linux_schedule_delayed_work(dwork, delayTime)
220 
221 #define work_busy(work) \
222     linux_work_busy(work)
223 
224 #define flush_delayed_work(dwork) \
225     linux_flush_delayed_work(dwork)
226 
227 #define cancel_delayed_work(dwork) \
228     linux_cancel_delayed_work(dwork)
229 
230 #define cancel_delayed_work_sync(dwork) \
231     linux_cancel_delayed_work_sync(dwork)
232 
233 #define flush_work(work) \
234     linux_flush_work(work)
235 
236 #define cancel_work_sync(work) \
237     linux_cancel_work_sync(work)
238 
239 /* prototypes */
240 
241 /**
242  * @ingroup  workqueue
243  * @brief Initialize a delayed work.
244  *
245  * @par Description:
246  * This API is used to initialize a delayed work.
247  *
248  * @attention
249  * <ul>
250  * <li>The parameter dwork and func shoud be valid memory, otherwise, the system may be abnormal. </li>
251  * </ul>
252  *
253  * @param  dwork   [IN] Work handle.
254  * @param  func    [IN] Executive function.
255  *
256  * @retval  None.
257  * @par Dependency:
258  * <ul><li>workqueue.h: the header file that contains the API declaration.</li></ul>
259  * @see none.
260  */
261 extern void linux_init_delayed_work(struct delayed_work *dwork, work_func_t func);
262 
263 /**
264  * @ingroup  workqueue
265  * @brief Create a workqueue.
266  *
267  * @par Description:
268  * This API is used to create a workqueue that has a specified name.
269  *
270  * @attention
271  * <ul>
272  * <li> The passed-in workqueue name is a character string that cannot be null
273  * and is the only identifier of the workqueue, make sure it is unique. </li>
274  * </ul>
275  *
276  * @param  name  [IN] Workqueue name.
277  *
278  * @retval  NULL                   The workqueue fails to be created.
279  * @retval  workqueue_struct*      The workqueue is successfully created.
280  * @par Dependency:
281  * <ul><li>workqueue.h: the header file that contains the API declaration.</li></ul>
282  * @see destroy_workqueue
283  */
284 extern struct workqueue_struct *linux_create_singlethread_workqueue(char *name);
285 
286 /**
287  * @ingroup  workqueue
288  * @brief Delete a workqueue.
289  *
290  * @par Description:
291  * This API is used to delete a workqueue that has a specified handle.
292  *
293  * @attention
294  * <ul>
295  * <li>The name of the workqueue will be null and the workqueue cannot be used again
296  * after the workqueue is deleted. </li>
297  * </ul>
298  *
299  * @param  wq  [IN] Workqueue handle.
300  *
301  * @retval  None.
302  * @par Dependency:
303  * <ul><li>workqueue.h: the header file that contains the API declaration.</li></ul>
304  * @see create_workqueue
305  */
306 extern void linux_destroy_workqueue(struct workqueue_struct *wq);
307 
308 /**
309  * @ingroup  workqueue
310  * @brief Queue a work on a workqueue.
311  *
312  * @par Description:
313  * This API is used to queue a work on a specified workqueue.
314  *
315  * @attention
316  * <ul>
317  * <li>The parameter wq and work shoud be valid memory, otherwise, the system may be abnormal. </li>
318  * <li>The work will be immediately queued on the workqueue. </li>
319  * </ul>
320  *
321  * @param  wq     [IN] Workqueue handle.
322  * @param  work  [IN] Work handle.
323  *
324  * @retval #TRUE      The work is successfully queued on the workqueue.
325  * @retval #FALSE     The work fails to be queued on the workqueue.
326  * @par Dependency:
327  * <ul>
328  * <li>This function should be used after create_singlethread_workqueue() or create_workqueue() has been called</li>
329  * <li>workqueue.h: the header file that contains the API declaration.</li>
330  * </ul>
331  * @see cancel_work_sync
332  */
333 extern bool linux_queue_work(struct workqueue_struct *wq, struct work_struct *work);
334 
335 /**
336  * @ingroup  workqueue
337  * @brief Queue a work on a workqueue after delay.
338  *
339  * @par Description:
340  * This API is used to queue a work on a specified workqueue after delay.
341  *
342  * @attention
343  * <ul>
344  * <li>The parameter wq and dwork shoud be valid memory, otherwise, the system may be abnormal. </li>
345  * <li>The work will be queued on the workqueue in a delayed period of time. </li>
346  * <li>The work will be queued on the workqueue immediately if delayTime is 0, it as same as queue_work(). </li>
347  * </ul>
348  *
349  * @param  wq         [IN] Workqueue handle.
350  * @param  dwork      [IN] Delayed work handle.
351  * @param  delayTime  [IN] Delayed time, number of ticks to wait or 0 for immediate execution.
352  *
353  * @retval #TRUE      The work is successfully queued on the workqueue.
354  * @retval #FALSE     The work fails to be queued on the workqueue.
355  * @par Dependency:
356  * <ul>
357  * <li>This function should be used after create_singlethread_workqueue() or create_workqueue() has been called</li>
358  * <li>workqueue.h: the header file that contains the API declaration.</li>
359  * </ul>
360  * @see cancel_delayed_work
361  */
362 extern bool linux_queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *dwork, unsigned int delayTime);
363 
364 /**
365  * @ingroup  workqueue
366  * @brief Put a work in a default workqueue.
367  *
368  * @par Description:
369  * This API is used to put a work in the default workqueue that is created when Huawei LiteOS is initialized.
370  *
371  * @attention
372  * <ul>
373  * <li>The parameter work shoud be valid memory, otherwise, the system may be abnormal. </li>
374  * <li>The default workqueue is g_pstSystemWq. </li>
375  * </ul>
376  *
377  * @param  work        [IN] Work handle.
378  *
379  * @retval #TRUE      The work is successfully put in the workqueue.
380  * @retval #FALSE     The work fails to be put in the workqueue.
381  * @par Dependency:
382  * <ul>
383  * <li>This function should be used after create_singlethread_workqueue() or create_workqueue() has been called</li>
384  * <li>workqueue.h: the header file that contains the API declaration.</li>
385  * </ul>
386  * @see cancel_work_sync
387  */
388 extern bool linux_schedule_work(struct work_struct *work);
389 
390 /**
391  * @ingroup  workqueue
392  * @brief Put a work in a default workqueue after delay.
393  *
394  * @par Description:
395  * This API is used to put a work in the default workqueue that is created
396  * when Huawei LiteOS is initialized in a delayed period of time.
397  *
398  * @attention
399  * <ul>
400  * <li>The parameter dwork shoud be valid memory, otherwise, the system may be abnormal. </li>
401  * <li>The default workqueue is g_pstSystemWq. </li>
402  * <li>The dwork will be queued on the workqueue immediately if delayTime is 0. </li>
403  * </ul>
404  *
405  * @param  dwork         [IN] Delayed work handle.
406  * @param  delayTime     [IN] Delayed time, number of ticks to wait or 0 for immediate execution.
407  *
408  * @retval #TRUE      The work is successfully put in the workqueue.
409  * @retval #FALSE     The work fails to be put in the workqueue.
410  * @par Dependency:
411  * <ul>
412  * <li>This function should be used after create_singlethread_workqueue() or create_workqueue() has been called</li>
413  * <li>workqueue.h: the header file that contains the API declaration.</li>
414  * </ul>
415  * @see cancel_delayed_work
416  */
417 extern bool linux_schedule_delayed_work(struct delayed_work *dwork, unsigned int delayTime);
418 
419 /**
420  * @ingroup  workqueue
421  * @brief Query the work status.
422  *
423  * @par Description:
424  * This API is used to query the status of a work and a delayed work.
425  *
426  * @attention
427  * <ul>
428  * <li>The parameter work shoud be valid memory, otherwise, the system may be abnormal.</li>
429  * </ul>
430  *
431  * @param  work          [IN] Work handle.
432  *
433  * @retval #WORK_BUSY_PENDING      The work is pending.
434  * @retval #WORK_BUSY_RUNNING      The work is running.
435  * @retval #FALSE                  The value of the parameter work is NULL.
436  * @par Dependency:
437  * <ul><li>workqueue.h: the header file that contains the API declaration.</li></ul>
438  * @see None.
439  */
440 extern unsigned int linux_work_busy(struct work_struct *work);
441 
442 /**
443  * @ingroup  workqueue
444  * @brief Immediately execute a delayed work.
445  *
446  * @par Description:
447  * This API is used to immediately put a delayed work in a workqueue
448  * and wait for the execution of the delayed work to end.
449  *
450  * @attention
451  * <ul>
452  * <li>flush_delayed_work() should be used after queue_delayed_work() has been called.</li>
453  * <li>The parameter dwork shoud be valid memory, otherwise, the system may be abnormal.</li>
454  * </ul>
455  *
456  * @param  dwork          [IN] Delayed work handle.
457  *
458  * @retval #TRUE      The operation succeeds.
459  * @retval #FALSE     The operation fails.
460  * @par Dependency
461  * <ul><li>workqueue.h: the header file that contains the API declaration.</li></ul>
462  * @see None.
463  */
464 extern bool linux_flush_delayed_work(struct delayed_work *dwork);
465 
466 /**
467  * @ingroup  workqueue
468  * @brief Cancel a delayed work.
469  *
470  * @par Description:
471  * This API is used to cancel a delayed work, which means that the work will not be executed regardless of
472  * whether the delayed time has expired.
473  *
474  * @attention
475  * <ul>
476  * <li>cancel_delayed_work() should be used after queue_delayed_work() has been called.</li>
477  * <li>The parameter dwork shoud be valid memory, otherwise, the system may be abnormal.</li>
478  * </ul>
479  *
480  * @param  dwork          [IN] Delayed work handle.
481  *
482  * @retval #TRUE      The delayed work is successfully canceled.
483  * @retval #FALSE     The delayed work fails to be canceled.
484  * @par Dependency:
485  * <ul><li>workqueue.h: the header file that contains the API declaration.</li></ul>
486  * @see queue_delayed_work
487  */
488 extern bool linux_cancel_delayed_work(struct delayed_work *dwork);
489 /**
490  * @ingroup  workqueue
491  * @brief Cancel a delayed work and wait for it to finish.
492  *
493  * @par Description:
494  * This API is used to cancel a delayed work, which means that the work will not be executed regardless of
495  * whether the delayed time has expired.
496  *
497  * @attention
498  * <ul>
499  * <li>cancel_delayed_work_sync() should be used after queue_delayed_work() has been called.</li>
500  * <li>The parameter dwork shoud be valid memory, otherwise, the system may be abnormal.</li>
501  * </ul>
502  *
503  * @param  dwork          [IN] Delayed work handle.
504  *
505  * @retval #TRUE      The delayed work is successfully canceled.
506  * @retval #FALSE     The delayed work fails to be canceled.
507  * @par Dependency:
508  * <ul><li>workqueue.h: the header file that contains the API declaration.</li></ul>
509  * @see queue_delayed_work
510  */
511 extern bool linux_cancel_delayed_work_sync(struct delayed_work *dwork);
512 
513 /**
514  * @ingroup  workqueue
515  * @brief Immediately execute a work.
516  *
517  * @par Description:
518  * This API is used to immediately execute a specified work and wait for the execution to end.
519  *
520  * @attention
521  * <ul>
522  * <li>flush_work() should be used after queue_work() has been called.</li>
523  * <li>The parameter work shoud be valid memory, otherwise, the system may be abnormal.</li>
524  * </ul>
525  *
526  * @param  work          [IN] Work handle.
527  *
528  * @retval #TRUE      The operation succeeds.
529  * @retval #FALSE     The operation fails.
530  * @par Dependency:
531  * <ul><li>workqueue.h: the header file that contains the API declaration.</li></ul>
532  * @see None.
533  */
534 extern bool linux_flush_work(struct work_struct *work);
535 
536 /**
537  * @ingroup  workqueue
538  * @brief Cancel a work.
539  *
540  * @par Description:
541  * This API is used to cancel a work that is pending or running.
542  *
543  * @attention
544  * <ul>
545  * <li>cancel_work_sync() should be used after queue_work() has been called.</li>
546  * <li>The parameter work shoud be valid memory, otherwise, the system may be abnormal.</li>
547  * </ul>
548  *
549  * @param  work          [IN] Work handle.
550  *
551  * @retval #TRUE      The work is successfully canceled.
552  * @retval #FALSE     The work fails to be canceled.
553  * @par Dependency:
554  * <ul><li>workqueue.h: the header file that contain the API declaration.</li></ul>
555  * @see queue_work
556  */
557 extern bool linux_cancel_work_sync(struct work_struct *work);
558 
559 #ifdef __cplusplus
560 #if __cplusplus
561 }
562 #endif /* __cplusplus */
563 #endif /* __cplusplus */
564 
565 #endif /* _LINUXKPI_LINUX_WORKQUEUE_H_ */
566