1.\" Copyright (c) 2002 Packet Design, LLC. 2.\" All rights reserved. 3.\" 4.\" Subject to the following obligations and disclaimer of warranty, 5.\" use and redistribution of this software, in source or object code 6.\" forms, with or without modifications are expressly permitted by 7.\" Packet Design; provided, however, that: 8.\" 9.\" (i) Any and all reproductions of the source or object code 10.\" must include the copyright notice above and the following 11.\" disclaimer of warranties; and 12.\" (ii) No rights are granted, in any manner or form, to use 13.\" Packet Design trademarks, including the mark "PACKET DESIGN" 14.\" on advertising, endorsements, or otherwise except as such 15.\" appears in the above copyright notice or in the software. 16.\" 17.\" THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND 18.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO 19.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING 20.\" THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED 21.\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, 22.\" OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE, 23.\" OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS 24.\" OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, 25.\" RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE 26.\" LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE 27.\" OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT, 28.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL 29.\" DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF 30.\" USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF 31.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 32.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 33.\" THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF 34.\" THE POSSIBILITY OF SUCH DAMAGE. 35.\" 36.\" $FreeBSD$ 37.\" 38.Dd February 13, 2007 39.Dt KSE 2 40.Os 41.Sh NAME 42.Nm kse 43.Nd "kernel support for user threads" 44.Sh LIBRARY 45.Lb libc 46.Sh SYNOPSIS 47.In sys/types.h 48.In sys/kse.h 49.Ft int 50.Fn kse_create "struct kse_mailbox *mbx" "int sys-scope" 51.Ft int 52.Fn kse_exit void 53.Ft int 54.Fn kse_release "struct timespec *timeout" 55.Ft int 56.Fn kse_switchin "struct kse_thr_mailbox *tmbx" "int flags" 57.Ft int 58.Fn kse_thr_interrupt "struct kse_thr_mailbox *tmbx" "int cmd" "long data" 59.Ft int 60.Fn kse_wakeup "struct kse_mailbox *mbx" 61.Sh DESCRIPTION 62These system calls implement kernel support for multi-threaded processes. 63.\" 64.Ss Overview 65.\" 66Traditionally, user threading has been implemented in one of two ways: 67either all threads are managed in user space and the kernel is unaware 68of any threading (also known as 69.Dq "N to 1" ) , 70or else separate processes sharing 71a common memory space are created for each thread (also known as 72.Dq "N to N" ) . 73These approaches have advantages and disadvantages: 74.Bl -column "- Cannot utilize multiple CPUs" "+ Can utilize multiple CPUs" 75.It Sy "User threading Kernel threading" 76.It "+ Lightweight - Heavyweight" 77.It "+ User controls scheduling - Kernel controls scheduling" 78.It "- Syscalls must be wrapped + No syscall wrapping required" 79.It "- Cannot utilize multiple CPUs + Can utilize multiple CPUs" 80.El 81.Pp 82The KSE system is a 83hybrid approach that achieves the advantages of both the user and kernel 84threading approaches. 85The underlying philosophy of the KSE system is to give kernel support 86for user threading without taking away any of the user threading library's 87ability to make scheduling decisions. 88A kernel-to-user upcall mechanism is used to pass control to the user 89threading library whenever a scheduling decision needs to be made. 90An arbitrarily number of user threads are multiplexed onto a fixed number of 91virtual CPUs supplied by the kernel. 92This can be thought of as an 93.Dq "N to M" 94threading scheme. 95.Pp 96Some general implications of this approach include: 97.Bl -bullet 98.It 99The user process can run multiple threads simultaneously on multi-processor 100machines. 101The kernel grants the process virtual CPUs to schedule as it 102wishes; these may run concurrently on real CPUs. 103.It 104All operations that block in the kernel become asynchronous, allowing 105the user process to schedule another thread when any thread blocks. 106.El 107.\" 108.Ss Definitions 109.\" 110KSE allows a user process to have multiple 111.Sy threads 112of execution in existence at the same time, some of which may be blocked 113in the kernel while others may be executing or blocked in user space. 114A 115.Sy "kernel scheduling entity" 116(KSE) is a 117.Dq "virtual CPU" 118granted to the process for the purpose of executing threads. 119A thread that is currently executing is always associated with 120exactly one KSE, whether executing in user space or in the kernel. 121The KSE is said to be 122.Sy assigned 123to the thread. 124KSEs (a user abstraction) are implemented on top 125of kernel threads using an 'upcall' entity. 126.Pp 127The KSE becomes 128.Sy unassigned , 129and the associated thread is suspended, when the KSE has an associated 130.Sy mailbox , 131(see below) the thread has an associated 132.Sy thread mailbox , 133(also see below) and any of the following occurs: 134.Bl -bullet 135.It 136The thread invokes a system call that blocks. 137.It 138The thread makes any other demand of the kernel that cannot be immediately 139satisfied, e.g., touches a page of memory that needs to be fetched from disk, 140causing a page fault. 141.It 142Another thread that was previously blocked in the kernel completes its 143work in the kernel (or is 144.Sy interrupted ) 145and becomes ready to return to user space, and the current thread is returning 146to user space. 147.It 148A signal is delivered to the process, and this KSE is chosen to deliver it. 149.El 150.Pp 151In other words, as soon as there is a scheduling decision to be made, 152the KSE becomes unassigned, because the kernel does not presume to know 153how the process' other runnable threads should be scheduled. 154Unassigned KSEs always return to user space as soon as possible via 155the 156.Sy upcall 157mechanism (described below), allowing the user process to decide how 158that KSE should be utilized next. 159KSEs always complete as much work as possible in the kernel before 160becoming unassigned. 161.Pp 162Individual KSEs within a process are effectively indistinguishable, 163and any KSE in a process may be assigned by the kernel to any runnable 164(in the kernel) thread associated with that process. 165In practice, the kernel attempts to preserve the affinity between threads 166and actual CPUs to optimize cache behavior, but this is invisible to the 167user process. 168(Affinity is not yet fully implemented.) 169.Pp 170Each KSE has a unique 171.Sy "KSE mailbox" 172supplied by the user process. 173A mailbox consists of a control structure containing a pointer to an 174.Sy "upcall function" 175and a user stack. 176The KSE invokes this function whenever it becomes unassigned. 177The kernel updates this structure with information about threads that have 178become runnable and signals that have been delivered before each upcall. 179Upcalls may be temporarily blocked by the user thread scheduling code 180during critical sections. 181.Pp 182Each user thread has a unique 183.Sy "thread mailbox" 184as well. 185Threads are referred to using pointers to these mailboxes when communicating 186between the kernel and the user thread scheduler. 187Each KSE's mailbox contains a pointer to the mailbox of the user thread 188that the KSE is currently executing. 189This pointer is saved when the thread blocks in the kernel. 190.Pp 191Whenever a thread blocked in the kernel is ready to return to user space, 192it is added to the process's list of 193.Sy completed 194threads. 195This list is presented to the user code at the next upcall as a linked list 196of thread mailboxes. 197.Pp 198There is a kernel-imposed limit on the number of threads in a process 199that may be simultaneously blocked in the kernel (this number is not 200currently visible to the user). 201When this limit is reached, upcalls are blocked and no work is performed 202for the process until one of the threads completes (or a signal is 203received). 204.\" 205.Ss Managing KSEs 206.\" 207To become multi-threaded, a process must first invoke 208.Fn kse_create . 209The 210.Fn kse_create 211system call 212creates a new KSE (except for the very first invocation; see below). 213The KSE will be associated with the mailbox pointed to by 214.Fa mbx . 215If 216.Fa sys_scope 217is non-zero, then the new thread will be counted as a system scope 218thread. Other things must be done as well to make a system scope thread 219so this is not sufficient (yet). 220System scope variables are not covered 221in detail in this manual page yet, but briefly, they never perform 222upcalls and do not return to the user thread scheduler. 223Once launched they run autonomously. 224The pthreads library knows how to make system 225scope threads and users are encouraged to use the library interface. 226.Pp 227Each process initially has a single KSE executing a single user thread. 228Since the KSE does not have an associated mailbox, it must remain assigned 229to the thread and does not perform any upcalls. 230(It is by definition a system scope thread). 231The result is the traditional, unthreaded mode of operation. 232Therefore, as a special case, the first call to 233.Fn kse_create 234by this initial thread with 235.Fa sys_scope 236equal to zero does not create a new KSE; instead, it simply associates the 237current KSE with the supplied KSE mailbox, and no immediate upcall results. 238However, an upcall will be triggered the next time the thread blocks and 239the required conditions are met. 240.Pp 241The kernel does not allow more KSEs to exist in a process than the 242number of physical CPUs in the system (this number is available as the 243.Xr sysctl 3 244variable 245.Va hw.ncpu ) . 246Having more KSEs than CPUs would not add any value to the user process, 247as the additional KSEs would just compete with each other for access to 248the real CPUs. 249Since the extra KSEs would always be side-lined, the result 250to the application would be exactly the same as having fewer KSEs. 251There may however be arbitrarily many user threads, and it is up to the 252user thread scheduler to handle mapping the application's user threads 253onto the available KSEs. 254.Pp 255The 256.Fn kse_exit 257system call 258causes the KSE assigned to the currently running thread to be destroyed. 259If this KSE is the last one in the process, there must be no remaining 260threads associated with that process blocked in the kernel. 261This system call does not return unless there is an error. 262Calling 263.Fn kse_exit 264from the last thread is the same as calling 265.Fn exit . 266.Pp 267The 268.Fn kse_release 269system call 270is used to 271.Dq park 272the KSE assigned to the currently running thread when it is not needed, 273e.g., when there are more available KSEs than runnable user threads. 274The thread converts to an upcall but does not get scheduled until 275there is a new reason to do so, e.g., a previously 276blocked thread becomes runnable, or the timeout expires. 277If successful, 278.Fn kse_release 279does not return to the caller. 280.Pp 281The 282.Fn kse_switchin 283system call can be used by the UTS, when it has selected a new thread, 284to switch to the context of that thread. 285The use of 286.Fn kse_switchin 287is machine dependent. 288Some platforms do not need a system call to switch to a new context, 289while others require its use in particular cases. 290.Pp 291The 292.Fn kse_wakeup 293system call 294is the opposite of 295.Fn kse_release . 296It causes the (parked) KSE associated with the mailbox pointed to by 297.Fa mbx 298to be woken up, causing it to upcall. 299If the KSE has already woken up for another reason, this system call has no 300effect. 301The 302.Fa mbx 303argument 304may be 305.Dv NULL 306to specify 307.Dq "any KSE in the current process" . 308.Pp 309The 310.Fn kse_thr_interrupt 311system call 312is used to interrupt a currently blocked thread. 313The thread must either be blocked in the kernel or assigned to a KSE 314(i.e., executing). 315The thread is then marked as interrupted. 316As soon as the thread invokes an interruptible system call (or immediately 317for threads already blocked in one), the thread will be made runnable again, 318even though the kernel operation may not have completed. 319The effect on the interrupted system call is the same as if it had been 320interrupted by a signal; typically this means an error is returned with 321.Va errno 322set to 323.Er EINTR . 324.\" 325.Ss Signals 326.\" 327The current implementation creates a special signal thread. 328Kernel threads (KSEs) in a process mask all signals, and only the signal 329thread waits for signals to be delivered to the process, the signal thread 330is responsible 331for dispatching signals to user threads. 332.Pp 333A downside of this is that if a multiplexed thread 334calls the 335.Fn execve 336syscall, its signal mask and pending signals may not be 337available in the kernel. 338They are stored 339in userland and the kernel does not know where to get them, however 340.Tn POSIX 341requires them to be restored and passed them to new process. 342Just setting the mask for the thread before calling 343.Fn execve 344is only a 345close approximation to the problem as it does not re-deliver back to the kernel 346any pending signals that the old process may have blocked, and it allows a 347window in which new signals may be delivered to the process between the setting 348of the mask and the 349.Fn execve . 350.Pp 351For now this problem has been solved by adding a special combined 352.Fn kse_thr_interrupt Ns / Ns Fn execve 353mode to the 354.Fn kse_thr_interrupt 355syscall. 356The 357.Fn kse_thr_interrupt 358syscall has a sub command 359.Dv KSE_INTR_EXECVE , 360that allows it to accept a 361.Vt kse_execv_args 362structure, and allowing it to adjust the signals and then atomically 363convert into an 364.Fn execve 365call. 366Additional pending signals and the correct signal mask can be passed 367to the kernel in this way. 368The thread library overrides the 369.Fn execve 370syscall 371and translates it into 372.Fn kse_intr_interrupt 373call, allowing a multiplexed thread 374to restore pending signals and the correct signal mask before doing the 375.Fn exec . 376This solution to the problem may change. 377.\" 378.Ss KSE Mailboxes 379.\" 380Each KSE has a unique mailbox for user-kernel communication defined in 381.In sys/kse.h . 382Some of the fields there are: 383.Pp 384.Va km_version 385describes the version of this structure and must be equal to 386.Dv KSE_VER_0 . 387.Va km_udata 388is an opaque pointer ignored by the kernel. 389.Pp 390.Va km_func 391points to the KSE's upcall function; 392it will be invoked using 393.Va km_stack , 394which must remain valid for the lifetime of the KSE. 395.Pp 396.Va km_curthread 397always points to the thread that is currently assigned to this KSE if any, 398or 399.Dv NULL 400otherwise. 401This field is modified by both the kernel and the user process as follows. 402.Pp 403When 404.Va km_curthread 405is not 406.Dv NULL , 407it is assumed to be pointing at the mailbox for the currently executing 408thread, and the KSE may be unassigned, e.g., if the thread blocks in the 409kernel. 410The kernel will then save the contents of 411.Va km_curthread 412with the blocked thread, set 413.Va km_curthread 414to 415.Dv NULL , 416and upcall to invoke 417.Fn km_func . 418.Pp 419When 420.Va km_curthread 421is 422.Dv NULL , 423the kernel will never perform any upcalls with this KSE; in other words, 424the KSE remains assigned to the thread even if it blocks. 425.Va km_curthread 426must be 427.Dv NULL 428while the KSE is executing critical user thread scheduler 429code that would be disrupted by an intervening upcall; 430in particular, while 431.Fn km_func 432itself is executing. 433.Pp 434Before invoking 435.Fn km_func 436in any upcall, the kernel always sets 437.Va km_curthread 438to 439.Dv NULL . 440Once the user thread scheduler has chosen a new thread to run, 441it should point 442.Va km_curthread 443at the thread's mailbox, re-enabling upcalls, and then resume the thread. 444.Em Note : 445modification of 446.Va km_curthread 447by the user thread scheduler must be atomic 448with the loading of the context of the new thread, to avoid 449the situation where the thread context area 450may be modified by a blocking async operation, while there 451is still valid information to be read out of it. 452.Pp 453.Va km_completed 454points to a linked list of user threads that have completed their work 455in the kernel since the last upcall. 456The user thread scheduler should put these threads back into its 457own runnable queue. 458Each thread in a process that completes a kernel operation 459(synchronous or asynchronous) that results in an upcall is guaranteed to be 460linked into exactly one KSE's 461.Va km_completed 462list; which KSE in the group, however, is indeterminate. 463Furthermore, the completion will be reported in only one upcall. 464.Pp 465.Va km_sigscaught 466contains the list of signals caught by this process since the previous 467upcall to any KSE in the process. 468As long as there exists one or more KSEs with an associated mailbox in 469the user process, signals are delivered this way rather than the 470traditional way. 471(This has not been implemented and may change.) 472.Pp 473.Va km_timeofday 474is set by the kernel to the current system time before performing 475each upcall. 476.Pp 477.Va km_flags 478may contain any of the following bits OR'ed together: 479.Bl -tag -width indent 480.It Dv KMF_NOUPCALL 481Block upcalls from happening. 482The thread is in some critical section. 483.It Dv KMF_NOCOMPLETED , KMF_DONE , KMF_BOUND 484This thread should be considered to be permanently bound to 485its KSE, and treated much like a non-threaded process would be. 486It is a 487.Dq "long term" 488version of 489.Dv KMF_NOUPCALL 490in some ways. 491.It Dv KMF_WAITSIGEVENT 492Implement characteristics needed for the signal delivery thread. 493.El 494.\" 495.Ss Thread Mailboxes 496.\" 497Each user thread must have associated with it a unique 498.Vt "struct kse_thr_mailbox" 499as defined in 500.In sys/kse.h . 501It includes the following fields. 502.Pp 503.Va tm_udata 504is an opaque pointer ignored by the kernel. 505.Pp 506.Va tm_context 507stores the context for the thread when the thread is blocked in user space. 508This field is also updated by the kernel before a completed thread is returned 509to the user thread scheduler via 510.Va km_completed . 511.Pp 512.Va tm_next 513links the 514.Va km_completed 515threads together when returned by the kernel with an upcall. 516The end of the list is marked with a 517.Dv NULL 518pointer. 519.Pp 520.Va tm_uticks 521and 522.Va tm_sticks 523are time counters for user mode and kernel mode execution, respectively. 524These counters count ticks of the statistics clock (see 525.Xr clocks 7 ) . 526While any thread is actively executing in the kernel, the corresponding 527.Va tm_sticks 528counter is incremented. 529While any KSE is executing in user space and that KSE's 530.Va km_curthread 531pointer is not equal to 532.Dv NULL , 533the corresponding 534.Va tm_uticks 535counter is incremented. 536.Pp 537.Va tm_flags 538may contain any of the following bits OR'ed together: 539.Bl -tag -width indent 540.It Dv TMF_NOUPCALL 541Similar to 542.Dv KMF_NOUPCALL . 543This flag inhibits upcalling for critical sections. 544Some architectures require this to be in one place and some in the other. 545.El 546.Sh RETURN VALUES 547The 548.Fn kse_create , 549.Fn kse_wakeup , 550and 551.Fn kse_thr_interrupt 552system calls 553return zero if successful. 554The 555.Fn kse_exit 556and 557.Fn kse_release 558system calls 559do not return if successful. 560.Pp 561All of these system calls return a non-zero error code in case of an error. 562.Sh ERRORS 563The 564.Fn kse_create 565system call 566will fail if: 567.Bl -tag -width Er 568.It Bq Er ENXIO 569There are already as many KSEs in the process as hardware processors. 570.It Bq Er EAGAIN 571The user is not the super user, and the soft resource limit corresponding 572to the 573.Fa resource 574argument 575.Dv RLIMIT_NPROC 576would be exceeded (see 577.Xr getrlimit 2 ) . 578.It Bq Er EFAULT 579The 580.Fa mbx 581argument 582points to an address which is not a valid part of the process address space. 583.El 584.Pp 585The 586.Fn kse_exit 587system call 588will fail if: 589.Bl -tag -width Er 590.It Bq Er EDEADLK 591The current KSE is the last in its process and there are still one or more 592threads associated with the process blocked in the kernel. 593.It Bq Er ESRCH 594The current KSE has no associated mailbox, i.e., the process is operating 595in traditional, unthreaded mode (in this case use 596.Xr _exit 2 597to exit the process). 598.El 599.Pp 600The 601.Fn kse_release 602system call 603will fail if: 604.Bl -tag -width Er 605.It Bq Er ESRCH 606The current KSE has no associated mailbox, i.e., the process is operating is 607traditional, unthreaded mode. 608.El 609.Pp 610The 611.Fn kse_wakeup 612system call 613will fail if: 614.Bl -tag -width Er 615.It Bq Er ESRCH 616The 617.Fa mbx 618argument 619is not 620.Dv NULL 621and the mailbox pointed to by 622.Fa mbx 623is not associated with any KSE in the process. 624.It Bq Er ESRCH 625The 626.Fa mbx 627argument 628is 629.Dv NULL 630and the current KSE has no associated mailbox, i.e., the process is operating 631in traditional, unthreaded mode. 632.El 633.Pp 634The 635.Fn kse_thr_interrupt 636system call 637will fail if: 638.Bl -tag -width Er 639.It Bq Er ESRCH 640The thread corresponding to 641.Fa tmbx 642is neither currently assigned to any KSE in the process nor blocked in the 643kernel. 644.El 645.Sh SEE ALSO 646.Xr rfork 2 , 647.Xr pthread 3 , 648.Xr ucontext 3 649.Rs 650.%A "Thomas E. Anderson" 651.%A "Brian N. Bershad" 652.%A "Edward D. Lazowska" 653.%A "Henry M. Levy" 654.%J "ACM Transactions on Computer Systems" 655.%N Issue 1 656.%V Volume 10 657.%D February 1992 658.%I ACM Press 659.%P pp. 53-79 660.%T "Scheduler activations: effective kernel support for the user-level management of parallelism" 661.Re 662.Sh HISTORY 663The KSE system calls first appeared in 664.Fx 5.0 . 665.Sh AUTHORS 666KSE was originally implemented by 667.An -nosplit 668.An "Julian Elischer" Aq julian@FreeBSD.org , 669with additional contributions by 670.An "Jonathan Mini" Aq mini@FreeBSD.org , 671.An "Daniel Eischen" Aq deischen@FreeBSD.org , 672and 673.An "David Xu" Aq davidxu@FreeBSD.org . 674.Pp 675This manual page was written by 676.An "Archie Cobbs" Aq archie@FreeBSD.org . 677.Sh BUGS 678The KSE code is 679.Ud 680