/ duct-tape / xnu / osfmk / kern / thread_act.c
thread_act.c
   1  /*
   2   * Copyright (c) 2000-2016 Apple Inc. All rights reserved.
   3   *
   4   * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
   5   *
   6   * This file contains Original Code and/or Modifications of Original Code
   7   * as defined in and that are subject to the Apple Public Source License
   8   * Version 2.0 (the 'License'). You may not use this file except in
   9   * compliance with the License. The rights granted to you under the License
  10   * may not be used to create, or enable the creation or redistribution of,
  11   * unlawful or unlicensed copies of an Apple operating system, or to
  12   * circumvent, violate, or enable the circumvention or violation of, any
  13   * terms of an Apple operating system software license agreement.
  14   *
  15   * Please obtain a copy of the License at
  16   * http://www.opensource.apple.com/apsl/ and read it before using this file.
  17   *
  18   * The Original Code and all software distributed under the License are
  19   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  20   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  21   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
  22   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  23   * Please see the License for the specific language governing rights and
  24   * limitations under the License.
  25   *
  26   * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  27   */
  28  /*
  29   * @OSF_FREE_COPYRIGHT@
  30   */
  31  /*
  32   * Copyright (c) 1993 The University of Utah and
  33   * the Center for Software Science (CSS).  All rights reserved.
  34   *
  35   * Permission to use, copy, modify and distribute this software and its
  36   * documentation is hereby granted, provided that both the copyright
  37   * notice and this permission notice appear in all copies of the
  38   * software, derivative works or modified versions, and any portions
  39   * thereof, and that both notices appear in supporting documentation.
  40   *
  41   * THE UNIVERSITY OF UTAH AND CSS ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
  42   * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSS DISCLAIM ANY LIABILITY OF
  43   * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
  44   *
  45   * CSS requests users of this software to return to css-dist@cs.utah.edu any
  46   * improvements that they make and grant CSS redistribution rights.
  47   *
  48   *	Author:	Bryan Ford, University of Utah CSS
  49   *
  50   *	Thread management routines
  51   */
  52  
  53  #include <mach/mach_types.h>
  54  #include <mach/kern_return.h>
  55  #include <mach/thread_act_server.h>
  56  
  57  #include <kern/kern_types.h>
  58  #include <kern/ast.h>
  59  #include <kern/mach_param.h>
  60  #include <kern/zalloc.h>
  61  #include <kern/extmod_statistics.h>
  62  #include <kern/thread.h>
  63  #include <kern/task.h>
  64  #include <kern/sched_prim.h>
  65  #include <kern/misc_protos.h>
  66  #include <kern/assert.h>
  67  #include <kern/exception.h>
  68  #include <kern/ipc_mig.h>
  69  #include <kern/ipc_tt.h>
  70  #include <kern/machine.h>
  71  #include <kern/spl.h>
  72  #include <kern/syscall_subr.h>
  73  #include <kern/sync_lock.h>
  74  #include <kern/processor.h>
  75  #include <kern/timer.h>
  76  #include <kern/affinity.h>
  77  #include <kern/host.h>
  78  
  79  #include <stdatomic.h>
  80  
  81  #include <security/mac_mach_internal.h>
  82  
  83  static void act_abort(thread_t thread);
  84  
  85  static void thread_suspended(void *arg, wait_result_t result);
  86  static void thread_set_apc_ast(thread_t thread);
  87  static void thread_set_apc_ast_locked(thread_t thread);
  88  
  89  /*
  90   * Internal routine to mark a thread as started.
  91   * Always called with the thread mutex locked.
  92   */
  93  void
  94  thread_start(
  95  	thread_t                        thread)
  96  {
  97  	clear_wait(thread, THREAD_AWAKENED);
  98  	thread->started = TRUE;
  99  }
 100  
 101  /*
 102   * Internal routine to mark a thread as waiting
 103   * right after it has been created.  The caller
 104   * is responsible to call wakeup()/thread_wakeup()
 105   * or thread_terminate() to get it going.
 106   *
 107   * Always called with the thread mutex locked.
 108   *
 109   * Task and task_threads mutexes also held
 110   * (so nobody can set the thread running before
 111   * this point)
 112   *
 113   * Converts TH_UNINT wait to THREAD_INTERRUPTIBLE
 114   * to allow termination from this point forward.
 115   */
 116  void
 117  thread_start_in_assert_wait(
 118  	thread_t                        thread,
 119  	event_t             event,
 120  	wait_interrupt_t    interruptible)
 121  {
 122  	struct waitq *waitq = assert_wait_queue(event);
 123  	wait_result_t wait_result;
 124  	spl_t spl;
 125  
 126  	spl = splsched();
 127  	waitq_lock(waitq);
 128  
 129  	/* clear out startup condition (safe because thread not started yet) */
 130  	thread_lock(thread);
 131  	assert(!thread->started);
 132  	assert((thread->state & (TH_WAIT | TH_UNINT)) == (TH_WAIT | TH_UNINT));
 133  	thread->state &= ~(TH_WAIT | TH_UNINT);
 134  	thread_unlock(thread);
 135  
 136  	/* assert wait interruptibly forever */
 137  	wait_result = waitq_assert_wait64_locked(waitq, CAST_EVENT64_T(event),
 138  	    interruptible,
 139  	    TIMEOUT_URGENCY_SYS_NORMAL,
 140  	    TIMEOUT_WAIT_FOREVER,
 141  	    TIMEOUT_NO_LEEWAY,
 142  	    thread);
 143  	assert(wait_result == THREAD_WAITING);
 144  
 145  	/* mark thread started while we still hold the waitq lock */
 146  	thread_lock(thread);
 147  	thread->started = TRUE;
 148  	thread_unlock(thread);
 149  
 150  	waitq_unlock(waitq);
 151  	splx(spl);
 152  }
 153  
 154  /*
 155   * Internal routine to terminate a thread.
 156   * Sometimes called with task already locked.
 157   */
 158  kern_return_t
 159  thread_terminate_internal(
 160  	thread_t                        thread,
 161  	thread_terminate_options_t      options)
 162  {
 163  	kern_return_t           result = KERN_SUCCESS;
 164  	boolean_t               test_pin_bit = false;
 165  
 166  	thread_mtx_lock(thread);
 167  
 168  	if (thread->active) {
 169  		thread->active = FALSE;
 170  
 171  		act_abort(thread);
 172  
 173  		if (thread->started) {
 174  			clear_wait(thread, THREAD_INTERRUPTED);
 175  		} else {
 176  			thread_start(thread);
 177  		}
 178  		/* This bit can be reliably tested only if the thread is still active */
 179  		test_pin_bit = (options == TH_TERMINATE_OPTION_UNPIN) ? true : false;
 180  	} else {
 181  		result = KERN_TERMINATED;
 182  	}
 183  
 184  	if (thread->affinity_set != NULL) {
 185  		thread_affinity_terminate(thread);
 186  	}
 187  
 188  	/*
 189  	 * <rdar://problem/53562036> thread_terminate shouldn't be allowed on pthread
 190  	 * Until thread_terminate is disallowed for pthreads, always unpin the pinned port
 191  	 * when the thread is being terminated.
 192  	 */
 193  	ipc_thread_port_unpin(thread->ith_self, test_pin_bit);
 194  
 195  	thread_mtx_unlock(thread);
 196  
 197  	if (thread != current_thread() && result == KERN_SUCCESS) {
 198  		thread_wait(thread, FALSE);
 199  	}
 200  
 201  	return result;
 202  }
 203  
 204  /*
 205   * Terminate a thread.
 206   */
 207  kern_return_t
 208  thread_terminate(
 209  	thread_t                thread)
 210  {
 211  	if (thread == THREAD_NULL) {
 212  		return KERN_INVALID_ARGUMENT;
 213  	}
 214  
 215  	/* Kernel threads can't be terminated without their own cooperation */
 216  	if (thread->task == kernel_task && thread != current_thread()) {
 217  		return KERN_FAILURE;
 218  	}
 219  
 220  	kern_return_t result = thread_terminate_internal(thread, TH_TERMINATE_OPTION_NONE);
 221  
 222  	/*
 223  	 * If a kernel thread is terminating itself, force handle the APC_AST here.
 224  	 * Kernel threads don't pass through the return-to-user AST checking code,
 225  	 * but all threads must finish their own termination in thread_apc_ast.
 226  	 */
 227  	if (thread->task == kernel_task) {
 228  		assert(thread->active == FALSE);
 229  		thread_ast_clear(thread, AST_APC);
 230  		thread_apc_ast(thread);
 231  
 232  		panic("thread_terminate");
 233  		/* NOTREACHED */
 234  	}
 235  
 236  	return result;
 237  }
 238  
 239  kern_return_t
 240  thread_terminate_pinned(
 241  	thread_t                thread)
 242  {
 243  	if (thread == THREAD_NULL) {
 244  		return KERN_INVALID_ARGUMENT;
 245  	}
 246  
 247  	assert(thread->task != kernel_task);
 248  
 249  	kern_return_t result = thread_terminate_internal(thread, TH_TERMINATE_OPTION_UNPIN);
 250  	return result;
 251  }
 252  
 253  /*
 254   * Suspend execution of the specified thread.
 255   * This is a recursive-style suspension of the thread, a count of
 256   * suspends is maintained.
 257   *
 258   * Called with thread mutex held.
 259   */
 260  void
 261  thread_hold(thread_t thread)
 262  {
 263  	if (thread->suspend_count++ == 0) {
 264  		thread_set_apc_ast(thread);
 265  		assert(thread->suspend_parked == FALSE);
 266  	}
 267  }
 268  
 269  /*
 270   * Decrement internal suspension count, setting thread
 271   * runnable when count falls to zero.
 272   *
 273   * Because the wait is abortsafe, we can't be guaranteed that the thread
 274   * is currently actually waiting even if suspend_parked is set.
 275   *
 276   * Called with thread mutex held.
 277   */
 278  void
 279  thread_release(thread_t thread)
 280  {
 281  	assertf(thread->suspend_count > 0, "thread %p over-resumed", thread);
 282  
 283  	/* fail-safe on non-assert builds */
 284  	if (thread->suspend_count == 0) {
 285  		return;
 286  	}
 287  
 288  	if (--thread->suspend_count == 0) {
 289  		if (!thread->started) {
 290  			thread_start(thread);
 291  		} else if (thread->suspend_parked) {
 292  			thread->suspend_parked = FALSE;
 293  			thread_wakeup_thread(&thread->suspend_count, thread);
 294  		}
 295  	}
 296  }
 297  
 298  kern_return_t
 299  thread_suspend(thread_t thread)
 300  {
 301  	kern_return_t result = KERN_SUCCESS;
 302  
 303  	if (thread == THREAD_NULL || thread->task == kernel_task) {
 304  		return KERN_INVALID_ARGUMENT;
 305  	}
 306  
 307  	thread_mtx_lock(thread);
 308  
 309  	if (thread->active) {
 310  		if (thread->user_stop_count++ == 0) {
 311  			thread_hold(thread);
 312  		}
 313  	} else {
 314  		result = KERN_TERMINATED;
 315  	}
 316  
 317  	thread_mtx_unlock(thread);
 318  
 319  	if (thread != current_thread() && result == KERN_SUCCESS) {
 320  		thread_wait(thread, FALSE);
 321  	}
 322  
 323  	return result;
 324  }
 325  
 326  kern_return_t
 327  thread_resume(thread_t thread)
 328  {
 329  	kern_return_t result = KERN_SUCCESS;
 330  
 331  	if (thread == THREAD_NULL || thread->task == kernel_task) {
 332  		return KERN_INVALID_ARGUMENT;
 333  	}
 334  
 335  	thread_mtx_lock(thread);
 336  
 337  	if (thread->active) {
 338  		if (thread->user_stop_count > 0) {
 339  			if (--thread->user_stop_count == 0) {
 340  				thread_release(thread);
 341  			}
 342  		} else {
 343  			result = KERN_FAILURE;
 344  		}
 345  	} else {
 346  		result = KERN_TERMINATED;
 347  	}
 348  
 349  	thread_mtx_unlock(thread);
 350  
 351  	return result;
 352  }
 353  
 354  /*
 355   *	thread_depress_abort_from_user:
 356   *
 357   *	Prematurely abort priority depression if there is one.
 358   */
 359  kern_return_t
 360  thread_depress_abort_from_user(thread_t thread)
 361  {
 362  	kern_return_t result;
 363  
 364  	if (thread == THREAD_NULL) {
 365  		return KERN_INVALID_ARGUMENT;
 366  	}
 367  
 368  	thread_mtx_lock(thread);
 369  
 370  	if (thread->active) {
 371  		result = thread_depress_abort(thread);
 372  	} else {
 373  		result = KERN_TERMINATED;
 374  	}
 375  
 376  	thread_mtx_unlock(thread);
 377  
 378  	return result;
 379  }
 380  
 381  
 382  /*
 383   * Indicate that the thread should run the AST_APC callback
 384   * to detect an abort condition.
 385   *
 386   * Called with thread mutex held.
 387   */
 388  static void
 389  act_abort(
 390  	thread_t        thread)
 391  {
 392  	spl_t           s = splsched();
 393  
 394  	thread_lock(thread);
 395  
 396  	if (!(thread->sched_flags & TH_SFLAG_ABORT)) {
 397  		thread->sched_flags |= TH_SFLAG_ABORT;
 398  		thread_set_apc_ast_locked(thread);
 399  		thread_depress_abort_locked(thread);
 400  	} else {
 401  		thread->sched_flags &= ~TH_SFLAG_ABORTSAFELY;
 402  	}
 403  
 404  	thread_unlock(thread);
 405  	splx(s);
 406  }
 407  
 408  kern_return_t
 409  thread_abort(
 410  	thread_t        thread)
 411  {
 412  	kern_return_t   result = KERN_SUCCESS;
 413  
 414  	if (thread == THREAD_NULL) {
 415  		return KERN_INVALID_ARGUMENT;
 416  	}
 417  
 418  	thread_mtx_lock(thread);
 419  
 420  	if (thread->active) {
 421  		act_abort(thread);
 422  		clear_wait(thread, THREAD_INTERRUPTED);
 423  	} else {
 424  		result = KERN_TERMINATED;
 425  	}
 426  
 427  	thread_mtx_unlock(thread);
 428  
 429  	return result;
 430  }
 431  
 432  kern_return_t
 433  thread_abort_safely(
 434  	thread_t                thread)
 435  {
 436  	kern_return_t   result = KERN_SUCCESS;
 437  
 438  	if (thread == THREAD_NULL) {
 439  		return KERN_INVALID_ARGUMENT;
 440  	}
 441  
 442  	thread_mtx_lock(thread);
 443  
 444  	if (thread->active) {
 445  		spl_t           s = splsched();
 446  
 447  		thread_lock(thread);
 448  		if (!thread->at_safe_point ||
 449  		    clear_wait_internal(thread, THREAD_INTERRUPTED) != KERN_SUCCESS) {
 450  			if (!(thread->sched_flags & TH_SFLAG_ABORT)) {
 451  				thread->sched_flags |= TH_SFLAG_ABORTED_MASK;
 452  				thread_set_apc_ast_locked(thread);
 453  				thread_depress_abort_locked(thread);
 454  			}
 455  		}
 456  		thread_unlock(thread);
 457  		splx(s);
 458  	} else {
 459  		result = KERN_TERMINATED;
 460  	}
 461  
 462  	thread_mtx_unlock(thread);
 463  
 464  	return result;
 465  }
 466  
 467  /*** backward compatibility hacks ***/
 468  #include <mach/thread_info.h>
 469  #include <mach/thread_special_ports.h>
 470  #include <ipc/ipc_port.h>
 471  
 472  kern_return_t
 473  thread_info(
 474  	thread_t                        thread,
 475  	thread_flavor_t                 flavor,
 476  	thread_info_t                   thread_info_out,
 477  	mach_msg_type_number_t  *thread_info_count)
 478  {
 479  	kern_return_t                   result;
 480  
 481  	if (thread == THREAD_NULL) {
 482  		return KERN_INVALID_ARGUMENT;
 483  	}
 484  
 485  	thread_mtx_lock(thread);
 486  
 487  	if (thread->active || thread->inspection) {
 488  		result = thread_info_internal(
 489  			thread, flavor, thread_info_out, thread_info_count);
 490  	} else {
 491  		result = KERN_TERMINATED;
 492  	}
 493  
 494  	thread_mtx_unlock(thread);
 495  
 496  	return result;
 497  }
 498  
 499  static inline kern_return_t
 500  thread_get_state_internal(
 501  	thread_t                thread,
 502  	int                                             flavor,
 503  	thread_state_t                  state,                  /* pointer to OUT array */
 504  	mach_msg_type_number_t  *state_count,   /*IN/OUT*/
 505  	boolean_t                               to_user)
 506  {
 507  	kern_return_t           result = KERN_SUCCESS;
 508  
 509  	if (thread == THREAD_NULL) {
 510  		return KERN_INVALID_ARGUMENT;
 511  	}
 512  
 513  	thread_mtx_lock(thread);
 514  
 515  	if (thread->active) {
 516  		if (thread != current_thread()) {
 517  			thread_hold(thread);
 518  
 519  			thread_mtx_unlock(thread);
 520  
 521  			if (thread_stop(thread, FALSE)) {
 522  				thread_mtx_lock(thread);
 523  				result = machine_thread_get_state(
 524  					thread, flavor, state, state_count);
 525  				thread_unstop(thread);
 526  			} else {
 527  				thread_mtx_lock(thread);
 528  				result = KERN_ABORTED;
 529  			}
 530  
 531  			thread_release(thread);
 532  		} else {
 533  			result = machine_thread_get_state(
 534  				thread, flavor, state, state_count);
 535  		}
 536  	} else if (thread->inspection) {
 537  		result = machine_thread_get_state(
 538  			thread, flavor, state, state_count);
 539  	} else {
 540  		result = KERN_TERMINATED;
 541  	}
 542  
 543  	if (to_user && result == KERN_SUCCESS) {
 544  		result = machine_thread_state_convert_to_user(thread, flavor, state,
 545  		    state_count);
 546  	}
 547  
 548  	thread_mtx_unlock(thread);
 549  
 550  	return result;
 551  }
 552  
 553  /* No prototype, since thread_act_server.h has the _to_user version if KERNEL_SERVER */
 554  
 555  kern_return_t
 556  thread_get_state(
 557  	thread_t                thread,
 558  	int                                             flavor,
 559  	thread_state_t                  state,
 560  	mach_msg_type_number_t  *state_count);
 561  
 562  kern_return_t
 563  thread_get_state(
 564  	thread_t                thread,
 565  	int                                             flavor,
 566  	thread_state_t                  state,                  /* pointer to OUT array */
 567  	mach_msg_type_number_t  *state_count)   /*IN/OUT*/
 568  {
 569  	return thread_get_state_internal(thread, flavor, state, state_count, FALSE);
 570  }
 571  
 572  kern_return_t
 573  thread_get_state_to_user(
 574  	thread_t                thread,
 575  	int                                             flavor,
 576  	thread_state_t                  state,                  /* pointer to OUT array */
 577  	mach_msg_type_number_t  *state_count)   /*IN/OUT*/
 578  {
 579  	return thread_get_state_internal(thread, flavor, state, state_count, TRUE);
 580  }
 581  
 582  /*
 583   *	Change thread's machine-dependent state.  Called with nothing
 584   *	locked.  Returns same way.
 585   */
 586  static inline kern_return_t
 587  thread_set_state_internal(
 588  	thread_t                thread,
 589  	int                                             flavor,
 590  	thread_state_t                  state,
 591  	mach_msg_type_number_t  state_count,
 592  	boolean_t                               from_user)
 593  {
 594  	kern_return_t           result = KERN_SUCCESS;
 595  
 596  	if (thread == THREAD_NULL) {
 597  		return KERN_INVALID_ARGUMENT;
 598  	}
 599  
 600  	thread_mtx_lock(thread);
 601  
 602  	if (thread->active) {
 603  		if (from_user) {
 604  			result = machine_thread_state_convert_from_user(thread, flavor,
 605  			    state, state_count);
 606  			if (result != KERN_SUCCESS) {
 607  				goto out;
 608  			}
 609  		}
 610  		if (thread != current_thread()) {
 611  			thread_hold(thread);
 612  
 613  			thread_mtx_unlock(thread);
 614  
 615  			if (thread_stop(thread, TRUE)) {
 616  				thread_mtx_lock(thread);
 617  				result = machine_thread_set_state(
 618  					thread, flavor, state, state_count);
 619  				thread_unstop(thread);
 620  			} else {
 621  				thread_mtx_lock(thread);
 622  				result = KERN_ABORTED;
 623  			}
 624  
 625  			thread_release(thread);
 626  		} else {
 627  			result = machine_thread_set_state(
 628  				thread, flavor, state, state_count);
 629  		}
 630  	} else {
 631  		result = KERN_TERMINATED;
 632  	}
 633  
 634  	if ((result == KERN_SUCCESS) && from_user) {
 635  		extmod_statistics_incr_thread_set_state(thread);
 636  	}
 637  
 638  out:
 639  	thread_mtx_unlock(thread);
 640  
 641  	return result;
 642  }
 643  
 644  /* No prototype, since thread_act_server.h has the _from_user version if KERNEL_SERVER */
 645  kern_return_t
 646  thread_set_state(
 647  	thread_t                thread,
 648  	int                                             flavor,
 649  	thread_state_t                  state,
 650  	mach_msg_type_number_t  state_count);
 651  
 652  kern_return_t
 653  thread_set_state(
 654  	thread_t                thread,
 655  	int                                             flavor,
 656  	thread_state_t                  state,
 657  	mach_msg_type_number_t  state_count)
 658  {
 659  	return thread_set_state_internal(thread, flavor, state, state_count, FALSE);
 660  }
 661  
 662  kern_return_t
 663  thread_set_state_from_user(
 664  	thread_t                thread,
 665  	int                                             flavor,
 666  	thread_state_t                  state,
 667  	mach_msg_type_number_t  state_count)
 668  {
 669  	return thread_set_state_internal(thread, flavor, state, state_count, TRUE);
 670  }
 671  
 672  kern_return_t
 673  thread_convert_thread_state(
 674  	thread_t                thread,
 675  	int                     direction,
 676  	thread_state_flavor_t   flavor,
 677  	thread_state_t          in_state,          /* pointer to IN array */
 678  	mach_msg_type_number_t  in_state_count,
 679  	thread_state_t          out_state,         /* pointer to OUT array */
 680  	mach_msg_type_number_t  *out_state_count)   /*IN/OUT*/
 681  {
 682  	kern_return_t kr;
 683  	thread_t to_thread = THREAD_NULL;
 684  	thread_t from_thread = THREAD_NULL;
 685  	mach_msg_type_number_t state_count = in_state_count;
 686  
 687  	if (direction != THREAD_CONVERT_THREAD_STATE_TO_SELF &&
 688  	    direction != THREAD_CONVERT_THREAD_STATE_FROM_SELF) {
 689  		return KERN_INVALID_ARGUMENT;
 690  	}
 691  
 692  	if (thread == THREAD_NULL) {
 693  		return KERN_INVALID_ARGUMENT;
 694  	}
 695  
 696  	if (state_count > *out_state_count) {
 697  		return KERN_INSUFFICIENT_BUFFER_SIZE;
 698  	}
 699  
 700  	if (direction == THREAD_CONVERT_THREAD_STATE_FROM_SELF) {
 701  		to_thread = thread;
 702  		from_thread = current_thread();
 703  	} else {
 704  		to_thread = current_thread();
 705  		from_thread = thread;
 706  	}
 707  
 708  	/* Authenticate and convert thread state to kernel representation */
 709  	kr = machine_thread_state_convert_from_user(from_thread, flavor,
 710  	    in_state, state_count);
 711  
 712  	/* Return early if one of the thread was jop disabled while other wasn't */
 713  	if (kr != KERN_SUCCESS) {
 714  		return kr;
 715  	}
 716  
 717  	/* Convert thread state to target thread user representation */
 718  	kr = machine_thread_state_convert_to_user(to_thread, flavor,
 719  	    in_state, &state_count);
 720  
 721  	if (kr == KERN_SUCCESS) {
 722  		if (state_count <= *out_state_count) {
 723  			memcpy(out_state, in_state, state_count * sizeof(uint32_t));
 724  			*out_state_count = state_count;
 725  		} else {
 726  			kr = KERN_INSUFFICIENT_BUFFER_SIZE;
 727  		}
 728  	}
 729  
 730  	return kr;
 731  }
 732  
 733  /*
 734   * Kernel-internal "thread" interfaces used outside this file:
 735   */
 736  
 737  /* Initialize (or re-initialize) a thread state.  Called from execve
 738   * with nothing locked, returns same way.
 739   */
 740  kern_return_t
 741  thread_state_initialize(
 742  	thread_t                thread)
 743  {
 744  	kern_return_t           result = KERN_SUCCESS;
 745  
 746  	if (thread == THREAD_NULL) {
 747  		return KERN_INVALID_ARGUMENT;
 748  	}
 749  
 750  	thread_mtx_lock(thread);
 751  
 752  	if (thread->active) {
 753  		if (thread != current_thread()) {
 754  			thread_hold(thread);
 755  
 756  			thread_mtx_unlock(thread);
 757  
 758  			if (thread_stop(thread, TRUE)) {
 759  				thread_mtx_lock(thread);
 760  				result = machine_thread_state_initialize( thread );
 761  				thread_unstop(thread);
 762  			} else {
 763  				thread_mtx_lock(thread);
 764  				result = KERN_ABORTED;
 765  			}
 766  
 767  			thread_release(thread);
 768  		} else {
 769  			result = machine_thread_state_initialize( thread );
 770  		}
 771  	} else {
 772  		result = KERN_TERMINATED;
 773  	}
 774  
 775  	thread_mtx_unlock(thread);
 776  
 777  	return result;
 778  }
 779  
 780  kern_return_t
 781  thread_dup(
 782  	thread_t        target)
 783  {
 784  	thread_t                        self = current_thread();
 785  	kern_return_t           result = KERN_SUCCESS;
 786  
 787  	if (target == THREAD_NULL || target == self) {
 788  		return KERN_INVALID_ARGUMENT;
 789  	}
 790  
 791  	thread_mtx_lock(target);
 792  
 793  	if (target->active) {
 794  		thread_hold(target);
 795  
 796  		thread_mtx_unlock(target);
 797  
 798  		if (thread_stop(target, TRUE)) {
 799  			thread_mtx_lock(target);
 800  			result = machine_thread_dup(self, target, FALSE);
 801  
 802  			if (self->affinity_set != AFFINITY_SET_NULL) {
 803  				thread_affinity_dup(self, target);
 804  			}
 805  			thread_unstop(target);
 806  		} else {
 807  			thread_mtx_lock(target);
 808  			result = KERN_ABORTED;
 809  		}
 810  
 811  		thread_release(target);
 812  	} else {
 813  		result = KERN_TERMINATED;
 814  	}
 815  
 816  	thread_mtx_unlock(target);
 817  
 818  	return result;
 819  }
 820  
 821  
 822  kern_return_t
 823  thread_dup2(
 824  	thread_t        source,
 825  	thread_t        target)
 826  {
 827  	kern_return_t           result = KERN_SUCCESS;
 828  	uint32_t                active = 0;
 829  
 830  	if (source == THREAD_NULL || target == THREAD_NULL || target == source) {
 831  		return KERN_INVALID_ARGUMENT;
 832  	}
 833  
 834  	thread_mtx_lock(source);
 835  	active = source->active;
 836  	thread_mtx_unlock(source);
 837  
 838  	if (!active) {
 839  		return KERN_TERMINATED;
 840  	}
 841  
 842  	thread_mtx_lock(target);
 843  
 844  	if (target->active || target->inspection) {
 845  		thread_hold(target);
 846  
 847  		thread_mtx_unlock(target);
 848  
 849  		if (thread_stop(target, TRUE)) {
 850  			thread_mtx_lock(target);
 851  			result = machine_thread_dup(source, target, TRUE);
 852  			if (source->affinity_set != AFFINITY_SET_NULL) {
 853  				thread_affinity_dup(source, target);
 854  			}
 855  			thread_unstop(target);
 856  		} else {
 857  			thread_mtx_lock(target);
 858  			result = KERN_ABORTED;
 859  		}
 860  
 861  		thread_release(target);
 862  	} else {
 863  		result = KERN_TERMINATED;
 864  	}
 865  
 866  	thread_mtx_unlock(target);
 867  
 868  	return result;
 869  }
 870  
 871  /*
 872   *	thread_setstatus:
 873   *
 874   *	Set the status of the specified thread.
 875   *	Called with (and returns with) no locks held.
 876   */
 877  kern_return_t
 878  thread_setstatus(
 879  	thread_t                thread,
 880  	int                                             flavor,
 881  	thread_state_t                  tstate,
 882  	mach_msg_type_number_t  count)
 883  {
 884  	return thread_set_state(thread, flavor, tstate, count);
 885  }
 886  
 887  kern_return_t
 888  thread_setstatus_from_user(
 889  	thread_t                thread,
 890  	int                                             flavor,
 891  	thread_state_t                  tstate,
 892  	mach_msg_type_number_t  count)
 893  {
 894  	return thread_set_state_from_user(thread, flavor, tstate, count);
 895  }
 896  
 897  /*
 898   *	thread_getstatus:
 899   *
 900   *	Get the status of the specified thread.
 901   */
 902  kern_return_t
 903  thread_getstatus(
 904  	thread_t                thread,
 905  	int                                             flavor,
 906  	thread_state_t                  tstate,
 907  	mach_msg_type_number_t  *count)
 908  {
 909  	return thread_get_state(thread, flavor, tstate, count);
 910  }
 911  
 912  kern_return_t
 913  thread_getstatus_to_user(
 914  	thread_t                thread,
 915  	int                                             flavor,
 916  	thread_state_t                  tstate,
 917  	mach_msg_type_number_t  *count)
 918  {
 919  	return thread_get_state_to_user(thread, flavor, tstate, count);
 920  }
 921  
 922  /*
 923   *	Change thread's machine-dependent userspace TSD base.
 924   *  Called with nothing locked.  Returns same way.
 925   */
 926  kern_return_t
 927  thread_set_tsd_base(
 928  	thread_t                        thread,
 929  	mach_vm_offset_t        tsd_base)
 930  {
 931  	kern_return_t           result = KERN_SUCCESS;
 932  
 933  	if (thread == THREAD_NULL) {
 934  		return KERN_INVALID_ARGUMENT;
 935  	}
 936  
 937  	thread_mtx_lock(thread);
 938  
 939  	if (thread->active) {
 940  		if (thread != current_thread()) {
 941  			thread_hold(thread);
 942  
 943  			thread_mtx_unlock(thread);
 944  
 945  			if (thread_stop(thread, TRUE)) {
 946  				thread_mtx_lock(thread);
 947  				result = machine_thread_set_tsd_base(thread, tsd_base);
 948  				thread_unstop(thread);
 949  			} else {
 950  				thread_mtx_lock(thread);
 951  				result = KERN_ABORTED;
 952  			}
 953  
 954  			thread_release(thread);
 955  		} else {
 956  			result = machine_thread_set_tsd_base(thread, tsd_base);
 957  		}
 958  	} else {
 959  		result = KERN_TERMINATED;
 960  	}
 961  
 962  	thread_mtx_unlock(thread);
 963  
 964  	return result;
 965  }
 966  
 967  /*
 968   * thread_set_apc_ast:
 969   *
 970   * Register the AST_APC callback that handles suspension and
 971   * termination, if it hasn't been installed already.
 972   *
 973   * Called with the thread mutex held.
 974   */
 975  static void
 976  thread_set_apc_ast(thread_t thread)
 977  {
 978  	spl_t s = splsched();
 979  
 980  	thread_lock(thread);
 981  	thread_set_apc_ast_locked(thread);
 982  	thread_unlock(thread);
 983  
 984  	splx(s);
 985  }
 986  
 987  /*
 988   * thread_set_apc_ast_locked:
 989   *
 990   * Do the work of registering for the AST_APC callback.
 991   *
 992   * Called with the thread mutex and scheduling lock held.
 993   */
 994  static void
 995  thread_set_apc_ast_locked(thread_t thread)
 996  {
 997  	thread_ast_set(thread, AST_APC);
 998  
 999  	if (thread == current_thread()) {
1000  		ast_propagate(thread);
1001  	} else {
1002  		processor_t processor = thread->last_processor;
1003  
1004  		if (processor != PROCESSOR_NULL &&
1005  		    processor->state == PROCESSOR_RUNNING &&
1006  		    processor->active_thread == thread) {
1007  			cause_ast_check(processor);
1008  		}
1009  	}
1010  }
1011  
1012  /*
1013   * Activation control support routines internal to this file:
1014   *
1015   */
1016  
1017  /*
1018   * thread_suspended
1019   *
1020   * Continuation routine for thread suspension.  It checks
1021   * to see whether there has been any new suspensions.  If so, it
1022   * installs the AST_APC handler again.
1023   */
1024  __attribute__((noreturn))
1025  static void
1026  thread_suspended(__unused void *parameter, wait_result_t result)
1027  {
1028  	thread_t thread = current_thread();
1029  
1030  	thread_mtx_lock(thread);
1031  
1032  	if (result == THREAD_INTERRUPTED) {
1033  		thread->suspend_parked = FALSE;
1034  	} else {
1035  		assert(thread->suspend_parked == FALSE);
1036  	}
1037  
1038  	if (thread->suspend_count > 0) {
1039  		thread_set_apc_ast(thread);
1040  	}
1041  
1042  	thread_mtx_unlock(thread);
1043  
1044  	thread_exception_return();
1045  	/*NOTREACHED*/
1046  }
1047  
1048  /*
1049   * thread_apc_ast - handles AST_APC and drives thread suspension and termination.
1050   * Called with nothing locked.  Returns (if it returns) the same way.
1051   */
1052  void
1053  thread_apc_ast(thread_t thread)
1054  {
1055  	thread_mtx_lock(thread);
1056  
1057  	assert(thread->suspend_parked == FALSE);
1058  
1059  	spl_t s = splsched();
1060  	thread_lock(thread);
1061  
1062  	/* TH_SFLAG_POLLDEPRESS is OK to have here */
1063  	assert((thread->sched_flags & TH_SFLAG_DEPRESS) == 0);
1064  
1065  	thread->sched_flags &= ~TH_SFLAG_ABORTED_MASK;
1066  	thread_unlock(thread);
1067  	splx(s);
1068  
1069  	if (!thread->active) {
1070  		/* Thread is ready to terminate, time to tear it down */
1071  		thread_mtx_unlock(thread);
1072  
1073  		thread_terminate_self();
1074  		/*NOTREACHED*/
1075  	}
1076  
1077  	/* If we're suspended, go to sleep and wait for someone to wake us up. */
1078  	if (thread->suspend_count > 0) {
1079  		thread->suspend_parked = TRUE;
1080  		assert_wait(&thread->suspend_count,
1081  		    THREAD_ABORTSAFE | THREAD_WAIT_NOREPORT_USER);
1082  		thread_mtx_unlock(thread);
1083  
1084  		thread_block(thread_suspended);
1085  		/*NOTREACHED*/
1086  	}
1087  
1088  	thread_mtx_unlock(thread);
1089  }
1090  
1091  
1092  /* Prototype, see justification above */
1093  kern_return_t
1094  act_set_state(
1095  	thread_t                                thread,
1096  	int                                             flavor,
1097  	thread_state_t                  state,
1098  	mach_msg_type_number_t  count);
1099  
1100  kern_return_t
1101  act_set_state(
1102  	thread_t                                thread,
1103  	int                                             flavor,
1104  	thread_state_t                  state,
1105  	mach_msg_type_number_t  count)
1106  {
1107  	if (thread == current_thread()) {
1108  		return KERN_INVALID_ARGUMENT;
1109  	}
1110  
1111  	return thread_set_state(thread, flavor, state, count);
1112  }
1113  
1114  kern_return_t
1115  act_set_state_from_user(
1116  	thread_t                                thread,
1117  	int                                             flavor,
1118  	thread_state_t                  state,
1119  	mach_msg_type_number_t  count)
1120  {
1121  	if (thread == current_thread()) {
1122  		return KERN_INVALID_ARGUMENT;
1123  	}
1124  
1125  	return thread_set_state_from_user(thread, flavor, state, count);
1126  }
1127  
1128  /* Prototype, see justification above */
1129  kern_return_t
1130  act_get_state(
1131  	thread_t                                thread,
1132  	int                                             flavor,
1133  	thread_state_t                  state,
1134  	mach_msg_type_number_t  *count);
1135  
1136  kern_return_t
1137  act_get_state(
1138  	thread_t                                thread,
1139  	int                                             flavor,
1140  	thread_state_t                  state,
1141  	mach_msg_type_number_t  *count)
1142  {
1143  	if (thread == current_thread()) {
1144  		return KERN_INVALID_ARGUMENT;
1145  	}
1146  
1147  	return thread_get_state(thread, flavor, state, count);
1148  }
1149  
1150  kern_return_t
1151  act_get_state_to_user(
1152  	thread_t                                thread,
1153  	int                                             flavor,
1154  	thread_state_t                  state,
1155  	mach_msg_type_number_t  *count)
1156  {
1157  	if (thread == current_thread()) {
1158  		return KERN_INVALID_ARGUMENT;
1159  	}
1160  
1161  	return thread_get_state_to_user(thread, flavor, state, count);
1162  }
1163  
1164  static void
1165  act_set_ast(
1166  	thread_t thread,
1167  	ast_t ast)
1168  {
1169  	spl_t s = splsched();
1170  
1171  	if (thread == current_thread()) {
1172  		thread_ast_set(thread, ast);
1173  		ast_propagate(thread);
1174  	} else {
1175  		processor_t processor;
1176  
1177  		thread_lock(thread);
1178  		thread_ast_set(thread, ast);
1179  		processor = thread->last_processor;
1180  		if (processor != PROCESSOR_NULL &&
1181  		    processor->state == PROCESSOR_RUNNING &&
1182  		    processor->active_thread == thread) {
1183  			cause_ast_check(processor);
1184  		}
1185  		thread_unlock(thread);
1186  	}
1187  
1188  	splx(s);
1189  }
1190  
1191  /*
1192   * set AST on thread without causing an AST check
1193   * and without taking the thread lock
1194   *
1195   * If thread is not the current thread, then it may take
1196   * up until the next context switch or quantum expiration
1197   * on that thread for it to notice the AST.
1198   */
1199  static void
1200  act_set_ast_async(thread_t  thread,
1201      ast_t     ast)
1202  {
1203  	thread_ast_set(thread, ast);
1204  
1205  	if (thread == current_thread()) {
1206  		spl_t s = splsched();
1207  		ast_propagate(thread);
1208  		splx(s);
1209  	}
1210  }
1211  
1212  void
1213  act_set_astbsd(
1214  	thread_t        thread)
1215  {
1216  	act_set_ast( thread, AST_BSD );
1217  }
1218  
1219  void
1220  act_set_astkevent(thread_t thread, uint16_t bits)
1221  {
1222  	os_atomic_or(&thread->kevent_ast_bits, bits, relaxed);
1223  
1224  	/* kevent AST shouldn't send immediate IPIs */
1225  	act_set_ast_async(thread, AST_KEVENT);
1226  }
1227  
1228  uint16_t
1229  act_clear_astkevent(thread_t thread, uint16_t bits)
1230  {
1231  	/*
1232  	 * avoid the atomic operation if none of the bits is set,
1233  	 * which will be the common case.
1234  	 */
1235  	uint16_t cur = os_atomic_load(&thread->kevent_ast_bits, relaxed);
1236  	if (cur & bits) {
1237  		cur = os_atomic_andnot_orig(&thread->kevent_ast_bits, bits, relaxed);
1238  	}
1239  	return cur & bits;
1240  }
1241  
1242  void
1243  act_set_ast_reset_pcs(thread_t thread)
1244  {
1245  	act_set_ast(thread, AST_RESET_PCS);
1246  }
1247  
1248  void
1249  act_set_kperf(
1250  	thread_t        thread)
1251  {
1252  	/* safety check */
1253  	if (thread != current_thread()) {
1254  		if (!ml_get_interrupts_enabled()) {
1255  			panic("unsafe act_set_kperf operation");
1256  		}
1257  	}
1258  
1259  	act_set_ast( thread, AST_KPERF );
1260  }
1261  
1262  #if CONFIG_MACF
1263  void
1264  act_set_astmacf(
1265  	thread_t        thread)
1266  {
1267  	act_set_ast( thread, AST_MACF);
1268  }
1269  #endif
1270  
1271  void
1272  act_set_astledger(thread_t thread)
1273  {
1274  	act_set_ast(thread, AST_LEDGER);
1275  }
1276  
1277  /*
1278   * The ledger AST may need to be set while already holding
1279   * the thread lock.  This routine skips sending the IPI,
1280   * allowing us to avoid the lock hold.
1281   *
1282   * However, it means the targeted thread must context switch
1283   * to recognize the ledger AST.
1284   */
1285  void
1286  act_set_astledger_async(thread_t thread)
1287  {
1288  	act_set_ast_async(thread, AST_LEDGER);
1289  }
1290  
1291  void
1292  act_set_io_telemetry_ast(thread_t thread)
1293  {
1294  	act_set_ast(thread, AST_TELEMETRY_IO);
1295  }