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