/ duct-tape / pthread / synch_internal.h
synch_internal.h
  1  /*
  2   * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  3   *
  4   * @APPLE_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. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   *
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   *
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  #ifndef __SYNCH_INTERNAL_H__
 25  #define __SYNCH_INTERNAL_H__
 26  
 27  // kwe_state
 28  enum {
 29  	KWE_THREAD_INWAIT = 1,
 30  	KWE_THREAD_PREPOST,
 31  	KWE_THREAD_BROADCAST,
 32  };
 33  
 34  #define _PTHREAD_MTX_OPT_PSHARED 0x010
 35  #define _PTHREAD_MTX_OPT_NOTIFY 0x1000	/* notify to drop mutex handling in cvwait */
 36  #define _PTHREAD_MTX_OPT_MUTEX	0x2000 /* this is a mutex type  */
 37  
 38  
 39  #define PTHRW_COUNT_SHIFT	8
 40  #define PTHRW_INC		(1 << PTHRW_COUNT_SHIFT)
 41  #define PTHRW_BIT_MASK		((1 << PTHRW_COUNT_SHIFT) - 1)
 42  #define PTHRW_COUNT_MASK 	((uint32_t)~PTHRW_BIT_MASK)
 43  #define PTHRW_MAX_READERS 	PTHRW_COUNT_MASK
 44  
 45  // L word
 46  #define PTH_RWL_KBIT		0x01 	// cannot acquire in user mode
 47  #define PTH_RWL_EBIT		0x02	// exclusive lock in progress
 48  #define PTH_RWL_WBIT		0x04	// write waiters pending in kernel
 49  #define PTH_RWL_PBIT		0x04	// prepost (cv) pending in kernel
 50  
 51  #define PTH_RWL_MTX_WAIT	0x20 	// in cvar in mutex wait
 52  #define PTH_RWL_UBIT		0x40	// lock is unlocked (no readers or writers)
 53  #define PTH_RWL_MBIT		0x40	// overlapping grants from kernel (only in updateval)
 54  #define PTH_RWL_IBIT		0x80	// lock reset, held until first successful unlock
 55  
 56  #define PTHRW_RWL_INIT		PTH_RWL_IBIT	// reset on the lock bits (U)
 57  #define PTHRW_RWLOCK_INIT	(PTH_RWL_IBIT | PTH_RWL_UBIT)   // reset on the lock bits (U)
 58  
 59  // S word
 60  #define PTH_RWS_SBIT		0x01	// kernel transition seq not set yet
 61  #define PTH_RWS_IBIT		0x02	// Sequence is not set on return from kernel
 62  
 63  #define PTH_RWS_CV_CBIT		PTH_RWS_SBIT	// kernel has cleared all info w.r.s.t CV
 64  #define PTH_RWS_CV_PBIT		PTH_RWS_IBIT	// kernel has prepost/fake structs only,no waiters
 65  #define PTH_RWS_CV_BITSALL	(PTH_RWS_CV_CBIT | PTH_RWS_CV_PBIT)
 66  #define PTH_RWS_CV_MBIT		PTH_RWL_MBIT    // to indicate prepost return from kernel
 67  #define PTH_RWS_CV_RESET_PBIT	((uint32_t)~PTH_RWS_CV_PBIT)
 68  
 69  #define PTH_RWS_WSVBIT		0x04	// save W bit
 70  
 71  #define PTHRW_RWS_SAVEMASK	(PTH_RWS_WSVBIT)	// save bits mask
 72  
 73  #define PTHRW_RWS_INIT		PTH_RWS_SBIT	// reset on the lock bits (U)
 74  
 75  // rw_flags
 76  #define PTHRW_KERN_PROCESS_SHARED	0x10
 77  #define PTHRW_KERN_PROCESS_PRIVATE	0x20
 78  
 79  #define PTHREAD_MTX_TID_SWITCHING (uint64_t)-1
 80  
 81  // L word tests
 82  #define is_rwl_ebit_set(x) (((x) & PTH_RWL_EBIT) != 0)
 83  #define is_rwl_wbit_set(x) (((x) & PTH_RWL_WBIT) != 0)
 84  #define is_rwl_ebit_clear(x) (((x) & PTH_RWL_EBIT) == 0)
 85  #define is_rwl_readoverlap(x) (((x) & PTH_RWL_MBIT) != 0)
 86  
 87  // S word tests
 88  #define is_rws_sbit_set(x) (((x) & PTH_RWS_SBIT) != 0)
 89  #define is_rws_unlockinit_set(x) (((x) & PTH_RWS_IBIT) != 0)
 90  #define is_rws_savemask_set(x) (((x) & PTHRW_RWS_SAVEMASK) != 0)
 91  #define is_rws_pbit_set(x) (((x) & PTH_RWS_CV_PBIT) != 0)
 92  
 93  // kwe_flags
 94  #define KWE_FLAG_LOCKPREPOST	0x1 // cvwait caused a lock prepost
 95  
 96  static inline int
 97  is_seqlower(uint32_t x, uint32_t y)
 98  {
 99  	x &= PTHRW_COUNT_MASK;
100  	y &= PTHRW_COUNT_MASK;
101  	if (x < y) {
102  		return ((y - x) < (PTHRW_MAX_READERS / 2));
103  	} else {
104  		return ((x - y) > (PTHRW_MAX_READERS / 2));
105  	}
106  }
107  
108  static inline int
109  is_seqlower_eq(uint32_t x, uint32_t y)
110  {
111  	if ((x & PTHRW_COUNT_MASK) == (y & PTHRW_COUNT_MASK)) {
112  		return 1;
113  	} else {
114  		return is_seqlower(x, y);
115  	}
116  }
117  
118  static inline int
119  is_seqhigher(uint32_t x, uint32_t y)
120  {
121  	x &= PTHRW_COUNT_MASK;
122  	y &= PTHRW_COUNT_MASK;
123  	if (x > y) {
124  		return ((x - y) < (PTHRW_MAX_READERS / 2));
125  	} else {
126  		return ((y - x) > (PTHRW_MAX_READERS / 2));
127  	}
128  }
129  
130  static inline int
131  is_seqhigher_eq(uint32_t x, uint32_t y)
132  {
133  	if ((x & PTHRW_COUNT_MASK) == (y & PTHRW_COUNT_MASK)) {
134  		return 1;
135  	} else {
136  		return is_seqhigher(x,y);
137  	}
138  }
139  
140  static inline int
141  diff_genseq(uint32_t x, uint32_t y)
142  {
143  	x &= PTHRW_COUNT_MASK;
144  	y &= PTHRW_COUNT_MASK;
145  	if (x == y) {
146  		return 0;
147  	} else if (x > y)  {
148  		return x - y;
149  	} else {
150  		return ((PTHRW_MAX_READERS - y) + x + PTHRW_INC);
151  	}
152  }
153  
154  static inline int
155  find_diff(uint32_t upto, uint32_t lowest)
156  {
157  	uint32_t diff;
158  	
159  	if (upto == lowest)
160  		return(0);
161  #if 0
162  	diff = diff_genseq(upto, lowest);
163  #else
164          if (is_seqlower(upto, lowest) != 0)
165                  diff = diff_genseq(lowest, upto);
166          else
167                  diff = diff_genseq(upto, lowest);
168  #endif
169  	diff = (diff >> PTHRW_COUNT_SHIFT);
170  	return(diff);
171  }
172  
173  #endif /* __SYNCH_INTERNAL_H__ */