mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-03-11 12:56:21 +03:00
Currently libspl is a static archive that is linked into multiple shared objects, which then re-export its symbols. We intend to fix this soon. For the moment though, most programs shipped with OpenZFS depend on two or more of these shared objects, and see the same symbols twice. For functions this is not a problem, as they do not have any mutable state and so the linker can simply select the first one and use that for all. For global data objects however, each shared object will have direct (non-relocatable) references to its own instance of the symbol, such that changes on one will not necessarily be seen by the other. While this shouldn't be a problem in practice as these reexported interfaces are not supposed to be used, they are technically undefined behaviour in C (C17 6.9.2) and are reported by ASAN as a violation of C++'s "One Definition Rule". To fix this, we hide these globals inside their compilation units, and add access functions and macros as appropriate to preserve the existing API (though not ABI). Sponsored-by: https://despairlabs.com/sponsor/ Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Signed-off-by: Rob Norris <robn@despairlabs.com> Closes #17861
120 lines
3.8 KiB
C
120 lines
3.8 KiB
C
// SPDX-License-Identifier: CDDL-1.0
|
|
/*
|
|
* CDDL HEADER START
|
|
*
|
|
* The contents of this file are subject to the terms of the
|
|
* Common Development and Distribution License (the "License").
|
|
* You may not use this file except in compliance with the License.
|
|
*
|
|
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
* or https://opensource.org/licenses/CDDL-1.0.
|
|
* See the License for the specific language governing permissions
|
|
* and limitations under the License.
|
|
*
|
|
* When distributing Covered Code, include this CDDL HEADER in each
|
|
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
* If applicable, add the following below this CDDL HEADER, with the
|
|
* fields enclosed by brackets "[]" replaced with your own identifying
|
|
* information: Portions Copyright [yyyy] [name of copyright owner]
|
|
*
|
|
* CDDL HEADER END
|
|
*/
|
|
/*
|
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
|
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
|
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
|
*/
|
|
|
|
#ifndef _SYS_TASKQ_H
|
|
#define _SYS_TASKQ_H
|
|
|
|
#include <pthread.h>
|
|
#include <stdint.h>
|
|
#include <sys/mutex.h>
|
|
#include <sys/rwlock.h>
|
|
#include <sys/condvar.h>
|
|
|
|
/*
|
|
* Task queues
|
|
*/
|
|
|
|
#define TASKQ_NAMELEN 31
|
|
|
|
typedef uintptr_t taskqid_t;
|
|
typedef void (task_func_t)(void *);
|
|
|
|
typedef struct taskq_ent {
|
|
struct taskq_ent *tqent_next;
|
|
struct taskq_ent *tqent_prev;
|
|
task_func_t *tqent_func;
|
|
void *tqent_arg;
|
|
uintptr_t tqent_flags;
|
|
} taskq_ent_t;
|
|
|
|
typedef struct taskq {
|
|
char tq_name[TASKQ_NAMELEN + 1];
|
|
kmutex_t tq_lock;
|
|
krwlock_t tq_threadlock;
|
|
kcondvar_t tq_dispatch_cv;
|
|
kcondvar_t tq_wait_cv;
|
|
kthread_t **tq_threadlist;
|
|
int tq_flags;
|
|
int tq_active;
|
|
int tq_nthreads;
|
|
int tq_nalloc;
|
|
int tq_minalloc;
|
|
int tq_maxalloc;
|
|
kcondvar_t tq_maxalloc_cv;
|
|
int tq_maxalloc_wait;
|
|
taskq_ent_t *tq_freelist;
|
|
taskq_ent_t tq_task;
|
|
} taskq_t;
|
|
|
|
#define TQENT_FLAG_PREALLOC 0x1 /* taskq_dispatch_ent used */
|
|
|
|
#define TASKQ_PREPOPULATE 0x0001
|
|
#define TASKQ_CPR_SAFE 0x0002 /* Use CPR safe protocol */
|
|
#define TASKQ_DYNAMIC 0x0004 /* Use dynamic thread scheduling */
|
|
#define TASKQ_THREADS_CPU_PCT 0x0008 /* Scale # threads by # cpus */
|
|
#define TASKQ_DC_BATCH 0x0010 /* Mark threads as batch */
|
|
|
|
#define TQ_SLEEP KM_SLEEP /* Can block for memory */
|
|
#define TQ_NOSLEEP KM_NOSLEEP /* cannot block for memory; may fail */
|
|
#define TQ_NOQUEUE 0x02 /* Do not enqueue if can't dispatch */
|
|
#define TQ_FRONT 0x08 /* Queue in front */
|
|
|
|
#define TASKQID_INVALID ((taskqid_t)0)
|
|
|
|
extern taskq_t *_system_taskq(void);
|
|
extern taskq_t *_system_delay_taskq(void);
|
|
|
|
#define system_taskq _system_taskq()
|
|
#define system_delay_taskq _system_delay_taskq()
|
|
|
|
extern taskq_t *taskq_create(const char *, int, pri_t, int, int, uint_t);
|
|
extern taskq_t *taskq_create_synced(const char *, int, pri_t, int, int, uint_t,
|
|
kthread_t ***);
|
|
#define taskq_create_proc(a, b, c, d, e, p, f) \
|
|
(taskq_create(a, b, c, d, e, f))
|
|
#define taskq_create_sysdc(a, b, d, e, p, dc, f) \
|
|
((void) sizeof (dc), taskq_create(a, b, maxclsyspri, d, e, f))
|
|
extern taskqid_t taskq_dispatch(taskq_t *, task_func_t, void *, uint_t);
|
|
extern taskqid_t taskq_dispatch_delay(taskq_t *, task_func_t, void *, uint_t,
|
|
clock_t);
|
|
extern void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t,
|
|
taskq_ent_t *);
|
|
extern int taskq_empty_ent(taskq_ent_t *);
|
|
extern void taskq_init_ent(taskq_ent_t *);
|
|
extern void taskq_destroy(taskq_t *);
|
|
extern void taskq_wait(taskq_t *);
|
|
extern void taskq_wait_id(taskq_t *, taskqid_t);
|
|
extern void taskq_wait_outstanding(taskq_t *, taskqid_t);
|
|
extern int taskq_member(taskq_t *, kthread_t *);
|
|
extern taskq_t *taskq_of_curthread(void);
|
|
extern int taskq_cancel_id(taskq_t *, taskqid_t);
|
|
extern void system_taskq_init(void);
|
|
extern void system_taskq_fini(void);
|
|
|
|
#endif /* _SYS_TASKQ_H */
|