+out:
+ kauth_cred_unref(&ucred);
+ kauth_cred_unref(&my_cred);
+ return (error);
+}
+
+/*
+ * do_background_thread
+ * Returns: 0 Success
+ * XXX - todo - does this need a MACF hook?
+ */
+static int
+do_background_thread(struct proc *curp, int priority)
+{
+ int i;
+ thread_t thread;
+ struct uthread *ut;
+ thread_precedence_policy_data_t policy;
+ struct filedesc *fdp;
+ struct fileproc *fp;
+
+ thread = current_thread();
+ ut = get_bsdthread_info(thread);
+
+ if ( (priority & PRIO_DARWIN_BG) == 0 ) {
+ /* turn off backgrounding of thread */
+ if ( (ut->uu_flag & UT_BACKGROUND) == 0 ) {
+ /* already off */
+ return(0);
+ }
+
+ /* clear background bit in thread and disable disk IO throttle */
+ ut->uu_flag &= ~UT_BACKGROUND;
+ ut->uu_iopol_disk = IOPOL_NORMAL;
+
+ /* reset thread priority (we did not save previous value) */
+ policy.importance = 0;
+ thread_policy_set( thread, THREAD_PRECEDENCE_POLICY,
+ (thread_policy_t)&policy,
+ THREAD_PRECEDENCE_POLICY_COUNT );
+
+ /* disable networking IO throttle.
+ * NOTE - It is a known limitation of the current design that we
+ * could potentially clear TRAFFIC_MGT_SO_BACKGROUND bit for
+ * sockets created by other threads within this process.
+ */
+ proc_fdlock(curp);
+ fdp = curp->p_fd;
+ for ( i = 0; i < fdp->fd_nfiles; i++ ) {
+ struct socket *sockp;
+
+ fp = fdp->fd_ofiles[ i ];
+ if ( fp == NULL || (fdp->fd_ofileflags[ i ] & UF_RESERVED) != 0 ||
+ fp->f_fglob->fg_type != DTYPE_SOCKET ) {
+ continue;
+ }
+ sockp = (struct socket *)fp->f_fglob->fg_data;
+ if ( sockp->so_background_thread != thread ) {
+ continue;
+ }
+ sockp->so_traffic_mgt_flags &= ~TRAFFIC_MGT_SO_BACKGROUND;
+ sockp->so_background_thread = NULL;
+ }
+ proc_fdunlock(curp);
+
+ return(0);
+ }
+
+ /* background this thread */
+ if ( (ut->uu_flag & UT_BACKGROUND) != 0 ) {
+ /* already backgrounded */
+ return(0);
+ }
+
+ /* tag thread as background and throttle disk IO */
+ ut->uu_flag |= UT_BACKGROUND;
+ ut->uu_iopol_disk = IOPOL_THROTTLE;
+
+ policy.importance = INT_MIN;
+ thread_policy_set( thread, THREAD_PRECEDENCE_POLICY,
+ (thread_policy_t)&policy,
+ THREAD_PRECEDENCE_POLICY_COUNT );
+
+ /* throttle networking IO happens in socket( ) syscall.
+ * If UT_BACKGROUND is set in the current thread then
+ * TRAFFIC_MGT_SO_BACKGROUND socket option is set.
+ */
+ return(0);