Index: head/share/man/man9/pci_iov_schema.9 =================================================================== --- head/share/man/man9/pci_iov_schema.9 (revision 284556) +++ head/share/man/man9/pci_iov_schema.9 (revision 284557) @@ -1,265 +1,265 @@ .\" .\" Copyright (c) 2014 Sandvine Inc. .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd May 28, 2015 .Dt pci_iov_schema 9 .Os .Sh NAME .Nm pci_iov_schema , .Nm pci_iov_schema_alloc_node , .Nm pci_iov_schema_add_bool , .Nm pci_iov_schema_add_string , .Nm pci_iov_schema_add_uint8 , .Nm pci_iov_schema_add_uint16 , .Nm pci_iov_schema_add_uint32 , .Nm pci_iov_schema_add_uint64 , .Nm pci_iov_schema_add_unicast_mac .Nd PCI SR-IOV config schema interface .Sh SYNOPSIS .In machine/stdarg.h .In sys/nv.h .In sys/iov_schema.h .Ft nvlist_t * .Fn pci_iov_schema_alloc_node "void" .Ft void .Fn pci_iov_schema_add_bool "nvlist_t *schema" "const char *name" \ "uint32_t flags" "int defaultVal" .Ft void .Fn pci_iov_schema_add_string "nvlist_t *schema" "const char *name" \ "uint32_t flags" "const char *defaultVal" .Ft void .Fn pci_iov_schema_add_uint8 "nvlist_t *schema" "const char *name" \ "uint32_t flags" "uint8_t defaultVal" .Ft void .Fn pci_iov_schema_add_uint16 "nvlist_t *schema" "const char *name" \ "uint32_t flags" "uint16_t defaultVal" .Ft void .Fn pci_iov_schema_add_uint32 "nvlist_t *schema" "const char *name" \ "uint32_t flags" "uint32_t defaultVal" .Ft void .Fn pci_iov_schema_add_uint64 "nvlist_t *schema" "const char *name" \ "uint32_t flags" "uint64_t defaultVal" .Ft void .Fn pci_iov_schema_add_unicast_mac "nvlist_t *schema" "const char *name" \ "uint32_t flags" "const uint8_t *defaultVal" .Sh DESCRIPTION -The PCI Single-Root I/O Virtualization +The PCI Single-Root I/O Virtualization .Pq SR-IOV configuration schema is a data structure that describes the device-specific configuration parameters that a PF driver will accept when SR-IOV is enabled on the PF device. Each PF driver defines two schema instances: the PF schema and the VF schema. The PF schema describes configuration that applies to the PF device as a whole. The VF schema describes configuration that applies to an individual VF device. Different VF devices may have different configuration applied to them, as long as the configuration for each VF conforms to the VF schema. .Pp A PF driver builds a configuration schema by first allocating a schema node and then adding configuration parameter specifications to the schema. The configuration parameter specification consists of a name and a value type. .Pp Configuration parameter names are case-insensitive. It is an error to specify two or more configuration parameters with the same name. It is also an error to specific a configuration parameter that uses the same name as a configuration parameter used by the SR-IOV infrastructure. See .Xr iovctl.conf 5 for documentation of all configuration parameters used by the SR-IOV infrastructure. .Pp The parameter type constrains the possible values that the configuration parameter may take. .Pp A configuration parameter may be specified as a required parameter by setting the .Dv IOV_SCHEMA_REQUIRED flag in the .Pa flags argument. Required parameters must be specified by the user when SR-IOV is enabled. If the user does not specify a required parameter, the SR-IOV infrastructure will abort the request to enable SR-IOV and return an error to the user. .Pp Alternatively, a configuration parameter may be given a default value by setting the .Dv IOV_SCHEMA_HASDEFAULT flag in the .Pa flags argument. If a configuration parameter has a default value but the user has not specified a value for that parameter, then the SR-IOV infrastructure will apply .Pa defaultVal for that parameter in the configuration before passing it to the PF driver. It is an error for the value of the .Pa defaultVal parameter to not conform to the restrictions of the specified type. If this flag is not specified then the .Pa defaultVal argument is ignored. This flag is not compatible with the .Dv IOV_SCHEMA_REQUIRED flag; it is an error to specify both on the same parameter. .Pp The SR-IOV infrastructure guarantees that all configuration parameters that are either specified as required or given a default value will be present in the configuration passed to the PF driver. Configuration parameters that are neither specified as required nor given a default value are optional and may or may not be present in the configuration passed to the PF driver. .Pp It is highly recommended that a PF driver reserve the use of optional parameters for configuration that is truly optional. For example, a Network Interface PF device might have the option to encapsulate all traffic to and from a VF device in a vlan tag. The PF driver could expose that option as a "vlan" parameter accepting an integer argument specifying the vlan tag. In this case, it would be appropriate to set the "vlan" parameter as an optional parameter as it would be legitimate for a VF to be configured to have no vlan tagging enabled at all. .Pp Alternatively, if the PF device had an boolean option that controlled whether the VF was allowed to change its MAC address, it would not be appropriate to set this parameter as optional. The PF driver must either allow the MAC to change or not, so it would be more appropriate for the PF driver to document the default behaviour by specifying -a default value in the schema +a default value in the schema .Po or potentially force the user to make the choice by setting the parameter -to be required +to be required .Pc . .Pp Configuration parameters that have security implications must default to the most secure configuration possible. .Pp All device-specific configuration parameters must be documented in the manual page for the PF driver, or in a separate manual page that is cross-referenced from the main driver manual page. .Pp It is not necessary for a PF driver to check for failure from any of these functions. If an error occurs, it is flagged in the schema. The .Xr pci_iov_attach 9 function checks for this error and will fail to initialize SR-IOV on the PF device if an error is set in the schema. If this occurs, it is recommended that the PF driver still succeed in attaching and run with SR-IOV disabled on the device. .Pp The .Fn pci_iov_schema_alloc_node function is used to allocate an empty configuration schema. It is not necessary to check for failure from this function. The SR-IOV infrastructure will gracefully handle failure to allocate a schema and will simply not enable SR-IOV on the PF device. .Pp The .Fn pci_iov_schema_add_bool function is used to specify a configuration parameter in the given schema with the name .Pa name and having a boolean type. Boolean values can only take the value true or false (1 or 0, respectively). .Pp The .Fn pci_iov_schema_add_string function is used to specify a configuration parameter in the given schema with the name .Pa name and having a string type. String values are standard C strings. .Pp The .Fn pci_iov_schema_add_uint8 function is used to specify a configuration parameter in the given schema with the name .Pa name and having a .Vt uint8_t type. Values of type .Vt uint8_t are unsigned integers in the range 0 to 255, inclusive. .Pp The .Fn pci_iov_schema_add_uint16 function is used to specify a configuration parameter in the given schema with the name .Pa name and having a .Vt uint16_t type. Values of type .Vt uint16_t are unsigned integers in the range 0 to 65535, inclusive. .Pp The .Fn pci_iov_schema_add_uint32 function is used to specify a configuration parameter in the given schema with the name .Pa name and having a .Vt uint32_t type. Values of type .Vt uint32_t -are unsigned integers in the range 0 to +are unsigned integers in the range 0 to .Po 2**32 - 1 Pc , inclusive. .Pp The .Fn pci_iov_schema_add_uint64 function is used to specify a configuration parameter in the given schema with the name .Pa name and having a .Vt uint64_t type. Values of type .Vt uint64_t -are unsigned integers in the range 0 to +are unsigned integers in the range 0 to .Po 2**64 - 1 Pc , inclusive. .Pp The .Fn pci_iov_schema_add_unicast_mac function is used to specify a configuration parameter in the given schema with the name .Pa name and having a unicast-mac type. Values of type unicast-mac are binary values exactly 6 bytes long. The MAC address is guaranteed to not be a multicast or broadcast address. .Sh RETURN VALUES The .Fn pci_iov_schema_alloc_node function returns a pointer to the allocated schema, or NULL if a failure occurs. .Sh SEE ALSO .Xr pci 9 , .Xr PCI_IOV_ADD_VF 9 , .Xr PCI_IOV_INIT 9 .Sh AUTHORS This manual page was written by .An Ryan Stone Aq rstone@FreeBSD.org . Index: head/share/man/man9/sbuf.9 =================================================================== --- head/share/man/man9/sbuf.9 (revision 284556) +++ head/share/man/man9/sbuf.9 (revision 284557) @@ -1,606 +1,606 @@ .\"- .\" Copyright (c) 2000 Poul-Henning Kamp and Dag-Erling Coïdan Smørgrav .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd March 14, 2015 .Dt SBUF 9 .Os .Sh NAME .Nm sbuf , .Nm sbuf_new , .Nm sbuf_new_auto , .Nm sbuf_new_for_sysctl , .Nm sbuf_clear , .Nm sbuf_get_flags , .Nm sbuf_set_flags , .Nm sbuf_clear_flags , .Nm sbuf_setpos , .Nm sbuf_bcat , .Nm sbuf_bcopyin , .Nm sbuf_bcpy , .Nm sbuf_cat , .Nm sbuf_copyin , .Nm sbuf_cpy , .Nm sbuf_printf , .Nm sbuf_vprintf , .Nm sbuf_putc , .Nm sbuf_set_drain , .Nm sbuf_trim , .Nm sbuf_error , .Nm sbuf_finish , .Nm sbuf_data , .Nm sbuf_len , .Nm sbuf_done , .Nm sbuf_delete , .Nm sbuf_start_section , .Nm sbuf_end_section , .Nm sbuf_hexdump .Nd safe string composition .Sh SYNOPSIS .In sys/types.h .In sys/sbuf.h .Ft typedef\ int ( sbuf_drain_func ) ( void\ *arg, const\ char\ *data, int\ len ) ; .Pp .Ft struct sbuf * .Fn sbuf_new "struct sbuf *s" "char *buf" "int length" "int flags" .Ft struct sbuf * .Fn sbuf_new_auto .Ft void .Fn sbuf_clear "struct sbuf *s" .Ft int .Fn sbuf_get_flags "struct sbuf *s" .Ft void .Fn sbuf_set_flags "struct sbuf *s" "int flags" .Ft void .Fn sbuf_clear_flags "struct sbuf *s" "int flags" .Ft int .Fn sbuf_setpos "struct sbuf *s" "int pos" .Ft int .Fn sbuf_bcat "struct sbuf *s" "const void *buf" "size_t len" .Ft int .Fn sbuf_bcopyin "struct sbuf *s" "const void *uaddr" "size_t len" .Ft int .Fn sbuf_bcpy "struct sbuf *s" "const void *buf" "size_t len" .Ft int .Fn sbuf_cat "struct sbuf *s" "const char *str" .Ft int .Fn sbuf_copyin "struct sbuf *s" "const void *uaddr" "size_t len" .Ft int .Fn sbuf_cpy "struct sbuf *s" "const char *str" .Ft int .Fn sbuf_printf "struct sbuf *s" "const char *fmt" "..." .Ft int .Fn sbuf_vprintf "struct sbuf *s" "const char *fmt" "va_list ap" .Ft int .Fn sbuf_putc "struct sbuf *s" "int c" .Ft void .Fn sbuf_set_drain "struct sbuf *s" "sbuf_drain_func *func" "void *arg" .Ft int .Fn sbuf_trim "struct sbuf *s" .Ft int .Fn sbuf_error "struct sbuf *s" .Ft int .Fn sbuf_finish "struct sbuf *s" .Ft char * .Fn sbuf_data "struct sbuf *s" .Ft ssize_t .Fn sbuf_len "struct sbuf *s" .Ft int .Fn sbuf_done "struct sbuf *s" .Ft void .Fn sbuf_delete "struct sbuf *s" .Ft void .Fn sbuf_start_section "struct sbuf *s" "ssize_t *old_lenp" .Ft ssize_t .Fn sbuf_end_section "struct sbuf *s" "ssize_t old_len" "size_t pad" "int c" .Ft void -.Fo sbuf_hexdump +.Fo sbuf_hexdump .Fa "struct sbuf *sb" .Fa "void *ptr" .Fa "int length" .Fa "const char *hdr" .Fa "int flags" .Fc .In sys/sysctl.h .Ft struct sbuf * .Fn sbuf_new_for_sysctl "struct sbuf *s" "char *buf" "int length" "struct sysctl_req *req" .Sh DESCRIPTION The .Nm family of functions allows one to safely allocate, compose and release strings in kernel or user space. .Pp Instead of arrays of characters, these functions operate on structures called .Fa sbufs , defined in .In sys/sbuf.h . .Pp Any errors encountered during the allocation or composition of the string will be latched in the data structure, making a single error test at the end of the composition sufficient to determine success or failure of the entire process. .Pp The .Fn sbuf_new function initializes the .Fa sbuf pointed to by its first argument. If that pointer is .Dv NULL , .Fn sbuf_new allocates a .Vt struct sbuf using .Xr malloc 9 . The .Fa buf argument is a pointer to a buffer in which to store the actual string; if it is .Dv NULL , .Fn sbuf_new will allocate one using .Xr malloc 9 . The .Fa length is the initial size of the storage buffer. The fourth argument, .Fa flags , may be comprised of the following flags: .Bl -tag -width ".Dv SBUF_AUTOEXTEND" .It Dv SBUF_FIXEDLEN The storage buffer is fixed at its initial size. Attempting to extend the sbuf beyond this size results in an overflow condition. .It Dv SBUF_AUTOEXTEND This indicates that the storage buffer may be extended as necessary, so long as resources allow, to hold additional data. .It Dv SBUF_INCLUDENUL This causes the final nulterm byte to be counted in the length of the data. .El .Pp Note that if .Fa buf is not .Dv NULL , it must point to an array of at least .Fa length characters. The result of accessing that array directly while it is in use by the sbuf is undefined. .Pp The .Fn sbuf_new_auto function is a shortcut for creating a completely dynamic .Nm . It is the equivalent of calling .Fn sbuf_new with values .Dv NULL , .Dv NULL , .Dv 0 , and .Dv SBUF_AUTOEXTEND . .Pp The .Fn sbuf_new_for_sysctl function will set up an sbuf with a drain function to use .Fn SYSCTL_OUT when the internal buffer fills. Note that if the various functions which append to an sbuf are used while a non-sleepable lock is held, the user buffer should be wired using .Fn sysctl_wire_old_buffer . .Pp The .Fn sbuf_delete function clears the .Fa sbuf and frees any memory allocated for it. There must be a call to .Fn sbuf_delete for every call to .Fn sbuf_new . Any attempt to access the sbuf after it has been deleted will fail. .Pp The .Fn sbuf_clear function invalidates the contents of the .Fa sbuf and resets its position to zero. .Pp The .Fn sbuf_get_flags function returns the current user flags. The .Fn sbuf_set_flags and .Fn sbuf_get_flags functions set or clear one or more user flags, respectively. The user flags are described under the .Fn sbuf_new function. .Pp The .Fn sbuf_setpos function sets the .Fa sbuf Ns 's end position to .Fa pos , which is a value between zero and one less than the size of the storage buffer. This effectively truncates the sbuf at the new position. .Pp The .Fn sbuf_bcat function appends the first .Fa len bytes from the buffer .Fa buf to the .Fa sbuf . .Pp The .Fn sbuf_bcopyin function copies .Fa len bytes from the specified userland address into the .Fa sbuf . .Pp The .Fn sbuf_bcpy function replaces the contents of the .Fa sbuf with the first .Fa len bytes from the buffer .Fa buf . .Pp The .Fn sbuf_cat function appends the NUL-terminated string .Fa str to the .Fa sbuf at the current position. .Pp The .Fn sbuf_set_drain function sets a drain function .Fa func for the .Fa sbuf , and records a pointer .Fa arg to be passed to the drain on callback. The drain function cannot be changed while .Fa sbuf_len is non-zero. .Pp The registered drain function .Vt sbuf_drain_func will be called with the argument .Fa arg provided to .Fn sbuf_set_drain , a pointer .Fa data to a byte string that is the contents of the sbuf, and the length .Fa len of the data. If the drain function exists, it will be called when the sbuf internal buffer is full, or on behalf of .Fn sbuf_finish . The drain function may drain some or all of the data, but must drain at least 1 byte. The return value from the drain function, if positive, indicates how many bytes were drained. If negative, the return value indicates the negative error code which will be returned from this or a later call to .Fn sbuf_finish . The returned drained length cannot be zero. To do unbuffered draining, initialize the sbuf with a two-byte buffer. The drain will be called for every byte added to the sbuf. The .Fn sbuf_bcopyin , .Fn sbuf_copyin , .Fn sbuf_trim , and .Fn sbuf_data functions cannot be used on an sbuf with a drain. .Pp The .Fn sbuf_copyin function copies a NUL-terminated string from the specified userland address into the .Fa sbuf . If the .Fa len argument is non-zero, no more than .Fa len characters (not counting the terminating NUL) are copied; otherwise the entire string, or as much of it as can fit in the .Fa sbuf , is copied. .Pp The .Fn sbuf_cpy function replaces the contents of the .Fa sbuf with those of the NUL-terminated string .Fa str . This is equivalent to calling .Fn sbuf_cat with a fresh .Fa sbuf or one which position has been reset to zero with .Fn sbuf_clear or .Fn sbuf_setpos . .Pp The .Fn sbuf_printf function formats its arguments according to the format string pointed to by .Fa fmt and appends the resulting string to the .Fa sbuf at the current position. .Pp The .Fn sbuf_vprintf function behaves the same as .Fn sbuf_printf except that the arguments are obtained from the variable-length argument list .Fa ap . .Pp The .Fn sbuf_putc function appends the character .Fa c to the .Fa sbuf at the current position. .Pp The .Fn sbuf_trim function removes trailing whitespace from the .Fa sbuf . .Pp The .Fn sbuf_error function returns any error value that the .Fa sbuf may have accumulated, either from the drain function, or ENOMEM if the .Fa sbuf overflowed. This function is generally not needed and instead the error code from .Fn sbuf_finish is the preferred way to discover whether an sbuf had an error. .Pp The .Fn sbuf_finish function will call the attached drain function if one exists until all the data in the .Fa sbuf is flushed. If there is no attached drain, .Fn sbuf_finish NUL-terminates the .Fa sbuf . In either case it marks the .Fa sbuf as finished, which means that it may no longer be modified using .Fn sbuf_setpos , .Fn sbuf_cat , .Fn sbuf_cpy , .Fn sbuf_printf or .Fn sbuf_putc , until .Fn sbuf_clear is used to reset the sbuf. .Pp The .Fn sbuf_data function returns the actual string; .Fn sbuf_data only works on a finished .Fa sbuf . The .Fn sbuf_len function returns the length of the string. For an .Fa sbuf with an attached drain, .Fn sbuf_len returns the length of the un-drained data. .Fn sbuf_done returns non-zero if the .Fa sbuf is finished. .Pp The .Fn sbuf_start_section and .Fn sbuf_end_section functions may be used for automatic section alignment. The arguments .Fa pad and .Fa c specify the padding size and a character used for padding. The arguments .Fa old_lenp and .Fa old_len are to save and restore the current section length when nested sections are used. For the top level section .Dv NULL and \-1 can be specified for .Fa old_lenp and .Fa old_len respectively. .Pp The .Fn sbuf_hexdump function prints an array of bytes to the supplied sbuf, along with an ASCII representation of the bytes if possible. See the .Xr hexdump 3 man page for more details on the interface. .Sh NOTES If an operation caused an .Fa sbuf to overflow, most subsequent operations on it will fail until the .Fa sbuf is finished using .Fn sbuf_finish or reset using .Fn sbuf_clear , or its position is reset to a value between 0 and one less than the size of its storage buffer using .Fn sbuf_setpos , or it is reinitialized to a sufficiently short string using .Fn sbuf_cpy . .Pp Drains in user-space will not always function as indicated. While the drain function will be called immediately on overflow from the .Fa sbuf_putc , .Fa sbuf_bcat , .Fa sbuf_cat functions, .Fa sbuf_printf and .Fa sbuf_vprintf currently have no way to determine whether there will be an overflow until after it occurs, and cannot do a partial expansion of the format string. Thus when using libsbuf the buffer may be extended to allow completion of a single printf call, even though a drain is attached. .Sh RETURN VALUES The .Fn sbuf_new function returns .Dv NULL if it failed to allocate a storage buffer, and a pointer to the new .Fa sbuf otherwise. .Pp The .Fn sbuf_setpos function returns \-1 if .Fa pos was invalid, and zero otherwise. .Pp The .Fn sbuf_cat , .Fn sbuf_cpy , .Fn sbuf_printf , .Fn sbuf_putc , and .Fn sbuf_trim functions all return \-1 if the buffer overflowed, and zero otherwise. .Pp The .Fn sbuf_error function returns a non-zero value if the buffer has an overflow or drain error, and zero otherwise. .Pp The .Fn sbuf_len function returns \-1 if the buffer overflowed. .Pp The .Fn sbuf_copyin function returns \-1 if copying string from userland failed, and number of bytes copied otherwise. .Pp The .Fn sbuf_end_section function returns the section length or \-1 if the buffer has an error. .Pp The .Fn sbuf_finish 9 function (the kernel version) returns ENOMEM if the sbuf overflowed before being finished, or returns the error code from the drain if one is attached. .Pp The .Fn sbuf_finish 3 function (the userland version) will return zero for success and \-1 and set errno on error. .Sh EXAMPLES .Bd -literal -compact #include struct sbuf *sb; sb = sbuf_new_auto(); sbuf_cat(sb, "Customers found:\en"); TAILQ_FOREACH(foo, &foolist, list) { sbuf_printf(sb, " %4d %s\en", foo->index, foo->name); sbuf_printf(sb, " Address: %s\en", foo->address); sbuf_printf(sb, " Zip: %s\en", foo->zipcode); } if (sbuf_finish(sb) != 0) /* Check for any and all errors */ err(1, "Could not generate message"); transmit_msg(sbuf_data(sb), sbuf_len(sb)); sbuf_delete(sb); .Ed .Sh SEE ALSO .Xr hexdump 3 , .Xr printf 3 , .Xr strcat 3 , .Xr strcpy 3 , .Xr copyin 9 , .Xr copyinstr 9 , .Xr printf 9 .Sh HISTORY The .Nm family of functions first appeared in .Fx 4.4 . .Sh AUTHORS .An -nosplit The .Nm family of functions was designed by .An Poul-Henning Kamp Aq Mt phk@FreeBSD.org and implemented by .An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org . Additional improvements were suggested by .An Justin T. Gibbs Aq Mt gibbs@FreeBSD.org . Auto-extend support added by .An Kelly Yancey Aq Mt kbyanc@FreeBSD.org . Drain functionality added by .An Matthew Fleming Aq Mt mdf@FreeBSD.org . .Pp This manual page was written by .An Dag-Erling Sm\(/orgrav Aq Mt des@FreeBSD.org . Index: head/share/man/man9/taskqueue.9 =================================================================== --- head/share/man/man9/taskqueue.9 (revision 284556) +++ head/share/man/man9/taskqueue.9 (revision 284557) @@ -1,508 +1,508 @@ .\" -*- nroff -*- .\" .\" Copyright (c) 2000 Doug Rabson .\" .\" All rights reserved. .\" .\" This program is free software. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR .\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES .\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. .\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, .\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT .\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd January 4, 2015 .Dt TASKQUEUE 9 .Os .Sh NAME .Nm taskqueue .Nd asynchronous task execution .Sh SYNOPSIS .In sys/param.h .In sys/kernel.h .In sys/malloc.h .In sys/queue.h .In sys/taskqueue.h .Bd -literal typedef void (*task_fn_t)(void *context, int pending); typedef void (*taskqueue_enqueue_fn)(void *context); struct task { STAILQ_ENTRY(task) ta_link; /* link for queue */ u_short ta_pending; /* count times queued */ u_short ta_priority; /* priority of task in queue */ task_fn_t ta_func; /* task handler */ void *ta_context; /* argument for handler */ }; enum taskqueue_callback_type { TASKQUEUE_CALLBACK_TYPE_INIT, TASKQUEUE_CALLBACK_TYPE_SHUTDOWN, }; typedef void (*taskqueue_callback_fn)(void *context); struct timeout_task; .Ed .Ft struct taskqueue * .Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" .Ft struct taskqueue * .Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" .Ft int .Fn taskqueue_start_threads "struct taskqueue **tqp" "int count" "int pri" "const char *name" "..." .Ft int .Fo taskqueue_start_threads_pinned .Fa "struct taskqueue **tqp" "int count" "int pri" "int cpu_id" .Fa "const char *name" "..." .Fc .Ft void .Fn taskqueue_set_callback "struct taskqueue *queue" "enum taskqueue_callback_type cb_type" "taskqueue_callback_fn callback" "void *context" .Ft void .Fn taskqueue_free "struct taskqueue *queue" .Ft int .Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" .Ft int .Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *task" .Ft int .Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks" .Ft int .Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp" .Ft int .Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp" .Ft void .Fn taskqueue_drain "struct taskqueue *queue" "struct task *task" .Ft void .Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" .Ft void .Fn taskqueue_drain_all "struct taskqueue *queue" .Ft void .Fn taskqueue_block "struct taskqueue *queue" .Ft void .Fn taskqueue_unblock "struct taskqueue *queue" .Ft int .Fn taskqueue_member "struct taskqueue *queue" "struct thread *td" .Ft void .Fn taskqueue_run "struct taskqueue *queue" .Fn TASK_INIT "struct task *task" "int priority" "task_fn_t func" "void *context" .Fn TASK_INITIALIZER "int priority" "task_fn_t func" "void *context" .Fn TASKQUEUE_DECLARE "name" .Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" .Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" .Fn TASKQUEUE_DEFINE_THREAD "name" .Fn TASKQUEUE_FAST_DEFINE_THREAD "name" .Fn TIMEOUT_TASK_INIT "struct taskqueue *queue" "struct timeout_task *timeout_task" "int priority" "task_fn_t func" "void *context" .Sh DESCRIPTION These functions provide a simple interface for asynchronous execution of code. .Pp The function .Fn taskqueue_create is used to create new queues. The arguments to .Fn taskqueue_create include a name that should be unique, a set of .Xr malloc 9 flags that specify whether the call to .Fn malloc is allowed to sleep, a function that is called from .Fn taskqueue_enqueue when a task is added to the queue, and a pointer to the memory location where the identity of the thread that services the queue is recorded. .\" XXX The rest of the sentence gets lots in relation to the first part. The function called from .Fn taskqueue_enqueue must arrange for the queue to be processed (for instance by scheduling a software interrupt or waking a kernel thread). The memory location where the thread identity is recorded is used to signal the service thread(s) to terminate--when this value is set to zero and the thread is signaled it will terminate. If the queue is intended for use in fast interrupt handlers .Fn taskqueue_create_fast should be used in place of .Fn taskqueue_create . .Pp The function .Fn taskqueue_free should be used to free the memory used by the queue. Any tasks that are on the queue will be executed at this time after which the thread servicing the queue will be signaled that it should exit. .Pp Once a taskqueue has been created, its threads should be started using .Fn taskqueue_start_threads or .Fn taskqueue_start_threads_pinned . .Fn taskqueue_start_threads_pinned takes a .Va cpu_id argument which will cause the threads which are started for the taskqueue to be pinned to run on the given CPU. Callbacks may optionally be registered using .Fn taskqueue_set_callback . Currently, callbacks may be registered for the following purposes: .Bl -tag -width TASKQUEUE_CALLBACK_TYPE_SHUTDOWN .It Dv TASKQUEUE_CALLBACK_TYPE_INIT This callback is called by every thread in the taskqueue, before it executes any tasks. This callback must be set before the taskqueue's threads are started. .It Dv TASKQUEUE_CALLBACK_TYPE_SHUTDOWN This callback is called by every thread in the taskqueue, after it executes its last task. This callback will always be called before the taskqueue structure is reclaimed. .El .Pp To add a task to the list of tasks queued on a taskqueue, call .Fn taskqueue_enqueue with pointers to the queue and task. If the task's .Va ta_pending field is non-zero, then it is simply incremented to reflect the number of times the task was enqueued, up to a cap of USHRT_MAX. Otherwise, the task is added to the list before the first task which has a lower .Va ta_priority value or at the end of the list if no tasks have a lower priority. Enqueueing a task does not perform any memory allocation which makes it suitable for calling from an interrupt handler. This function will return .Er EPIPE if the queue is being freed. .Pp The function .Fn taskqueue_enqueue_fast should be used in place of .Fn taskqueue_enqueue when the enqueuing must happen from a fast interrupt handler. This method uses spin locks to avoid the possibility of sleeping in the fast interrupt context. .Pp When a task is executed, first it is removed from the queue, the value of .Va ta_pending is recorded and then the field is zeroed. The function .Va ta_func from the task structure is called with the value of the field .Va ta_context as its first argument and the value of .Va ta_pending as its second argument. After the function .Va ta_func returns, .Xr wakeup 9 is called on the task pointer passed to .Fn taskqueue_enqueue . .Pp The .Fn taskqueue_enqueue_timeout is used to schedule the enqueue after the specified amount of .Va ticks . Only non-fast task queues can be used for .Va timeout_task scheduling. If the .Va ticks argument is negative, the already scheduled enqueueing is not re-scheduled. Otherwise, the task is scheduled for enqueueing in the future, after the absolute value of .Va ticks is passed. .Pp The .Fn taskqueue_cancel function is used to cancel a task. The .Va ta_pending count is cleared, and the old value returned in the reference parameter .Fa pendp , if it is .Pf non- Dv NULL . If the task is currently running, .Dv EBUSY is returned, otherwise 0. To implement a blocking .Fn taskqueue_cancel that waits for a running task to finish, it could look like: .Bd -literal -offset indent while (taskqueue_cancel(tq, task, NULL) != 0) taskqueue_drain(tq, task); .Ed .Pp Note that, as with .Fn taskqueue_drain , the caller is responsible for ensuring that the task is not re-enqueued after being canceled. .Pp Similarly, the .Fn taskqueue_cancel_timeout function is used to cancel the scheduled task execution. .Pp The .Fn taskqueue_drain function is used to wait for the task to finish, and the .Fn taskqueue_drain_timeout function is used to wait for the scheduled task to finish. There is no guarantee that the task will not be enqueued after call to .Fn taskqueue_drain . If the caller wants to put the task into a known state, then before calling .Fn taskqueue_drain the caller should use out-of-band means to ensure that the task would not be enqueued. For example, if the task is enqueued by an interrupt filter, then the interrupt could be disabled. .Pp The .Fn taskqueue_drain_all function is used to wait for all pending and running tasks that are enqueued on the taskqueue to finish. Tasks posted to the taskqueue after .Fn taskqueue_drain_all begins processing, -including pending enqueues scheduled by a previous call to +including pending enqueues scheduled by a previous call to .Fn taskqueue_enqueue_timeout , do not extend the wait time of .Fn taskqueue_drain_all -and may complete after +and may complete after .Fn taskqueue_drain_all returns. .Pp The .Fn taskqueue_block function blocks the taskqueue. It prevents any enqueued but not running tasks from being executed. Future calls to .Fn taskqueue_enqueue will enqueue tasks, but the tasks will not be run until .Fn taskqueue_unblock is called. Please note that .Fn taskqueue_block does not wait for any currently running tasks to finish. Thus, the .Fn taskqueue_block does not provide a guarantee that .Fn taskqueue_run is not running after .Fn taskqueue_block returns, but it does provide a guarantee that .Fn taskqueue_run will not be called again until .Fn taskqueue_unblock is called. If the caller requires a guarantee that .Fn taskqueue_run is not running, then this must be arranged by the caller. Note that if .Fn taskqueue_drain is called on a task that is enqueued on a taskqueue that is blocked by .Fn taskqueue_block , then .Fn taskqueue_drain can not return until the taskqueue is unblocked. This can result in a deadlock if the thread blocked in .Fn taskqueue_drain is the thread that is supposed to call .Fn taskqueue_unblock . Thus, use of .Fn taskqueue_drain after .Fn taskqueue_block is discouraged, because the state of the task can not be known in advance. The same caveat applies to .Fn taskqueue_drain_all . .Pp The .Fn taskqueue_unblock function unblocks the previously blocked taskqueue. All enqueued tasks can be run after this call. .Pp The .Fn taskqueue_member function returns .No 1 if the given thread .Fa td is part of the given taskqueue .Fa queue and .No 0 otherwise. .Pp The .Fn taskqueue_run function will run all pending tasks in the specified .Fa queue . Normally this function is only used internally. .Pp A convenience macro, .Fn TASK_INIT "task" "priority" "func" "context" is provided to initialise a .Va task structure. The .Fn TASK_INITIALIZER macro generates an initializer for a task structure. A macro .Fn TIMEOUT_TASK_INIT "queue" "timeout_task" "priority" "func" "context" initializes the .Va timeout_task structure. The values of .Va priority , .Va func , and .Va context are simply copied into the task structure fields and the .Va ta_pending field is cleared. .Pp Five macros .Fn TASKQUEUE_DECLARE "name" , .Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" , .Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" , and .Fn TASKQUEUE_DEFINE_THREAD "name" .Fn TASKQUEUE_FAST_DEFINE_THREAD "name" are used to declare a reference to a global queue, to define the implementation of the queue, and declare a queue that uses its own thread. The .Fn TASKQUEUE_DEFINE macro arranges to call .Fn taskqueue_create with the values of its .Va name , .Va enqueue and .Va context arguments during system initialisation. After calling .Fn taskqueue_create , the .Va init argument to the macro is executed as a C statement, allowing any further initialisation to be performed (such as registering an interrupt handler etc.) .Pp The .Fn TASKQUEUE_DEFINE_THREAD macro defines a new taskqueue with its own kernel thread to serve tasks. The variable .Vt struct taskqueue *taskqueue_name is used to enqueue tasks onto the queue. .Pp .Fn TASKQUEUE_FAST_DEFINE and .Fn TASKQUEUE_FAST_DEFINE_THREAD act just like .Fn TASKQUEUE_DEFINE and .Fn TASKQUEUE_DEFINE_THREAD respectively but taskqueue is created with .Fn taskqueue_create_fast . .Ss Predefined Task Queues The system provides four global taskqueues, .Va taskqueue_fast , .Va taskqueue_swi , .Va taskqueue_swi_giant , and .Va taskqueue_thread . The .Va taskqueue_fast queue is for swi handlers dispatched from fast interrupt handlers, where sleep mutexes cannot be used. The swi taskqueues are run via a software interrupt mechanism. The .Va taskqueue_swi queue runs without the protection of the .Va Giant kernel lock, and the .Va taskqueue_swi_giant queue runs with the protection of the .Va Giant kernel lock. The thread taskqueue .Va taskqueue_thread runs in a kernel thread context, and tasks run from this thread do not run under the .Va Giant kernel lock. If the caller wants to run under .Va Giant , he should explicitly acquire and release .Va Giant in his taskqueue handler routine. .Pp To use these queues, call .Fn taskqueue_enqueue with the value of the global taskqueue variable for the queue you wish to use .Va ( taskqueue_swi , .Va taskqueue_swi_giant , or .Va taskqueue_thread ) . Use .Fn taskqueue_enqueue_fast for the global taskqueue variable .Va taskqueue_fast . .Pp The software interrupt queues can be used, for instance, for implementing interrupt handlers which must perform a significant amount of processing in the handler. The hardware interrupt handler would perform minimal processing of the interrupt and then enqueue a task to finish the work. This reduces to a minimum the amount of time spent with interrupts disabled. .Pp The thread queue can be used, for instance, by interrupt level routines that need to call kernel functions that do things that can only be done from a thread context. (e.g., call malloc with the M_WAITOK flag.) .Pp Note that tasks queued on shared taskqueues such as .Va taskqueue_swi may be delayed an indeterminate amount of time before execution. If queueing delays cannot be tolerated then a private taskqueue should be created with a dedicated processing thread. .Sh SEE ALSO .Xr ithread 9 , .Xr kthread 9 , .Xr swi 9 .Sh HISTORY This interface first appeared in .Fx 5.0 . There is a similar facility called work_queue in the Linux kernel. .Sh AUTHORS This manual page was written by .An Doug Rabson .