2  * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   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. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  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. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29 #ifndef _SYS_PTHREAD_INTERNAL_H_ 
  30 #define _SYS_PTHREAD_INTERNAL_H_ 
  33 #include <kern/thread_call.h> 
  34 #include <sys/pthread_shims.h> 
  35 #include <sys/queue.h> 
  38 #include "kern/synch_internal.h" 
  39 #include "kern/workqueue_internal.h" 
  40 #include "kern/kern_trace.h" 
  41 #include "pthread/qos.h" 
  42 #include "private/qos_private.h" 
  44 /* pthread userspace SPI feature checking, these constants are returned from bsdthread_register, 
  45  * as a bitmask, to inform userspace of the supported feature set. Old releases of OS X return 
  46  * from this call either zero or -1, allowing us to return a positive number for feature bits. 
  48 #define PTHREAD_FEATURE_DISPATCHFUNC    0x01            /* same as WQOPS_QUEUE_NEWSPISUPP, checks for dispatch function support */ 
  49 #define PTHREAD_FEATURE_FINEPRIO                0x02            /* are fine grained prioirities available */ 
  50 #define PTHREAD_FEATURE_BSDTHREADCTL    0x04            /* is the bsdthread_ctl syscall available */ 
  51 #define PTHREAD_FEATURE_SETSELF                 0x08            /* is the BSDTHREAD_CTL_SET_SELF command of bsdthread_ctl available */ 
  52 #define PTHREAD_FEATURE_QOS_MAINTENANCE 0x10            /* is QOS_CLASS_MAINTENANCE available */ 
  53 #define PTHREAD_FEATURE_QOS_DEFAULT             0x40000000      /* the kernel supports QOS_CLASS_DEFAULT */ 
  55 /* pthread bsdthread_ctl sysctl commands */ 
  56 #define BSDTHREAD_CTL_SET_QOS   0x10    /* bsdthread_ctl(BSDTHREAD_CTL_SET_QOS, thread_port, tsd_entry_addr, 0) */ 
  57 #define BSDTHREAD_CTL_GET_QOS   0x20    /* bsdthread_ctl(BSDTHREAD_CTL_GET_QOS, thread_port, 0, 0) */ 
  58 #define BSDTHREAD_CTL_QOS_OVERRIDE_START        0x40    /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_START, thread_port, priority, 0) */ 
  59 #define BSDTHREAD_CTL_QOS_OVERRIDE_END          0x80    /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_END, thread_port, 0, 0) */ 
  60 #define BSDTHREAD_CTL_SET_SELF  0x100   /* bsdthread_ctl(BSDTHREAD_CTL_SET_SELF, priority, voucher, flags) */ 
  61 #define BSDTHREAD_CTL_QOS_OVERRIDE_RESET        0x200   /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_RESET, 0, 0, 0) */ 
  62 #define BSDTHREAD_CTL_QOS_OVERRIDE_DISPATCH     0x400   /* bsdthread_ctl(BSDTHREAD_CTL_QOS_OVERRIDE_DISPATCH, thread_port, priority, 0) */ 
  63 #define BSDTHREAD_CTL_QOS_DISPATCH_ASYNCHRONOUS_OVERRIDE_ADD    0x401   /* bsdthread_ctl(BSDTHREAD_CTL_QOS_DISPATCH_ASYNCHRONOUS_OVERRIDE_ADD, thread_port, priority, resource) */ 
  64 #define BSDTHREAD_CTL_QOS_DISPATCH_ASYNCHRONOUS_OVERRIDE_RESET  0x402   /* bsdthread_ctl(BSDTHREAD_CTL_QOS_DISPATCH_ASYNCHRONOUS_OVERRIDE_RESET, 0|1 (?reset_all), resource, 0) */ 
  66 /* qos_class_t is mapped into one of these bits in the bitfield, this mapping now exists here because 
  67  * libdispatch requires the QoS class mask of the pthread_priority_t to be a bitfield. 
  69 #define __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE 0x20 
  70 #define __PTHREAD_PRIORITY_CBIT_USER_INITIATED 0x10 
  71 #define __PTHREAD_PRIORITY_CBIT_DEFAULT 0x8 
  72 #define __PTHREAD_PRIORITY_CBIT_UTILITY 0x4 
  73 #define __PTHREAD_PRIORITY_CBIT_BACKGROUND 0x2 
  74 #define __PTHREAD_PRIORITY_CBIT_MAINTENANCE 0x1 
  75 #define __PTHREAD_PRIORITY_CBIT_UNSPECIFIED 0x0 
  77 /* Added support for QOS_CLASS_MAINTENANCE */ 
  78 static inline pthread_priority_t
 
  79 _pthread_priority_make_newest(qos_class_t qc
, int rel
, unsigned long flags
) 
  81         pthread_priority_t cls
; 
  83                 case QOS_CLASS_USER_INTERACTIVE
: cls 
= __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE
; break; 
  84                 case QOS_CLASS_USER_INITIATED
: cls 
= __PTHREAD_PRIORITY_CBIT_USER_INITIATED
; break; 
  85                 case QOS_CLASS_DEFAULT
: cls 
= __PTHREAD_PRIORITY_CBIT_DEFAULT
; break; 
  86                 case QOS_CLASS_UTILITY
: cls 
= __PTHREAD_PRIORITY_CBIT_UTILITY
; break; 
  87                 case QOS_CLASS_BACKGROUND
: cls 
= __PTHREAD_PRIORITY_CBIT_BACKGROUND
; break; 
  88                 case QOS_CLASS_MAINTENANCE
: cls 
= __PTHREAD_PRIORITY_CBIT_MAINTENANCE
; break; 
  89                 case QOS_CLASS_UNSPECIFIED
: 
  91                         cls 
= __PTHREAD_PRIORITY_CBIT_UNSPECIFIED
; 
  92                         rel 
= 1; // results in priority bits == 0 <rdar://problem/16184900> 
  96         pthread_priority_t p 
= 
  97                 (flags 
& _PTHREAD_PRIORITY_FLAGS_MASK
) | 
  98                 ((cls 
<< _PTHREAD_PRIORITY_QOS_CLASS_SHIFT
) & _PTHREAD_PRIORITY_QOS_CLASS_MASK
) | 
  99                 (((uint8_t)rel 
- 1) & _PTHREAD_PRIORITY_PRIORITY_MASK
); 
 104 /* Added support for QOS_CLASS_LEGACY and QOS_CLASS_INHERIT */ 
 105 static inline pthread_priority_t
 
 106 _pthread_priority_make_version2(qos_class_t qc
, int rel
, unsigned long flags
) 
 108         pthread_priority_t cls
; 
 110                 case QOS_CLASS_USER_INTERACTIVE
: cls 
= __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE
; break; 
 111                 case QOS_CLASS_USER_INITIATED
: cls 
= __PTHREAD_PRIORITY_CBIT_USER_INITIATED
; break; 
 112                 case QOS_CLASS_DEFAULT
: cls 
= __PTHREAD_PRIORITY_CBIT_DEFAULT
; break; 
 113                 case QOS_CLASS_UTILITY
: cls 
= __PTHREAD_PRIORITY_CBIT_UTILITY
; break; 
 114                 case QOS_CLASS_BACKGROUND
: cls 
= __PTHREAD_PRIORITY_CBIT_BACKGROUND
; break; 
 115                 case QOS_CLASS_UNSPECIFIED
: 
 117                         cls 
= __PTHREAD_PRIORITY_CBIT_UNSPECIFIED
; 
 118                         rel 
= 1; // results in priority bits == 0 <rdar://problem/16184900> 
 123          * __PTHREAD_PRIORITY_CBIT_MAINTENANCE was defined as the 0th bit by shifting all the 
 124          * existing bits to the left by one.  So for backward compatiblity for kernels that does 
 125          * not support QOS_CLASS_MAINTENANCE, we have to make it up by shifting the cls bit to 
 130         pthread_priority_t p 
= 
 131                 (flags 
& _PTHREAD_PRIORITY_FLAGS_MASK
) | 
 132                 ((cls 
<< _PTHREAD_PRIORITY_QOS_CLASS_SHIFT
) & _PTHREAD_PRIORITY_QOS_CLASS_MASK
) | 
 133                 (((uint8_t)rel 
- 1) & _PTHREAD_PRIORITY_PRIORITY_MASK
); 
 138 /* QOS_CLASS_MAINTENANCE is supported */ 
 139 static inline qos_class_t
 
 140 _pthread_priority_get_qos_newest(pthread_priority_t priority
) 
 143         switch ((priority 
& _PTHREAD_PRIORITY_QOS_CLASS_MASK
) >> _PTHREAD_PRIORITY_QOS_CLASS_SHIFT
) { 
 144                 case __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE
: qc 
= QOS_CLASS_USER_INTERACTIVE
; break; 
 145                 case __PTHREAD_PRIORITY_CBIT_USER_INITIATED
: qc 
= QOS_CLASS_USER_INITIATED
; break; 
 146                 case __PTHREAD_PRIORITY_CBIT_DEFAULT
: qc 
= QOS_CLASS_DEFAULT
; break; 
 147                 case __PTHREAD_PRIORITY_CBIT_UTILITY
: qc 
= QOS_CLASS_UTILITY
; break; 
 148                 case __PTHREAD_PRIORITY_CBIT_BACKGROUND
: qc 
= QOS_CLASS_BACKGROUND
; break; 
 149                 case __PTHREAD_PRIORITY_CBIT_MAINTENANCE
: qc 
= QOS_CLASS_MAINTENANCE
; break; 
 150                 case __PTHREAD_PRIORITY_CBIT_UNSPECIFIED
: 
 151                 default: qc 
= QOS_CLASS_UNSPECIFIED
; break; 
 156 /* QOS_CLASS_MAINTENANCE is not supported */ 
 157 static inline qos_class_t
 
 158 _pthread_priority_get_qos_version2(pthread_priority_t priority
) 
 161         pthread_priority_t cls
; 
 163         cls 
= (priority 
& _PTHREAD_PRIORITY_QOS_CLASS_MASK
) >> _PTHREAD_PRIORITY_QOS_CLASS_SHIFT
; 
 166          * __PTHREAD_PRIORITY_CBIT_MAINTENANCE was defined as the 0th bit by shifting all the 
 167          * existing bits to the left by one.  So for backward compatiblity for kernels that does 
 168          * not support QOS_CLASS_MAINTENANCE, pthread_priority_make() shifted the cls bit to the 
 169          * right by one.  Therefore we have to shift it back during decoding the priority bit. 
 174                 case __PTHREAD_PRIORITY_CBIT_USER_INTERACTIVE
: qc 
= QOS_CLASS_USER_INTERACTIVE
; break; 
 175                 case __PTHREAD_PRIORITY_CBIT_USER_INITIATED
: qc 
= QOS_CLASS_USER_INITIATED
; break; 
 176                 case __PTHREAD_PRIORITY_CBIT_DEFAULT
: qc 
= QOS_CLASS_DEFAULT
; break; 
 177                 case __PTHREAD_PRIORITY_CBIT_UTILITY
: qc 
= QOS_CLASS_UTILITY
; break; 
 178                 case __PTHREAD_PRIORITY_CBIT_BACKGROUND
: qc 
= QOS_CLASS_BACKGROUND
; break; 
 179                 case __PTHREAD_PRIORITY_CBIT_UNSPECIFIED
: 
 180                 default: qc 
= QOS_CLASS_UNSPECIFIED
; break; 
 185 #define _pthread_priority_get_relpri(priority) \ 
 186         ((int8_t)((priority & _PTHREAD_PRIORITY_PRIORITY_MASK) >> _PTHREAD_PRIORITY_PRIORITY_SHIFT) + 1) 
 188 #define _pthread_priority_get_flags(priority) \ 
 189         (priority & _PTHREAD_PRIORITY_FLAGS_MASK) 
 191 #define _pthread_priority_split_newest(priority, qos, relpri) \ 
 192         ({ qos = _pthread_priority_get_qos_newest(priority); \ 
 193            relpri = (qos == QOS_CLASS_UNSPECIFIED) ? 0 : \ 
 194                    _pthread_priority_get_relpri(priority); \ 
 197 #define _pthread_priority_split_version2(priority, qos, relpri) \ 
 198         ({ qos = _pthread_priority_get_qos_version2(priority); \ 
 199            relpri = (qos == QOS_CLASS_UNSPECIFIED) ? 0 : \ 
 200                    _pthread_priority_get_relpri(priority); \ 
 203 /* <rdar://problem/15969976> Required for backward compatibility on older kernels. */ 
 204 #define _pthread_priority_make_version1(qos, relpri, flags) \ 
 205         (((flags >> 15) & 0xffff0000) | \ 
 206         ((qos << 8) & 0x0000ff00) | \ 
 207         (((uint8_t)relpri - 1) & 0x000000ff)) 
 209 /* userspace <-> kernel registration struct, for passing data to/from the kext during main thread init. */ 
 210 struct _pthread_registration_data 
{ 
 211         uint64_t version
; /* copy-in */ 
 212         uint64_t dispatch_queue_offset
; /* copy-in */ 
 213         pthread_priority_t main_qos
; /* copy-out */ 
 218 /* The set of features, from the feature bits above, that we support. */ 
 219 #define PTHREAD_FEATURE_SUPPORTED       ( \ 
 220         PTHREAD_FEATURE_DISPATCHFUNC | \ 
 221         PTHREAD_FEATURE_FINEPRIO | \ 
 222         PTHREAD_FEATURE_BSDTHREADCTL | \ 
 223         PTHREAD_FEATURE_SETSELF | \ 
 224         PTHREAD_FEATURE_QOS_MAINTENANCE | \ 
 225         PTHREAD_FEATURE_QOS_DEFAULT) 
 227 extern pthread_callbacks_t pthread_kern
; 
 229 struct ksyn_waitq_element 
{ 
 230         TAILQ_ENTRY(ksyn_waitq_element
) kwe_list
;       /* link to other list members */ 
 231         void *          kwe_kwqqueue
;                   /* queue blocked on */ 
 232         uint32_t        kwe_state
;                      /* state */ 
 233         uint32_t        kwe_lockseq
;                    /* the sequence of the entry */ 
 234         uint32_t        kwe_count
;                      /* upper bound on number of matches still pending */ 
 235         uint32_t        kwe_psynchretval
;               /* thread retval */ 
 236         void            *kwe_uth
;                       /* uthread */ 
 237         uint64_t        kwe_tid
;                        /* tid of waiter */ 
 239 typedef struct ksyn_waitq_element 
* ksyn_waitq_element_t
; 
 241 pthread_priority_t 
pthread_qos_class_get_priority(int qos
); 
 242 int pthread_priority_get_qos_class(pthread_priority_t priority
); 
 243 int pthread_priority_get_class_index(pthread_priority_t priority
); 
 244 pthread_priority_t 
pthread_priority_from_class_index(int index
); 
 246 #define PTH_DEFAULT_STACKSIZE 512*1024 
 247 #define MAX_PTHREAD_SIZE 64*1024 
 249 /* exported from the kernel but not present in any headers. */ 
 250 extern thread_t 
port_name_to_thread(mach_port_name_t port_name
); 
 252 /* function declarations for pthread_kext.c */ 
 253 void pthread_init(void); 
 254 void psynch_zoneinit(void); 
 255 void _pth_proc_hashinit(proc_t p
); 
 256 void _pth_proc_hashdelete(proc_t p
); 
 257 void pth_global_hashinit(void); 
 258 void psynch_wq_cleanup(void*, void*); 
 260 void _pthread_init(void); 
 261 int _fill_procworkqueue(proc_t p
, struct proc_workqueueinfo 
* pwqinfo
); 
 262 void _workqueue_init_lock(proc_t p
); 
 263 void _workqueue_destroy_lock(proc_t p
); 
 264 void _workqueue_exit(struct proc 
*p
); 
 265 void _workqueue_mark_exiting(struct proc 
*p
); 
 266 void _workqueue_thread_yielded(void); 
 267 sched_call_t 
_workqueue_get_sched_callback(void); 
 269 int _bsdthread_create(struct proc 
*p
, user_addr_t user_func
, user_addr_t user_funcarg
, user_addr_t user_stack
, user_addr_t user_pthread
, uint32_t flags
, user_addr_t 
*retval
); 
 270 int _bsdthread_register(struct proc 
*p
, user_addr_t threadstart
, user_addr_t wqthread
, int pthsize
, user_addr_t dummy_value
, user_addr_t targetconc_ptr
, uint64_t dispatchqueue_offset
, int32_t *retval
); 
 271 int _bsdthread_terminate(struct proc 
*p
, user_addr_t stackaddr
, size_t size
, uint32_t kthport
, uint32_t sem
, int32_t *retval
); 
 272 int _bsdthread_ctl_set_qos(struct proc 
*p
, user_addr_t cmd
, mach_port_name_t kport
, user_addr_t tsd_priority_addr
, user_addr_t arg3
, int *retval
); 
 273 int _bsdthread_ctl_set_self(struct proc 
*p
, user_addr_t cmd
, pthread_priority_t priority
, mach_port_name_t voucher
, _pthread_set_flags_t flags
, int *retval
); 
 274 int _bsdthread_ctl_qos_override_start(struct proc 
*p
, user_addr_t cmd
, mach_port_name_t kport
, pthread_priority_t priority
, user_addr_t resource
, int *retval
); 
 275 int _bsdthread_ctl_qos_override_end(struct proc 
*p
, user_addr_t cmd
, mach_port_name_t kport
, user_addr_t resource
, user_addr_t arg3
, int *retval
); 
 276 int _bsdthread_ctl_qos_override_dispatch(struct proc __unused 
*p
, user_addr_t __unused cmd
, mach_port_name_t kport
, pthread_priority_t priority
, user_addr_t arg3
, int __unused 
*retval
); 
 277 int _bsdthread_ctl_qos_override_reset(struct proc __unused 
*p
, user_addr_t __unused cmd
, user_addr_t arg1
, user_addr_t arg2
, user_addr_t arg3
, int __unused 
*retval
); 
 278 int _bsdthread_ctl_qos_dispatch_asynchronous_override_add(struct proc __unused 
*p
, user_addr_t __unused cmd
, mach_port_name_t kport
, pthread_priority_t priority
, user_addr_t resource
, int __unused 
*retval
); 
 279 int _bsdthread_ctl_qos_dispatch_asynchronous_override_reset(struct proc __unused 
*p
, user_addr_t __unused cmd
, int reset_all
, user_addr_t resource
, user_addr_t arg3
, int __unused 
*retval
); 
 280 int _bsdthread_ctl(struct proc 
*p
, user_addr_t cmd
, user_addr_t arg1
, user_addr_t arg2
, user_addr_t arg3
, int *retval
); 
 281 int _thread_selfid(__unused 
struct proc 
*p
, uint64_t *retval
); 
 282 int _workq_kernreturn(struct proc 
*p
, int options
, user_addr_t item
, int arg2
, int arg3
, int32_t *retval
); 
 283 int _workq_open(struct proc 
*p
, int32_t *retval
); 
 285 int _psynch_mutexwait(proc_t p
, user_addr_t mutex
,  uint32_t mgen
, uint32_t  ugen
, uint64_t tid
, uint32_t flags
, uint32_t * retval
); 
 286 int _psynch_mutexdrop(proc_t p
, user_addr_t mutex
,  uint32_t mgen
, uint32_t  ugen
, uint64_t tid
, uint32_t flags
, uint32_t * retval
); 
 287 int _psynch_cvbroad(proc_t p
, user_addr_t cv
, uint64_t cvlsgen
, uint64_t cvudgen
, uint32_t flags
, user_addr_t mutex
,  uint64_t mugen
, uint64_t tid
, uint32_t *retval
); 
 288 int _psynch_cvsignal(proc_t p
, user_addr_t cv
, uint64_t cvlsgen
, uint32_t cvugen
, int thread_port
, user_addr_t mutex
,  uint64_t mugen
, uint64_t tid
, uint32_t flags
, uint32_t * retval
); 
 289 int _psynch_cvwait(proc_t p
, user_addr_t cv
, uint64_t cvlsgen
, uint32_t cvugen
, user_addr_t mutex
,  uint64_t mugen
, uint32_t flags
, int64_t sec
, uint32_t nsec
, uint32_t * retval
); 
 290 int _psynch_cvclrprepost(proc_t p
, user_addr_t cv
, uint32_t cvgen
, uint32_t cvugen
, uint32_t cvsgen
, uint32_t prepocnt
, uint32_t preposeq
, uint32_t flags
, int *retval
); 
 291 int _psynch_rw_longrdlock(proc_t p
, user_addr_t rwlock
, uint32_t lgenval
, uint32_t ugenval
, uint32_t rw_wc
, int flags
, uint32_t * retval
); 
 292 int _psynch_rw_rdlock(proc_t p
, user_addr_t rwlock
, uint32_t lgenval
, uint32_t ugenval
, uint32_t rw_wc
, int flags
, uint32_t *retval
); 
 293 int _psynch_rw_unlock(proc_t p
, user_addr_t rwlock
, uint32_t lgenval
, uint32_t ugenval
, uint32_t rw_wc
, int flags
, uint32_t *retval
); 
 294 int _psynch_rw_wrlock(proc_t p
, user_addr_t rwlock
, uint32_t lgenval
, uint32_t ugenval
, uint32_t rw_wc
, int flags
, uint32_t *retval
); 
 295 int _psynch_rw_yieldwrlock(proc_t p
, user_addr_t rwlock
, uint32_t lgenval
, uint32_t ugenval
, uint32_t rw_wc
, int flags
, uint32_t *retval
); 
 297 extern lck_grp_attr_t 
*pthread_lck_grp_attr
; 
 298 extern lck_grp_t 
*pthread_lck_grp
; 
 299 extern lck_attr_t 
*pthread_lck_attr
; 
 300 extern lck_mtx_t 
*pthread_list_mlock
; 
 301 extern thread_call_t psynch_thcall
; 
 303 struct uthread
* current_uthread(void); 
 307 #endif /* _SYS_PTHREAD_INTERNAL_H_ */