xref: /freebsd/share/man/man9/kqueue.9 (revision 74a603eb004536f306e105569daaa39f26747662)
174a603ebSRuslan Ermilov.\" Copyright 2006 John-Mark Gurney
290db62acSJohn-Mark Gurney.\" All rights reserved.
390db62acSJohn-Mark Gurney.\"
490db62acSJohn-Mark Gurney.\" Redistribution and use in source and binary forms, with or without
590db62acSJohn-Mark Gurney.\" modification, are permitted provided that the following conditions
690db62acSJohn-Mark Gurney.\" are met:
790db62acSJohn-Mark Gurney.\" 1. Redistributions of source code must retain the above copyright
890db62acSJohn-Mark Gurney.\"    notice, this list of conditions and the following disclaimer.
990db62acSJohn-Mark Gurney.\" 2. Redistributions in binary form must reproduce the above copyright
1090db62acSJohn-Mark Gurney.\"    notice, this list of conditions and the following disclaimer in the
1190db62acSJohn-Mark Gurney.\"    documentation and/or other materials provided with the distribution.
1290db62acSJohn-Mark Gurney.\"
1390db62acSJohn-Mark Gurney.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1490db62acSJohn-Mark Gurney.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1590db62acSJohn-Mark Gurney.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1690db62acSJohn-Mark Gurney.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1790db62acSJohn-Mark Gurney.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1890db62acSJohn-Mark Gurney.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1990db62acSJohn-Mark Gurney.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2090db62acSJohn-Mark Gurney.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2190db62acSJohn-Mark Gurney.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2290db62acSJohn-Mark Gurney.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2390db62acSJohn-Mark Gurney.\" SUCH DAMAGE.
2490db62acSJohn-Mark Gurney.\"
2590db62acSJohn-Mark Gurney.\" $FreeBSD$
2690db62acSJohn-Mark Gurney.\"
27b5cc2eb7SJohn-Mark Gurney.Dd October 4, 2006
2890db62acSJohn-Mark Gurney.Dt KQUEUE 9
2990db62acSJohn-Mark Gurney.Os
3090db62acSJohn-Mark Gurney.Sh NAME
3174a603ebSRuslan Ermilov.Nm kqueue_add_filteropts , kqueue_del_filteropts ,
3274a603ebSRuslan Ermilov.Nm kqfd_register ,
3374a603ebSRuslan Ermilov.Nm knote_fdclose ,
3474a603ebSRuslan Ermilov.Nm knlist_add , knlist_remove , knlist_remove_inevent , knlist_empty ,
3574a603ebSRuslan Ermilov.Nm knlist_init , knlist_destroy , knlist_clear , knlist_delete ,
3690db62acSJohn-Mark Gurney.Nm KNOTE_LOCKED , KNOTE_UNLOCKED
3774a603ebSRuslan Ermilov.Nd "event delivery subsystem"
3890db62acSJohn-Mark Gurney.Sh SYNOPSIS
3990db62acSJohn-Mark Gurney.In sys/event.h
4090db62acSJohn-Mark Gurney.Ft int
4174a603ebSRuslan Ermilov.Fn kqueue_add_filteropts "int filt" "struct filterops *filtops"
4290db62acSJohn-Mark Gurney.Ft int
4390db62acSJohn-Mark Gurney.Fn kqueue_del_filteropts "int filt"
4490db62acSJohn-Mark Gurney.Ft int
4574a603ebSRuslan Ermilov.Fn kqfd_register "int fd" "struct kevent *kev" "struct thread *td" "int waitok"
4690db62acSJohn-Mark Gurney.Ft void
4774a603ebSRuslan Ermilov.Fn knote_fdclose "struct thread *td" "int fd"
4890db62acSJohn-Mark Gurney.Ft void
4974a603ebSRuslan Ermilov.Fn knlist_add "struct knlist *knl" "struct knote *kn" "int islocked"
5090db62acSJohn-Mark Gurney.Ft void
5174a603ebSRuslan Ermilov.Fn knlist_remove "struct knlist *knl" "struct knote *kn" "int islocked"
5290db62acSJohn-Mark Gurney.Ft void
5374a603ebSRuslan Ermilov.Fn knlist_remove_inevent "struct knlist *knl" "struct knote *kn"
5490db62acSJohn-Mark Gurney.Ft int
5574a603ebSRuslan Ermilov.Fn knlist_empty "struct knlist *knl"
5690db62acSJohn-Mark Gurney.Ft void
5774a603ebSRuslan Ermilov.Fo knlist_init
5874a603ebSRuslan Ermilov.Fa "struct knlist *knl"
5974a603ebSRuslan Ermilov.Fa "void *lock"
6074a603ebSRuslan Ermilov.Fa "void \*[lp]*kl_lock\*[rp]\*[lp]void *\*[rp]"
6174a603ebSRuslan Ermilov.Fa "void \*[lp]*kl_unlock\*[rp]\*[lp]void *\*[rp]"
6274a603ebSRuslan Ermilov.Fa "int \*[lp]*kl_locked\*[rp]\*[lp]void *\*[rp]"
6374a603ebSRuslan Ermilov.Fc
6490db62acSJohn-Mark Gurney.Ft void
6574a603ebSRuslan Ermilov.Fn knlist_destroy "struct knlist *knl"
6690db62acSJohn-Mark Gurney.Ft void
6774a603ebSRuslan Ermilov.Fn knlist_clear "struct knlist *knl" "int islocked"
6890db62acSJohn-Mark Gurney.Ft void
6974a603ebSRuslan Ermilov.Fn knlist_delete "struct knlist *knl" "struct thread *td" "int islocked"
7090db62acSJohn-Mark Gurney.Ft void
7174a603ebSRuslan Ermilov.Fn KNOTE_LOCKED "struct knlist *knl" "long hint"
7290db62acSJohn-Mark Gurney.Ft void
7374a603ebSRuslan Ermilov.Fn KNOTE_UNLOCKED "struct knlist *knl" "long hint"
7490db62acSJohn-Mark Gurney.Sh DESCRIPTION
7590db62acSJohn-Mark GurneyThe functions
7690db62acSJohn-Mark Gurney.Fn kqueue_add_filteropts
7790db62acSJohn-Mark Gurneyand
7890db62acSJohn-Mark Gurney.Fn kqueue_del_filteropts
7974a603ebSRuslan Ermilovallow for the addition and removal of a filter type.
8074a603ebSRuslan ErmilovThe filter is statically defined by the
8190db62acSJohn-Mark Gurney.Dv EVFILT_*
8290db62acSJohn-Mark Gurneymacros.
8390db62acSJohn-Mark GurneyThe function
8490db62acSJohn-Mark Gurney.Fn kqueue_add_filteropts
8574a603ebSRuslan Ermilovwill make
8674a603ebSRuslan Ermilov.Fa filt
8774a603ebSRuslan Ermilovavailable.
8874a603ebSRuslan ErmilovThe
8990db62acSJohn-Mark Gurney.Vt "struct filterops"
9090db62acSJohn-Mark Gurneyhas the following members:
9190db62acSJohn-Mark Gurney.Bl -tag -width ".Va f_attach"
9290db62acSJohn-Mark Gurney.It Va f_isfd
9390db62acSJohn-Mark GurneyIf
9490db62acSJohn-Mark Gurney.Va f_isfd
9590db62acSJohn-Mark Gurneyis set,
9690db62acSJohn-Mark Gurney.Va ident
9790db62acSJohn-Mark Gurneyin
9890db62acSJohn-Mark Gurney.Vt "struct kevent"
9990db62acSJohn-Mark Gurneyis taken to be a file descriptor.
10074a603ebSRuslan ErmilovIn this case, the
10174a603ebSRuslan Ermilov.Vt knote
10274a603ebSRuslan Ermilovpassed into
10390db62acSJohn-Mark Gurney.Va f_attach
10490db62acSJohn-Mark Gurneywill have the
10590db62acSJohn-Mark Gurney.Va kn_fp
10674a603ebSRuslan Ermilovmember initialized to the
10790db62acSJohn-Mark Gurney.Vt "struct file *"
10874a603ebSRuslan Ermilovthat represents the file descriptor.
10990db62acSJohn-Mark Gurney.It Va f_attach
11090db62acSJohn-Mark GurneyThe
11190db62acSJohn-Mark Gurney.Va f_attach
11274a603ebSRuslan Ermilovfunction will be called when attaching a
11390db62acSJohn-Mark Gurney.Vt knote
11490db62acSJohn-Mark Gurneyto the object.
11590db62acSJohn-Mark GurneyThe method should call
11690db62acSJohn-Mark Gurney.Fn knlist_add
11790db62acSJohn-Mark Gurneyto add the
11890db62acSJohn-Mark Gurney.Vt knote
11974a603ebSRuslan Ermilovto the list that was initialized with
12090db62acSJohn-Mark Gurney.Fn knlist_init .
12190db62acSJohn-Mark GurneyThe call to
12290db62acSJohn-Mark Gurney.Fn knlist_add
12374a603ebSRuslan Ermilovis only necessary if the object can have multiple
12474a603ebSRuslan Ermilov.Vt knotes
12574a603ebSRuslan Ermilovassociated with it.
12690db62acSJohn-Mark GurneyIf there is no
12790db62acSJohn-Mark Gurney.Vt knlist
12890db62acSJohn-Mark Gurneyto call
12990db62acSJohn-Mark Gurney.Fn knlist_add
13090db62acSJohn-Mark Gurneywith, the function
13190db62acSJohn-Mark Gurney.Va f_attach
13290db62acSJohn-Mark Gurneymust clear the
13390db62acSJohn-Mark Gurney.Dv KN_DETACHED
13490db62acSJohn-Mark Gurneybit of
13590db62acSJohn-Mark Gurney.Va kn_status
13690db62acSJohn-Mark Gurneyin the
13774a603ebSRuslan Ermilov.Vt knote .
13874a603ebSRuslan ErmilovThe function shall return 0 on success, or appropriate error for the failure.
13974a603ebSRuslan ErmilovDuring
14074a603ebSRuslan Ermilov.Va f_attach ,
14190db62acSJohn-Mark Gurneyit is valid to change the
14290db62acSJohn-Mark Gurney.Va kn_fops
14390db62acSJohn-Mark Gurneypointer to a different pointer.
14490db62acSJohn-Mark GurneyThis will change the
14590db62acSJohn-Mark Gurney.Va f_event
14690db62acSJohn-Mark Gurneyand
14790db62acSJohn-Mark Gurney.Va f_detach
14874a603ebSRuslan Ermilovfunctions called when processing the
14974a603ebSRuslan Ermilov.Vt knote .
15090db62acSJohn-Mark Gurney.It Va f_detach
15190db62acSJohn-Mark GurneyThe
15290db62acSJohn-Mark Gurney.Va f_detach
15374a603ebSRuslan Ermilovfunction will be called to detach the
15490db62acSJohn-Mark Gurney.Vt knote
15590db62acSJohn-Mark Gurneyif the
15690db62acSJohn-Mark Gurney.Vt knote
15790db62acSJohn-Mark Gurneyhas not already been detached by a call to
15890db62acSJohn-Mark Gurney.Fn knlist_remove .
15990db62acSJohn-Mark Gurney.It Va f_event
16090db62acSJohn-Mark GurneyThe
16190db62acSJohn-Mark Gurney.Va f_event
16274a603ebSRuslan Ermilovfunction will be called to update the status of the
16390db62acSJohn-Mark Gurney.Vt knote .
16490db62acSJohn-Mark GurneyIf the function returns 0, it will be assumed that the object is not
16590db62acSJohn-Mark Gurneyready (or no longer ready) to be woken up.
16674a603ebSRuslan ErmilovThe
16774a603ebSRuslan Ermilov.Fa hint
16874a603ebSRuslan Ermilovargument will be 0 when scanning
16974a603ebSRuslan Ermilov.Vt knotes
17074a603ebSRuslan Ermilovto see which are triggered.
17174a603ebSRuslan ErmilovOtherwise, the
17274a603ebSRuslan Ermilov.Fa hint
17374a603ebSRuslan Ermilovargument will be the value passed to either
17490db62acSJohn-Mark Gurney.Dv KNOTE_LOCKED
17590db62acSJohn-Mark Gurneyor
17690db62acSJohn-Mark Gurney.Dv KNOTE_UNLOCKED .
17790db62acSJohn-Mark GurneyThe
17890db62acSJohn-Mark Gurney.Va kn_data
17990db62acSJohn-Mark Gurneyvalue should be updated as necessary to reflect the current value, such as
18090db62acSJohn-Mark Gurneynumber of bytes available for reading, or buffer space available for writing.
18190db62acSJohn-Mark GurneyIf the note needs to be removed,
18290db62acSJohn-Mark Gurney.Fn knlist_remove_inevent
18390db62acSJohn-Mark Gurneymust be called.
18490db62acSJohn-Mark GurneyThe function
18590db62acSJohn-Mark Gurney.Fn knlist_remove_inevent
18690db62acSJohn-Mark Gurneywill remove the note from the list, the
18790db62acSJohn-Mark Gurney.Va f_detach
18874a603ebSRuslan Ermilovfunction will not be called and the
18974a603ebSRuslan Ermilov.Vt knote
19090db62acSJohn-Mark Gurneywill not be returned as an event.
19190db62acSJohn-Mark Gurney.El
19290db62acSJohn-Mark Gurney.Pp
19390db62acSJohn-Mark GurneyThe function
19490db62acSJohn-Mark Gurney.Fn kqfd_register
19590db62acSJohn-Mark Gurneywill register the
19690db62acSJohn-Mark Gurney.Vt kevent
19790db62acSJohn-Mark Gurneyon the kqueue file descriptor
19890db62acSJohn-Mark Gurney.Fa fd .
19974a603ebSRuslan ErmilovIf it is safe to sleep,
20074a603ebSRuslan Ermilov.Fa waitok
20174a603ebSRuslan Ermilovshould be set.
20290db62acSJohn-Mark Gurney.Pp
20390db62acSJohn-Mark GurneyThe function
20490db62acSJohn-Mark Gurney.Fn knote_fdclose
20590db62acSJohn-Mark Gurneyis used to delete all
20690db62acSJohn-Mark Gurney.Vt knotes
20790db62acSJohn-Mark Gurneyassociated with
20890db62acSJohn-Mark Gurney.Fa fd .
20974a603ebSRuslan ErmilovOnce returned, there will no longer be any
21090db62acSJohn-Mark Gurney.Vt knotes
21190db62acSJohn-Mark Gurneyassociated with the
21290db62acSJohn-Mark Gurney.Fa fd .
21390db62acSJohn-Mark GurneyThe
21490db62acSJohn-Mark Gurney.Vt knotes
21590db62acSJohn-Mark Gurneyremoved will never be returned from a
21690db62acSJohn-Mark Gurney.Xr kevent 2
21790db62acSJohn-Mark Gurneycall, so if userland uses the
21890db62acSJohn-Mark Gurney.Vt knote
21990db62acSJohn-Mark Gurneyto track resources, they will be leaked.
22090db62acSJohn-Mark GurneyThe
22190db62acSJohn-Mark Gurney.Fn FILEDESC_LOCK
22274a603ebSRuslan Ermilovlock must be held over the call to
22390db62acSJohn-Mark Gurney.Fn knote_fdclose
22490db62acSJohn-Mark Gurneyso that file descriptors cannot be added or removed.
22590db62acSJohn-Mark Gurney.Pp
22690db62acSJohn-Mark GurneyThe
22790db62acSJohn-Mark Gurney.Fn knlist_*
22874a603ebSRuslan Ermilovfamily of functions are for managing
22974a603ebSRuslan Ermilov.Vt knotes
23074a603ebSRuslan Ermilovassociated with an object.
23190db62acSJohn-Mark GurneyA
23274a603ebSRuslan Ermilov.Vt knlist
23390db62acSJohn-Mark Gurneyis not required, but is commonly used.
23490db62acSJohn-Mark GurneyIf used, the
23590db62acSJohn-Mark Gurney.Vt knlist
23674a603ebSRuslan Ermilovmust be initialized with the
23790db62acSJohn-Mark Gurney.Fn knlist_init
23890db62acSJohn-Mark Gurneyfunction.
23990db62acSJohn-Mark GurneyIf
24090db62acSJohn-Mark Gurney.Fa lock
24190db62acSJohn-Mark Gurneyis
24290db62acSJohn-Mark Gurney.Dv NULL ,
24390db62acSJohn-Mark Gurneyan internal lock will be used and the remaining arguments will be ignored.
24490db62acSJohn-Mark GurneyThe
24590db62acSJohn-Mark Gurney.Fa kl_lock , kl_unlock
24690db62acSJohn-Mark Gurneyand
24790db62acSJohn-Mark Gurney.Fa kl_locked
24874a603ebSRuslan Ermilovfunctions will be used to manipulate a
24990db62acSJohn-Mark Gurney.Fa lock .
25090db62acSJohn-Mark GurneyIf the argument is
25190db62acSJohn-Mark Gurney.Dv NULL ,
25274a603ebSRuslan Ermilovdefault routines operating on
25390db62acSJohn-Mark Gurney.Vt "struct mtx *"
25490db62acSJohn-Mark Gurneywill be used.
25590db62acSJohn-Mark GurneyThe
25690db62acSJohn-Mark Gurney.Vt knlist
25774a603ebSRuslan Ermilovstructure may be embedded into the object structure.
25890db62acSJohn-Mark GurneyThe
25990db62acSJohn-Mark Gurney.Fa lock
26090db62acSJohn-Mark Gurneywill be held over calls to
26174a603ebSRuslan Ermilov.Va f_event .
26290db62acSJohn-Mark GurneyIf
26390db62acSJohn-Mark Gurney.Dv NULL
26490db62acSJohn-Mark Gurneyis passed for the mutex, a private mutex will be used.
26590db62acSJohn-Mark GurneyThe function
26690db62acSJohn-Mark Gurney.Fn knlist_empty
26774a603ebSRuslan Ermilovrequires that a
26890db62acSJohn-Mark Gurney.Fa lock
26990db62acSJohn-Mark Gurneybe held.
27090db62acSJohn-Mark GurneyThe function
27190db62acSJohn-Mark Gurney.Fn knlist_clear
27274a603ebSRuslan Ermilovis used to remove all
27374a603ebSRuslan Ermilov.Vt knotes
27474a603ebSRuslan Ermilovassociated with the list.
27590db62acSJohn-Mark GurneyThe
27690db62acSJohn-Mark Gurney.Fa islocked
27774a603ebSRuslan Ermilovargument declares if
27890db62acSJohn-Mark Gurney.Fa lock
27974a603ebSRuslan Ermilovhas been acquired.
28090db62acSJohn-Mark GurneyAll
28190db62acSJohn-Mark Gurney.Vt knotes
28290db62acSJohn-Mark Gurneywill be marked as detached, and
28390db62acSJohn-Mark Gurney.Dv EV_ONESHOT
28490db62acSJohn-Mark Gurneywill be set so that the
28590db62acSJohn-Mark Gurney.Vt knote
28690db62acSJohn-Mark Gurneywill be deleted after the next scan.
28774a603ebSRuslan ErmilovThe
28890db62acSJohn-Mark Gurney.Fn knlist_destroy
28974a603ebSRuslan Ermilovfunction is used to destroy a
29074a603ebSRuslan Ermilov.Vt knlist .
29190db62acSJohn-Mark GurneyThere must be no
29290db62acSJohn-Mark Gurney.Vt knotes
29390db62acSJohn-Mark Gurneyassociated with the
29490db62acSJohn-Mark Gurney.Vt knlist
29574a603ebSRuslan Ermilov.Fn ( knlist_empty
29674a603ebSRuslan Ermilovreturns true)
29774a603ebSRuslan Ermilovand no more
29890db62acSJohn-Mark Gurney.Vt knotes
29974a603ebSRuslan Ermilovmay be attached to the object.
30074a603ebSRuslan ErmilovA
30174a603ebSRuslan Ermilov.Vt knlist
30274a603ebSRuslan Ermilovmay be emptied by calling
30374a603ebSRuslan Ermilov.Fn knlist_clear .
30490db62acSJohn-Mark Gurney.Pp
30574a603ebSRuslan ErmilovThe macros
30690db62acSJohn-Mark Gurney.Fn KNOTE_LOCKED
30790db62acSJohn-Mark Gurneyand
30890db62acSJohn-Mark Gurney.Fn KNOTE_UNLOCKED
30974a603ebSRuslan Ermilovare used to notify
31074a603ebSRuslan Ermilov.Vt knotes
31174a603ebSRuslan Ermilovabout events associated with the object.
31274a603ebSRuslan ErmilovIt will iterate over all
31390db62acSJohn-Mark Gurney.Vt knotes
31490db62acSJohn-Mark Gurneyon the list calling the
31590db62acSJohn-Mark Gurney.Va f_event
31690db62acSJohn-Mark Gurneyfunction associated with the
31790db62acSJohn-Mark Gurney.Vt knote .
31874a603ebSRuslan ErmilovThe macro
31990db62acSJohn-Mark Gurney.Fn KNOTE_LOCKED
32090db62acSJohn-Mark Gurneymust be used if the lock associated with the
32190db62acSJohn-Mark Gurney.Fa knl
32290db62acSJohn-Mark Gurneypassed in is held.
32390db62acSJohn-Mark GurneyThe function
32490db62acSJohn-Mark Gurney.Fn KNOTE_UNLOCKED
32574a603ebSRuslan Ermilovwill acquire the lock before iterating over the list of
32674a603ebSRuslan Ermilov.Vt knotes .
32790db62acSJohn-Mark Gurney.Sh RETURN VALUES
32890db62acSJohn-Mark GurneyThe function
32990db62acSJohn-Mark Gurney.Fn kqueue_add_filteropts
33090db62acSJohn-Mark Gurneywill return zero on success,
33190db62acSJohn-Mark Gurney.Er EINVAL
33290db62acSJohn-Mark Gurneyin the case of an invalid
33374a603ebSRuslan Ermilov.Fa filt ,
33490db62acSJohn-Mark Gurneyor
33590db62acSJohn-Mark Gurney.Er EEXIST
33690db62acSJohn-Mark Gurneyif the filter has already been installed.
33790db62acSJohn-Mark Gurney.Pp
33890db62acSJohn-Mark GurneyThe function
33990db62acSJohn-Mark Gurney.Fn kqueue_del_filteropts
34090db62acSJohn-Mark Gurneywill return zero on success,
34190db62acSJohn-Mark Gurney.Er EINVAL
34290db62acSJohn-Mark Gurneyin the case of an invalid
34374a603ebSRuslan Ermilov.Fa filt ,
34490db62acSJohn-Mark Gurneyor
34590db62acSJohn-Mark Gurney.Er EBUSY
34690db62acSJohn-Mark Gurneyif the filter is still in use.
34790db62acSJohn-Mark Gurney.Pp
34890db62acSJohn-Mark GurneyThe function
34990db62acSJohn-Mark Gurney.Fn kqfd_register
35090db62acSJohn-Mark Gurneywill return zero on success,
35190db62acSJohn-Mark Gurney.Er EBADF
35274a603ebSRuslan Ermilovif the file descriptor is not a kqueue, or any of the possible values returned
35390db62acSJohn-Mark Gurneyby
35474a603ebSRuslan Ermilov.Xr kevent 2 .
35590db62acSJohn-Mark Gurney.Sh SEE ALSO
35674a603ebSRuslan Ermilov.Xr kevent 2 ,
35774a603ebSRuslan Ermilov.Xr kqueue 2
35890db62acSJohn-Mark Gurney.Sh AUTHORS
35990db62acSJohn-Mark GurneyThis
36090db62acSJohn-Mark Gurneymanual page was written by
36190db62acSJohn-Mark Gurney.An John-Mark Gurney Aq jmg@FreeBSD.org .
362