xref: /NextBSD/lib/libdispatch/src/semaphore_internal.h (revision 33da5adc555b3bc29986eeadca03829e4ad06b1e)
1 /*
2  * Copyright (c) 2008-2013 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20 
21 /*
22  * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
23  * which are subject to change in future releases of Mac OS X. Any applications
24  * relying on these interfaces WILL break.
25  */
26 
27 #ifndef __DISPATCH_SEMAPHORE_INTERNAL__
28 #define __DISPATCH_SEMAPHORE_INTERNAL__
29 
30 struct dispatch_queue_s;
31 
32 DISPATCH_CLASS_DECL(semaphore);
33 struct dispatch_semaphore_s {
34 	DISPATCH_STRUCT_HEADER(semaphore);
35 #if USE_MACH_SEM
36 	semaphore_t dsema_port;
37 #elif USE_POSIX_SEM
38 	sem_t dsema_sem;
39 #elif USE_WIN32_SEM
40 	HANDLE dsema_handle;
41 #else
42 #error "No supported semaphore type"
43 #endif
44 	long dsema_orig;
45 	long volatile dsema_value;
46 	union {
47 		long volatile dsema_sent_ksignals;
48 		long volatile dsema_group_waiters;
49 	};
50 	struct dispatch_continuation_s *volatile dsema_notify_head;
51 	struct dispatch_continuation_s *volatile dsema_notify_tail;
52 };
53 
54 DISPATCH_CLASS_DECL(group);
55 
56 #define DISPATCH_GROUP_INITIALIZER(s) \
57 		{ \
58 			.do_vtable = (const void*)DISPATCH_VTABLE(group), \
59 			.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, \
60 			.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT, \
61 			.dsema_value = LONG_MAX - (s), \
62 			.dsema_orig = LONG_MAX, \
63 		}
64 
65 void _dispatch_semaphore_dispose(dispatch_object_t dou);
66 size_t _dispatch_semaphore_debug(dispatch_object_t dou, char *buf,
67 		size_t bufsiz);
68 
69 typedef uintptr_t _dispatch_thread_semaphore_t;
70 
71 _dispatch_thread_semaphore_t _dispatch_thread_semaphore_create(void);
72 void _dispatch_thread_semaphore_dispose(_dispatch_thread_semaphore_t);
73 void _dispatch_thread_semaphore_wait(_dispatch_thread_semaphore_t);
74 void _dispatch_thread_semaphore_signal(_dispatch_thread_semaphore_t);
75 
76 DISPATCH_ALWAYS_INLINE
77 static inline _dispatch_thread_semaphore_t
_dispatch_get_thread_semaphore(void)78 _dispatch_get_thread_semaphore(void)
79 {
80 	_dispatch_thread_semaphore_t sema = (_dispatch_thread_semaphore_t)
81 			_dispatch_thread_getspecific(dispatch_sema4_key);
82 	if (slowpath(!sema)) {
83 		return _dispatch_thread_semaphore_create();
84 	}
85 	_dispatch_thread_setspecific(dispatch_sema4_key, NULL);
86 	return sema;
87 }
88 
89 DISPATCH_ALWAYS_INLINE
90 static inline void
_dispatch_put_thread_semaphore(_dispatch_thread_semaphore_t sema)91 _dispatch_put_thread_semaphore(_dispatch_thread_semaphore_t sema)
92 {
93 	_dispatch_thread_semaphore_t old_sema = (_dispatch_thread_semaphore_t)
94 			_dispatch_thread_getspecific(dispatch_sema4_key);
95 	_dispatch_thread_setspecific(dispatch_sema4_key, (void*)sema);
96 	if (slowpath(old_sema)) {
97 		return _dispatch_thread_semaphore_dispose(old_sema);
98 	}
99 }
100 
101 #endif
102