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 42extern "C" { 43#endif /* __cplusplus */ 44#endif /* __cplusplus */ 45 46 47struct 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 */ 81extern struct workqueue_struct *g_pstSystemWq; 82 83/** 84 * @ingroup workqueue 85 * Workqueue task control block structure. 86 */ 87typedef struct LosTaskCB task_struct; 88 89/** 90 * @ingroup workqueue 91 * Define atomic_long_t as a signed integer. 92 * 93 */ 94typedef long atomic_long_t; 95 96struct work_struct; 97 98/** 99 * @ingroup workqueue 100 * Workqueue handling function. 101 */ 102typedef 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 */ 109struct 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 */ 124struct 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 */ 136typedef 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 */ 147struct 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 */ 165enum 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 */ 261extern 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 */ 284extern 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 */ 306extern 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 */ 333extern 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 */ 362extern 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 */ 388extern 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 */ 417extern 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 */ 440extern 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 */ 464extern 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 */ 488extern 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 */ 511extern 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 */ 534extern 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 */ 557extern 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