Print this page
9017 Introduce taskq_empty()
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Yuri Pankov <yuripv@yuripv.net>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/taskq.c
          +++ new/usr/src/uts/common/os/taskq.c
↓ open down ↓ 18 lines elided ↑ open up ↑
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  /*
  27   27   * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  28   28   * Copyright (c) 2017 by Delphix. All rights reserved.
       29 + * Copyright 2018, Joyent, Inc.
  29   30   */
  30   31  
  31   32  /*
  32   33   * Kernel task queues: general-purpose asynchronous task scheduling.
  33   34   *
  34   35   * A common problem in kernel programming is the need to schedule tasks
  35   36   * to be performed later, by another thread. There are several reasons
  36   37   * you may want or need to do this:
  37   38   *
  38   39   * (1) The task isn't time-critical, but your current code path is.
↓ open down ↓ 154 lines elided ↑ open up ↑
 193  194   *
 194  195   *      This is a light-weight form of taskq_dispatch(), that uses a
 195  196   *      preallocated taskq_ent_t structure for scheduling.  As a
 196  197   *      result, it does not perform allocations and cannot ever fail.
 197  198   *      Note especially that it cannot be used with TASKQ_DYNAMIC
 198  199   *      taskqs.  The memory for the tqent must not be modified or used
 199  200   *      until the function (func) is called.  (However, func itself
 200  201   *      may safely modify or free this memory, once it is called.)
 201  202   *      Note that the taskq framework will NOT free this memory.
 202  203   *
      204 + * boolean_t taskq_empty(tq)
      205 + *
      206 + *      Queries if there are tasks pending on the queue.
      207 + *
 203  208   * void taskq_wait(tq):
 204  209   *
 205  210   *      Waits for all previously scheduled tasks to complete.
 206  211   *
 207  212   *      NOTE: It does not stop any new task dispatches.
 208  213   *            Do NOT call taskq_wait() from a task: it will cause deadlock.
 209  214   *
 210  215   * void taskq_suspend(tq)
 211  216   *
 212  217   *      Suspend all task execution. Tasks already scheduled for a dynamic task
↓ open down ↓ 1099 lines elided ↑ open up ↑
1312 1317          mutex_enter(&tq->tq_lock);
1313 1318  
1314 1319          if (flags & TQ_FRONT) {
1315 1320                  TQ_ENQUEUE_FRONT(tq, tqe, func, arg);
1316 1321          } else {
1317 1322                  TQ_ENQUEUE(tq, tqe, func, arg);
1318 1323          }
1319 1324          mutex_exit(&tq->tq_lock);
1320 1325  }
1321 1326  
     1327 +/*
     1328 + * Allow our caller to ask if there are tasks pending on the queue.
     1329 + */
     1330 +boolean_t
     1331 +taskq_empty(taskq_t *tq)
     1332 +{
     1333 +        boolean_t rv;
     1334 +
     1335 +        ASSERT3P(tq, !=, curthread->t_taskq);
     1336 +        mutex_enter(&tq->tq_lock);
     1337 +        rv = (tq->tq_task.tqent_next == &tq->tq_task) && (tq->tq_active == 0);
     1338 +        mutex_exit(&tq->tq_lock);
     1339 +
     1340 +        return (rv);
     1341 +}
     1342 +
1322 1343  /*
1323 1344   * Wait for all pending tasks to complete.
1324 1345   * Calling taskq_wait from a task will cause deadlock.
1325 1346   */
1326 1347  void
1327 1348  taskq_wait(taskq_t *tq)
1328 1349  {
1329 1350          ASSERT(tq != curthread->t_taskq);
1330 1351  
1331 1352          mutex_enter(&tq->tq_lock);
↓ open down ↓ 984 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX