Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/external/libetonyek/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 134 B image not shown  

Quelle  vhost_task.c   Sprache: unbekannt

 
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2021 Oracle Corporation
 */

#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/sched/task.h>
#include <linux/sched/vhost_task.h>
#include <linux/sched/signal.h>

enum vhost_task_flags {
 VHOST_TASK_FLAGS_STOP,
 VHOST_TASK_FLAGS_KILLED,
};

struct vhost_task {
 bool (*fn)(void *data);
 void (*handle_sigkill)(void *data);
 void *data;
 struct completion exited;
 unsigned long flags;
 struct task_struct *task;
 /* serialize SIGKILL and vhost_task_stop calls */
 struct mutex exit_mutex;
};

static int vhost_task_fn(void *data)
{
 struct vhost_task *vtsk = data;

 for (;;) {
  bool did_work;

  if (signal_pending(current)) {
   struct ksignal ksig;

   if (get_signal(&ksig))
    break;
  }

  /* mb paired w/ vhost_task_stop */
  set_current_state(TASK_INTERRUPTIBLE);

  if (test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags)) {
   __set_current_state(TASK_RUNNING);
   break;
  }

  did_work = vtsk->fn(vtsk->data);
  if (!did_work)
   schedule();
 }

 mutex_lock(&vtsk->exit_mutex);
 /*
 * If a vhost_task_stop and SIGKILL race, we can ignore the SIGKILL.
 * When the vhost layer has called vhost_task_stop it's already stopped
 * new work and flushed.
 */

 if (!test_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags)) {
  set_bit(VHOST_TASK_FLAGS_KILLED, &vtsk->flags);
  vtsk->handle_sigkill(vtsk->data);
 }
 mutex_unlock(&vtsk->exit_mutex);
 complete(&vtsk->exited);

 do_exit(0);
}

/**
 * vhost_task_wake - wakeup the vhost_task
 * @vtsk: vhost_task to wake
 *
 * wake up the vhost_task worker thread
 */

void vhost_task_wake(struct vhost_task *vtsk)
{
 wake_up_process(vtsk->task);
}
EXPORT_SYMBOL_GPL(vhost_task_wake);

/**
 * vhost_task_stop - stop a vhost_task
 * @vtsk: vhost_task to stop
 *
 * vhost_task_fn ensures the worker thread exits after
 * VHOST_TASK_FLAGS_STOP becomes true.
 */

void vhost_task_stop(struct vhost_task *vtsk)
{
 mutex_lock(&vtsk->exit_mutex);
 if (!test_bit(VHOST_TASK_FLAGS_KILLED, &vtsk->flags)) {
  set_bit(VHOST_TASK_FLAGS_STOP, &vtsk->flags);
  vhost_task_wake(vtsk);
 }
 mutex_unlock(&vtsk->exit_mutex);

 /*
 * Make sure vhost_task_fn is no longer accessing the vhost_task before
 * freeing it below.
 */

 wait_for_completion(&vtsk->exited);
 put_task_struct(vtsk->task);
 kfree(vtsk);
}
EXPORT_SYMBOL_GPL(vhost_task_stop);

/**
 * vhost_task_create - create a copy of a task to be used by the kernel
 * @fn: vhost worker function
 * @handle_sigkill: vhost function to handle when we are killed
 * @arg: data to be passed to fn and handled_kill
 * @name: the thread's name
 *
 * This returns a specialized task for use by the vhost layer or ERR_PTR() on
 * failure. The returned task is inactive, and the caller must fire it up
 * through vhost_task_start().
 */

struct vhost_task *vhost_task_create(bool (*fn)(void *),
         void (*handle_sigkill)(void *), void *arg,
         const char *name)
{
 struct kernel_clone_args args = {
  .flags  = CLONE_FS | CLONE_UNTRACED | CLONE_VM |
      CLONE_THREAD | CLONE_SIGHAND,
  .exit_signal = 0,
  .fn  = vhost_task_fn,
  .name  = name,
  .user_worker = 1,
  .no_files = 1,
 };
 struct vhost_task *vtsk;
 struct task_struct *tsk;

 vtsk = kzalloc(sizeof(*vtsk), GFP_KERNEL);
 if (!vtsk)
  return ERR_PTR(-ENOMEM);
 init_completion(&vtsk->exited);
 mutex_init(&vtsk->exit_mutex);
 vtsk->data = arg;
 vtsk->fn = fn;
 vtsk->handle_sigkill = handle_sigkill;

 args.fn_arg = vtsk;

 tsk = copy_process(NULL, 0, NUMA_NO_NODE, &args);
 if (IS_ERR(tsk)) {
  kfree(vtsk);
  return ERR_CAST(tsk);
 }

 vtsk->task = get_task_struct(tsk);
 return vtsk;
}
EXPORT_SYMBOL_GPL(vhost_task_create);

/**
 * vhost_task_start - start a vhost_task created with vhost_task_create
 * @vtsk: vhost_task to wake up
 */

void vhost_task_start(struct vhost_task *vtsk)
{
 wake_up_new_task(vtsk->task);
}
EXPORT_SYMBOL_GPL(vhost_task_start);

96%


[ Dauer der Verarbeitung: 0.37 Sekunden  (vorverarbeitet)  ]