Schedule Work ============= .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow Topics in this section, * :ref:`Version Info ` * :ref:`Learnings in this program ` * :ref:`Explanation of Workqueue APIs ` * :ref:`INIT_WORK ` * :ref:`schedule_work_on ` * :ref:`cancel_work_sync ` * :ref:`INIT_DELAYED_WORK ` * :ref:`schedule_delayed_work_on ` * :ref:`cancel_delayed_work_sync ` * :ref:`work_on_cpu ` * :ref:`work_on_cpu_safe ` * :ref:`Example 1 : Scheduling the workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initialize work ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Example 2 : Scheduling the workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Initialize work ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Example 3 : Scheduling the workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` * :ref:`Example 4 : Scheduling the workqueue ` * :ref:`List of headers ` * :ref:`Module macros ` * :ref:`Workqueue Handler Function ` * :ref:`Queue Start Function ` * :ref:`Queue Init Function ` * :ref:`Queue Stop Function ` * :ref:`Queue Exit Function ` * :ref:`Driver entry points ` * :ref:`See the full program below ` * :ref:`Makefile ` * :ref:`Compile and Load ` .. _schedule_workqueue_0: .. tab-set:: .. tab-item:: Version Info =============================== ======================================= # Version =============================== ======================================= Ubuntu Ubuntu 22.10 Kernel 6.8.0 =============================== ======================================= .. _schedule_workqueue_1: .. tab-set:: .. tab-item:: Learnings in this section * In this program, you are going to learn .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to create workqueue ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to allocate the work to the queue ? .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use Workqueue APIs ? * `INIT_WORK `_ * `schedule_work_on `_ * `cancel_work_sync `_ * `INIT_DELAYED_WORK `_ * `schedule_delayed_work_on `_ * `cancel_delayed_work_sync `_ * `work_on_cpu `_ * `work_on_cpu_safe `_ .. panels:: :container: container pb-4 :column: col-lg-12 p-2 :card: shadow * How to use below APIs ? * `MODULE_LICENSE `_ * `MODULE_DESCRIPTION `_ * `MODULE_AUTHOR `_ * `module_init `_ * `module_exit `_ .. _schedule_workqueue_2: .. tab-set:: .. tab-item:: Explanation of workqueue APIs .. _schedule_workqueue_3: .. tab-set:: .. tab-item:: INIT_WORK * Here is the function prototype of the API: `INIT_WORK `_ .. code-block:: c #include #define INIT_WORK(_work, _func) * Here is an example of how to use the API, .. code-block:: c INIT_WORK(&my_work_1,workqueue_func_1); .. _schedule_workqueue_4: .. tab-set:: .. tab-item:: schedule_work_on * Here is the function prototype of the API: `schedule_work_on `_ .. code-block:: c #include static inline bool schedule_work_on(int cpu, struct work_struct *work); * Here is an example of how to use the API, .. code-block:: c schedule_work_on(0,&my_work_1); .. _schedule_workqueue_5: .. tab-set:: .. tab-item:: cancel_work_sync * Here is the function prototype of the API: `cancel_work_sync `_ .. code-block:: c #include extern bool cancel_work_sync(struct work_struct *work); * Here is an example of how to use the API, .. code-block:: c cancel_work_sync(&my_work_1); .. _schedule_workqueue_6: .. tab-set:: .. tab-item:: INIT_DELAYED_WORK * Here is the function prototype of the API: `INIT_DELAYED_WORK `_ .. code-block:: c #include #define INIT_DELAYED_WORK(_work, _func) * Here is an example of how to use the API, .. code-block:: c INIT_DELAYED_WORK(&my_work_1,workqueue_func_1); .. _schedule_workqueue_7: .. tab-set:: .. tab-item:: schedule_delayed_work_on * Here is the function prototype of the API: `schedule_delayed_work_on `_ .. code-block:: c #include static inline bool schedule_delayed_work_on(int cpu, struct delayed_work *dwork, unsigned long delay); * Here is an example of how to use the API, .. code-block:: c schedule_delayed_work_on(0,&my_work_1,msecs_to_jiffies(100)); .. _schedule_workqueue_8: .. tab-set:: .. tab-item:: cancel_delayed_work_sync * Here is the function prototype of the API: `cancel_delayed_work_sync `_ .. code-block:: c #include extern bool cancel_delayed_work_sync(struct delayed_work *dwork); * Here is an example of how to use the API, .. code-block:: c cancel_delayed_work_sync(&my_work_1); .. _schedule_workqueue_9: .. tab-set:: .. tab-item:: work_on_cpu * Here is the function prototype of the API: `work_on_cpu `_ .. code-block:: c #include static inline long work_on_cpu(int cpu, long (*fn)(void *), void *arg); * Here is an example of how to use the API, .. code-block:: c work_on_cpu(0,workqueue_func_1,NULL); work_on_cpu(0,workqueue_func_2,NULL); .. _schedule_workqueue_10: .. tab-set:: .. tab-item:: work_on_cpu_safe * Here is the function prototype of the API: `work_on_cpu_safe `_ .. code-block:: c #include static inline long work_on_cpu_safe(int cpu, long (*fn)(void *), void *arg); * Here is an example of how to use the API, .. code-block:: c work_on_cpu_safe(0,workqueue_func_1,NULL); work_on_cpu_safe(0,workqueue_func_2,NULL); .. _schedule_workqueue_11: .. tab-set:: .. tab-item:: Example 1 : Scheduling the workqueue * In this example let's see how to schedule workqueue and execute it. .. _schedule_workqueue_12: .. tab-set:: .. tab-item:: List of headers * Include the follow header files(.h) to refer the API being used for the execution. .. code-block:: c #include #include #include #include #include #include .. _schedule_workqueue_13: .. tab-set:: .. tab-item:: Module macros * Add the following module macros to display information about the license, author and description about the module. .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux_usr"); MODULE_DESCRIPTION("Example of schedule_work_on"); .. _schedule_workqueue_14: .. tab-set:: .. tab-item:: Initialize work * Initialize the work which we are going to use in this example .. code-block:: c INIT_WORK(&my_work_1,workqueue_func_1); .. _schedule_workqueue_15: .. tab-set:: .. tab-item:: Workqueue Handler Function * This function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(500); } } .. _schedule_workqueue_16: .. tab-set:: .. tab-item:: Queue Start Function * This function executes during execution of queue_start, creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { INIT_WORK(&my_work_1,workqueue_func_1); schedule_work_on(0,&my_work_1); } .. _schedule_workqueue_17: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _schedule_workqueue_18: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { pr_info("Destroying workqueue\n"); cancel_work_sync(&my_work_1); } .. _schedule_workqueue_19: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _schedule_workqueue_20: .. tab-set:: .. tab-item:: Driver entry points * Add the driver entry points which will be executed once the module is inserted or removed from the kernel. .. code-block:: c module_init(queue_init); module_exit(queue_exit); .. _schedule_workqueue_21: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc1.c .. literalinclude:: schedule_work/schedule_work_on/tc1.c :language: c :linenos: .. _schedule_workqueue_22: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: schedule_work/schedule_work_on/Makefile :language: c :linenos: .. _schedule_workqueue_23: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 376 -rw-rw-r-- 1 test test 151 Aug 2 11:42 Makefile -rw-rw-r-- 1 test test 77 Aug 2 13:00 modules.order -rw-rw-r-- 1 test test 0 Aug 2 13:00 Module.symvers -rw-rw-r-- 1 test test 1604 Aug 2 11:42 tc1.c -rw-rw-r-- 1 test test 179336 Aug 2 13:00 tc1.ko -rw-rw-r-- 1 test test 77 Aug 2 13:00 tc1.mod -rw-rw-r-- 1 test test 1095 Aug 2 13:00 tc1.mod.c -rw-rw-r-- 1 test test 149280 Aug 2 13:00 tc1.mod.o -rw-rw-r-- 1 test test 31528 Aug 2 13:00 tc1.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc1.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 2501.281318] Inside queue_init function [ 2501.281378] Inside workqueue_func_1 [ 2501.786594] Inside workqueue_func_1 [ 2502.298749] Inside workqueue_func_1 [ 2502.810724] Inside workqueue_func_1 [ 2503.322661] Inside workqueue_func_1 [ 2503.834783] Inside workqueue_func_1 [ 2504.346752] Inside workqueue_func_1 [ 2504.858631] Inside workqueue_func_1 [ 2505.370734] Inside workqueue_func_1 [ 2505.882749] Inside workqueue_func_1 * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc1 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 2531.335261] Inside queue_exit function [ 2531.335267] Destroying workqueue .. _schedule_workqueue_24: .. tab-set:: .. tab-item:: Example 2 : Scheduling the workqueue * In this example let's see how to schedule workqueue and execute it. .. _schedule_workqueue_25: .. tab-set:: .. tab-item:: List of headers * Include the follow header files(.h) to refer the API being used for the execution. .. code-block:: c #include #include #include #include #include #include .. _schedule_workqueue_26: .. tab-set:: .. tab-item:: Module macros * Add the following module macros to display information about the license, author and description about the module. .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux_usr"); MODULE_DESCRIPTION("Example of schedule_delayed_work_on"); .. _schedule_workqueue_27: .. tab-set:: .. tab-item:: Initialize work * Initialize the work which we are going to use in this example .. code-block:: c INIT_WORK(&my_work_1,workqueue_func_1); .. _schedule_workqueue_28: .. tab-set:: .. tab-item:: Workqueue Handler Function * This function executes when work is queued to workqueue. .. code-block:: c void workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(500); } } .. _schedule_workqueue_29: .. tab-set:: .. tab-item:: Queue Start Function * This function executes during execution of queue_start, creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { INIT_WORK(&my_work_1,workqueue_func_1); schedule_delayed_work_on(0,&my_work_1,msecs_to_jiffies(100)); } .. _schedule_workqueue_30: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _schedule_workqueue_31: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { pr_info("Destroying workqueue\n"); cancel_delayed_work_sync(&my_work_1); } .. _schedule_workqueue_32: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _schedule_workqueue_33: .. tab-set:: .. tab-item:: Driver entry points * Add the driver entry points which will be executed once the module is inserted or removed from the kernel. .. code-block:: c module_init(queue_init); module_exit(queue_exit); .. _schedule_workqueue_34: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc2.c .. literalinclude:: schedule_work/schedule_delayed_work_on/tc2.c :language: c :linenos: .. _schedule_workqueue_35: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: schedule_work/schedule_delayed_work_on/Makefile :language: c :linenos: .. _schedule_workqueue_36: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 376 -rw-rw-r-- 1 test test 151 Aug 2 12:58 Makefile -rw-rw-r-- 1 test test 85 Aug 2 12:58 modules.order -rw-rw-r-- 1 test test 0 Aug 2 12:58 Module.symvers -rw-rw-r-- 1 test test 1659 Aug 2 11:42 tc2.c -rw-rw-r-- 1 test test 179712 Aug 2 12:58 tc2.ko -rw-rw-r-- 1 test test 85 Aug 2 12:58 tc2.mod -rw-rw-r-- 1 test test 1189 Aug 2 12:58 tc2.mod.c -rw-rw-r-- 1 test test 149424 Aug 2 12:58 tc2.mod.o -rw-rw-r-- 1 test test 31728 Aug 2 12:58 tc2.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc2.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 2358.328633] Inside queue_init function [ 2358.430764] Inside workqueue_func_1 [ 2358.938739] Inside workqueue_func_1 [ 2359.450680] Inside workqueue_func_1 [ 2359.962748] Inside workqueue_func_1 [ 2360.474731] Inside workqueue_func_1 [ 2360.986714] Inside workqueue_func_1 [ 2361.498682] Inside workqueue_func_1 [ 2362.010688] Inside workqueue_func_1 [ 2362.522739] Inside workqueue_func_1 [ 2363.034725] Inside workqueue_func_1 * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc2 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 2391.552930] Inside queue_exit function [ 2391.552940] Destroying workqueue .. _schedule_workqueue_37: .. tab-set:: .. tab-item:: Example 3 : Scheduling the workqueue * In this example let's see how to schedule workqueue and execute it. .. _schedule_workqueue_38: .. tab-set:: .. tab-item:: List of headers * Include the follow header files(.h) to refer the API being used for the execution. .. code-block:: c #include #include #include #include #include #include .. _schedule_workqueue_39: .. tab-set:: .. tab-item:: Module macros * Add the following module macros to display information about the license, author and description about the module. .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux_usr"); MODULE_DESCRIPTION("Example of work_on_cpu"); .. _schedule_workqueue_40: .. tab-set:: .. tab-item:: Workqueue Handler Function * This workqueue_func_1 function executes when work is queued to workqueue. .. code-block:: c long int workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(500); } } * This workqueue_func_2 function executes when work is queued to workqueue. .. code-block:: c long int workqueue_func_2(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_2\n"); i++; msleep(500); } } .. _schedule_workqueue_41: .. tab-set:: .. tab-item:: Queue Start Function * This function executes during execution of queue_start, creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { work_on_cpu(0,workqueue_func_1,NULL); work_on_cpu(0,workqueue_func_2,NULL); } .. _schedule_workqueue_42: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _schedule_workqueue_43: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { pr_info("Destroying workqueue\n"); } .. _schedule_workqueue_44: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _schedule_workqueue_45: .. tab-set:: .. tab-item:: Driver entry points * Add the driver entry points which will be executed once the module is inserted or removed from the kernel. .. code-block:: c module_init(queue_init); module_exit(queue_exit); .. _schedule_workqueue_46: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc3.c .. literalinclude:: schedule_work/work_on_cpu/tc3.c :language: c :linenos: .. _schedule_workqueue_47: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: schedule_work/work_on_cpu/Makefile :language: c :linenos: .. _schedule_workqueue_48: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 368 -rw-rw-r-- 1 test test 151 Aug 2 11:42 Makefile -rw-rw-r-- 1 test test 72 Aug 2 13:02 modules.order -rw-rw-r-- 1 test test 0 Aug 2 13:02 Module.symvers -rw-rw-r-- 1 test test 1826 Aug 2 11:42 tc3.c -rw-rw-r-- 1 test test 175808 Aug 2 13:02 tc3.ko -rw-rw-r-- 1 test test 72 Aug 2 13:02 tc3.mod -rw-rw-r-- 1 test test 1031 Aug 2 13:02 tc3.mod.c -rw-rw-r-- 1 test test 149144 Aug 2 13:02 tc3.mod.o -rw-rw-r-- 1 test test 28160 Aug 2 13:02 tc3.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc3.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 2586.720879] Inside queue_init function [ 2586.720925] Inside workqueue_func_1 [ 2587.226675] Inside workqueue_func_1 [ 2587.738795] Inside workqueue_func_1 [ 2588.250747] Inside workqueue_func_1 [ 2588.762771] Inside workqueue_func_1 [ 2589.274774] Inside workqueue_func_1 [ 2589.786797] Inside workqueue_func_1 [ 2590.298791] Inside workqueue_func_1 [ 2590.810741] Inside workqueue_func_1 [ 2591.322597] Inside workqueue_func_1 [ 2591.834882] Inside workqueue_func_2 [ 2592.346790] Inside workqueue_func_2 [ 2592.858774] Inside workqueue_func_2 [ 2593.370736] Inside workqueue_func_2 [ 2593.882757] Inside workqueue_func_2 [ 2594.394540] Inside workqueue_func_2 [ 2594.906671] Inside workqueue_func_2 [ 2595.418783] Inside workqueue_func_2 [ 2595.930782] Inside workqueue_func_2 [ 2596.442785] Inside workqueue_func_2 * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc3 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 2614.919189] Inside queue_exit function [ 2614.919199] Destroying workqueue .. _schedule_workqueue_49: .. tab-set:: .. tab-item:: Example 4 : Scheduling the workqueue * In this example let's see how to schedule workqueue and execute it. .. _schedule_workqueue_50: .. tab-set:: .. tab-item:: List of headers * Include the follow header files(.h) to refer the API being used for the execution. .. code-block:: c #include #include #include #include #include #include .. _schedule_workqueue_51: .. tab-set:: .. tab-item:: Module macros * Add the following module macros to display information about the license, author and description about the module. .. code-block:: c MODULE_LICENSE("GPL"); MODULE_AUTHOR("Linux_usr"); MODULE_DESCRIPTION("Example of work_on_cpu_safe"); .. _schedule_workqueue_52: .. tab-set:: .. tab-item:: Workqueue Handler Function * This workqueue_func_1 function executes when work is queued to workqueue. .. code-block:: c long int workqueue_func_1(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_1\n"); i++; msleep(500); } } * This workqueue_func_2 function executes when work is queued to workqueue. .. code-block:: c long int workqueue_func_2(struct work_struct *work) { int i = 0; while (i < 10) { pr_info("Inside workqueue_func_2\n"); i++; msleep(500); } } .. _schedule_workqueue_53: .. tab-set:: .. tab-item:: Queue Start Function * This function executes during execution of queue_start, creates workqueue, intiializes work and queues to the workqueue. .. code-block:: c void queue_start(void) { work_on_cpu_safe(0,workqueue_func_1,NULL); work_on_cpu_safe(0,workqueue_func_2,NULL); } .. _schedule_workqueue_54: .. tab-set:: .. tab-item:: Queue Init Function * This function executes when module is loaded. .. code-block:: c static int __init queue_init(void) { pr_info("Inside queue_init function\n"); queue_start(); return 0; } .. _schedule_workqueue_55: .. tab-set:: .. tab-item:: Queue Stop Function * This function executes during execution of queue_exit, waits until the completion and destroys workqueue. .. code-block:: c void queue_stop(void) { pr_info("Destroying workqueue\n"); } .. _schedule_workqueue_56: .. tab-set:: .. tab-item:: Queue Exit Function * This function executes when module is unloaded. .. code-block:: c static void __exit queue_exit(void) { pr_info("Inside queue_exit function\n"); queue_stop(); return; } .. _schedule_workqueue_57: .. tab-set:: .. tab-item:: Driver entry points * Add the driver entry points which will be executed once the module is inserted or removed from the kernel. .. code-block:: c module_init(queue_init); module_exit(queue_exit); .. _schedule_workqueue_58: .. tab-set:: .. tab-item:: See the full program below .. tab-set:: .. tab-item:: tc4.c .. literalinclude:: schedule_work/work_on_cpu_safe/tc4.c :language: c :linenos: .. _schedule_workqueue_59: .. tab-set:: .. tab-item:: Makefile .. literalinclude:: schedule_work/work_on_cpu_safe/Makefile :language: c :linenos: .. _schedule_workqueue_60: .. tab-set:: .. tab-item:: Compile and Load * Run make to load the kernel module. .. code-block:: shell $ make * Check if work_queue.ko is generated or not using ls command. .. code-block:: shell $ ls -l total 368 -rw-rw-r-- 1 test test 151 Aug 2 11:42 Makefile -rw-rw-r-- 1 test test 77 Aug 2 13:06 modules.order -rw-rw-r-- 1 test test 0 Aug 2 13:06 Module.symvers -rw-rw-r-- 1 test test 1836 Aug 2 11:42 tc4.c -rw-rw-r-- 1 test test 175832 Aug 2 13:06 tc4.ko -rw-rw-r-- 1 test test 77 Aug 2 13:06 tc4.mod -rw-rw-r-- 1 test test 1036 Aug 2 13:06 tc4.mod.c -rw-rw-r-- 1 test test 149152 Aug 2 13:06 tc4.mod.o -rw-rw-r-- 1 test test 28184 Aug 2 13:06 tc4.o * Load the module to kernel using insmod command. .. code-block:: shell $ sudo insmod ./tc4.ko * Check kernel messages to verify if the module is loaded or not. .. code-block:: shell $ dmesg [ 2840.301249] Inside queue_init function [ 2840.301327] Inside workqueue_func_1 [ 2840.826763] Inside workqueue_func_1 [ 2841.338795] Inside workqueue_func_1 [ 2841.850758] Inside workqueue_func_1 [ 2842.362763] Inside workqueue_func_1 [ 2842.874753] Inside workqueue_func_1 [ 2843.386787] Inside workqueue_func_1 [ 2843.898748] Inside workqueue_func_1 [ 2844.410762] Inside workqueue_func_1 [ 2844.922632] Inside workqueue_func_1 [ 2845.434911] Inside workqueue_func_2 [ 2845.946770] Inside workqueue_func_2 [ 2846.458715] Inside workqueue_func_2 [ 2846.970762] Inside workqueue_func_2 [ 2847.482759] Inside workqueue_func_2 [ 2847.994557] Inside workqueue_func_2 [ 2848.506718] Inside workqueue_func_2 [ 2849.018758] Inside workqueue_func_2 [ 2849.530761] Inside workqueue_func_2 [ 2850.042761] Inside workqueue_func_2 * Unload the module using rmmod command. .. code-block:: shell $ sudo rmmod tc4 * Check kernel messages to see if the module is unloaded or not. .. code-block:: shell $ dmesg [ 2866.416509] Inside queue_exit function [ 2866.416516] Destroying workqueue