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