1 | /* $NetBSD: prop_object_impl.h,v 1.32 2015/05/11 16:50:35 christos Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2006 The NetBSD Foundation, Inc. |
5 | * All rights reserved. |
6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Jason R. Thorpe. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ |
31 | |
32 | #ifndef _PROPLIB_PROP_OBJECT_IMPL_H_ |
33 | #define _PROPLIB_PROP_OBJECT_IMPL_H_ |
34 | |
35 | #if defined(_KERNEL) || defined(_STANDALONE) |
36 | #include <lib/libkern/libkern.h> |
37 | #else |
38 | #include <inttypes.h> |
39 | #endif |
40 | |
41 | #include "prop_stack.h" |
42 | |
43 | struct _prop_object_externalize_context { |
44 | char * poec_buf; /* string buffer */ |
45 | size_t poec_capacity; /* capacity of buffer */ |
46 | size_t poec_len; /* current length of string */ |
47 | unsigned int poec_depth; /* nesting depth */ |
48 | }; |
49 | |
50 | bool _prop_object_externalize_start_tag( |
51 | struct _prop_object_externalize_context *, |
52 | const char *); |
53 | bool _prop_object_externalize_end_tag( |
54 | struct _prop_object_externalize_context *, |
55 | const char *); |
56 | bool _prop_object_externalize_empty_tag( |
57 | struct _prop_object_externalize_context *, |
58 | const char *); |
59 | bool _prop_object_externalize_append_cstring( |
60 | struct _prop_object_externalize_context *, |
61 | const char *); |
62 | bool _prop_object_externalize_append_encoded_cstring( |
63 | struct _prop_object_externalize_context *, |
64 | const char *); |
65 | bool _prop_object_externalize_append_char( |
66 | struct _prop_object_externalize_context *, |
67 | unsigned char); |
68 | bool ( |
69 | struct _prop_object_externalize_context *); |
70 | bool ( |
71 | struct _prop_object_externalize_context *); |
72 | |
73 | struct _prop_object_externalize_context * |
74 | _prop_object_externalize_context_alloc(void); |
75 | void _prop_object_externalize_context_free( |
76 | struct _prop_object_externalize_context *); |
77 | |
78 | typedef enum { |
79 | _PROP_TAG_TYPE_START, /* e.g. <dict> */ |
80 | _PROP_TAG_TYPE_END, /* e.g. </dict> */ |
81 | _PROP_TAG_TYPE_EITHER |
82 | } _prop_tag_type_t; |
83 | |
84 | struct _prop_object_internalize_context { |
85 | const char *poic_xml; |
86 | const char *poic_cp; |
87 | |
88 | const char *poic_tag_start; |
89 | |
90 | const char *poic_tagname; |
91 | size_t poic_tagname_len; |
92 | const char *poic_tagattr; |
93 | size_t poic_tagattr_len; |
94 | const char *poic_tagattrval; |
95 | size_t poic_tagattrval_len; |
96 | |
97 | bool poic_is_empty_element; |
98 | _prop_tag_type_t poic_tag_type; |
99 | }; |
100 | |
101 | typedef enum { |
102 | _PROP_OBJECT_FREE_DONE, |
103 | _PROP_OBJECT_FREE_RECURSE, |
104 | _PROP_OBJECT_FREE_FAILED |
105 | } _prop_object_free_rv_t; |
106 | |
107 | typedef enum { |
108 | _PROP_OBJECT_EQUALS_FALSE, |
109 | _PROP_OBJECT_EQUALS_TRUE, |
110 | _PROP_OBJECT_EQUALS_RECURSE |
111 | } _prop_object_equals_rv_t; |
112 | |
113 | #define _PROP_EOF(c) ((c) == '\0') |
114 | #define _PROP_ISSPACE(c) \ |
115 | ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r') |
116 | |
117 | #define _PROP_TAG_MATCH(ctx, t) \ |
118 | _prop_object_internalize_match((ctx)->poic_tagname, \ |
119 | (ctx)->poic_tagname_len, \ |
120 | (t), strlen(t)) |
121 | |
122 | #define _PROP_TAGATTR_MATCH(ctx, a) \ |
123 | _prop_object_internalize_match((ctx)->poic_tagattr, \ |
124 | (ctx)->poic_tagattr_len, \ |
125 | (a), strlen(a)) |
126 | |
127 | #define _PROP_TAGATTRVAL_MATCH(ctx, a) \ |
128 | _prop_object_internalize_match((ctx)->poic_tagattrval, \ |
129 | (ctx)->poic_tagattrval_len,\ |
130 | (a), strlen(a)) |
131 | |
132 | bool _prop_object_internalize_find_tag( |
133 | struct _prop_object_internalize_context *, |
134 | const char *, _prop_tag_type_t); |
135 | bool _prop_object_internalize_match(const char *, size_t, |
136 | const char *, size_t); |
137 | prop_object_t _prop_object_internalize_by_tag( |
138 | struct _prop_object_internalize_context *); |
139 | bool _prop_object_internalize_decode_string( |
140 | struct _prop_object_internalize_context *, |
141 | char *, size_t, size_t *, const char **); |
142 | prop_object_t _prop_generic_internalize(const char *, const char *); |
143 | |
144 | struct _prop_object_internalize_context * |
145 | _prop_object_internalize_context_alloc(const char *); |
146 | void _prop_object_internalize_context_free( |
147 | struct _prop_object_internalize_context *); |
148 | |
149 | #if !defined(_KERNEL) && !defined(_STANDALONE) |
150 | bool _prop_object_externalize_write_file(const char *, |
151 | const char *, size_t); |
152 | |
153 | struct _prop_object_internalize_mapped_file { |
154 | char * poimf_xml; |
155 | size_t poimf_mapsize; |
156 | }; |
157 | |
158 | struct _prop_object_internalize_mapped_file * |
159 | _prop_object_internalize_map_file(const char *); |
160 | void _prop_object_internalize_unmap_file( |
161 | struct _prop_object_internalize_mapped_file *); |
162 | #endif /* !_KERNEL && !_STANDALONE */ |
163 | |
164 | typedef bool (*prop_object_internalizer_t)(prop_stack_t, prop_object_t *, |
165 | struct _prop_object_internalize_context *); |
166 | typedef bool (*prop_object_internalizer_continue_t)(prop_stack_t, |
167 | prop_object_t *, |
168 | struct _prop_object_internalize_context *, |
169 | void *, prop_object_t); |
170 | |
171 | /* These are here because they're required by shared code. */ |
172 | bool _prop_array_internalize(prop_stack_t, prop_object_t *, |
173 | struct _prop_object_internalize_context *); |
174 | bool _prop_bool_internalize(prop_stack_t, prop_object_t *, |
175 | struct _prop_object_internalize_context *); |
176 | bool _prop_data_internalize(prop_stack_t, prop_object_t *, |
177 | struct _prop_object_internalize_context *); |
178 | bool _prop_dictionary_internalize(prop_stack_t, prop_object_t *, |
179 | struct _prop_object_internalize_context *); |
180 | bool _prop_number_internalize(prop_stack_t, prop_object_t *, |
181 | struct _prop_object_internalize_context *); |
182 | bool _prop_string_internalize(prop_stack_t, prop_object_t *, |
183 | struct _prop_object_internalize_context *); |
184 | |
185 | struct _prop_object_type { |
186 | /* type indicator */ |
187 | uint32_t pot_type; |
188 | /* func to free object */ |
189 | _prop_object_free_rv_t |
190 | (*pot_free)(prop_stack_t, prop_object_t *); |
191 | /* |
192 | * func to free the child returned by pot_free with stack == NULL. |
193 | * |
194 | * Must be implemented if pot_free can return anything other than |
195 | * _PROP_OBJECT_FREE_DONE. |
196 | */ |
197 | void (*pot_emergency_free)(prop_object_t); |
198 | /* func to externalize object */ |
199 | bool (*pot_extern)(struct _prop_object_externalize_context *, |
200 | void *); |
201 | /* func to test quality */ |
202 | _prop_object_equals_rv_t |
203 | (*pot_equals)(prop_object_t, prop_object_t, |
204 | void **, void **, |
205 | prop_object_t *, prop_object_t *); |
206 | /* |
207 | * func to finish equality iteration. |
208 | * |
209 | * Must be implemented if pot_equals can return |
210 | * _PROP_OBJECT_EQUALS_RECURSE |
211 | */ |
212 | void (*pot_equals_finish)(prop_object_t, prop_object_t); |
213 | void (*pot_lock)(void); |
214 | void (*pot_unlock)(void); |
215 | }; |
216 | |
217 | struct _prop_object { |
218 | const struct _prop_object_type *po_type;/* type descriptor */ |
219 | uint32_t po_refcnt; /* reference count */ |
220 | }; |
221 | |
222 | void _prop_object_init(struct _prop_object *, |
223 | const struct _prop_object_type *); |
224 | void _prop_object_fini(struct _prop_object *); |
225 | |
226 | struct _prop_object_iterator { |
227 | prop_object_t (*pi_next_object)(void *); |
228 | void (*pi_reset)(void *); |
229 | prop_object_t pi_obj; |
230 | uint32_t pi_version; |
231 | }; |
232 | |
233 | #define _PROP_NOTHREAD_ONCE_DECL(x) static bool x = false; |
234 | #define _PROP_NOTHREAD_ONCE_RUN(x,f) \ |
235 | do { \ |
236 | if ((x) == false) { \ |
237 | f(); \ |
238 | x = true; \ |
239 | } \ |
240 | } while (/*CONSTCOND*/0) |
241 | |
242 | #if defined(_KERNEL) |
243 | |
244 | /* |
245 | * proplib in the kernel... |
246 | */ |
247 | |
248 | #include <sys/param.h> |
249 | #include <sys/malloc.h> |
250 | #include <sys/pool.h> |
251 | #include <sys/systm.h> |
252 | #include <sys/rwlock.h> |
253 | #include <sys/once.h> |
254 | |
255 | #define _PROP_ASSERT(x) KASSERT(x) |
256 | |
257 | #define _PROP_MALLOC(s, t) malloc((s), (t), M_WAITOK) |
258 | #define _PROP_CALLOC(s, t) malloc((s), (t), M_WAITOK | M_ZERO) |
259 | #define _PROP_REALLOC(v, s, t) realloc((v), (s), (t), M_WAITOK) |
260 | #define _PROP_FREE(v, t) free((v), (t)) |
261 | |
262 | #define _PROP_POOL_GET(p) pool_get(&(p), PR_WAITOK) |
263 | #define _PROP_POOL_PUT(p, v) pool_put(&(p), (v)) |
264 | |
265 | struct prop_pool_init { |
266 | struct pool *pp; |
267 | size_t size; |
268 | const char *wchan; |
269 | }; |
270 | #define _PROP_POOL_INIT(pp, size, wchan) \ |
271 | struct pool pp; \ |
272 | static const struct prop_pool_init _link_ ## pp[1] = { \ |
273 | { &pp, size, wchan } \ |
274 | }; \ |
275 | __link_set_add_rodata(prop_linkpools, _link_ ## pp); |
276 | |
277 | #define _PROP_MALLOC_DEFINE(t, s, l) \ |
278 | MALLOC_DEFINE(t, s, l); |
279 | |
280 | #define _PROP_MUTEX_DECL_STATIC(x) static kmutex_t x; |
281 | #define _PROP_MUTEX_INIT(x) mutex_init(&(x),MUTEX_DEFAULT,IPL_NONE) |
282 | #define _PROP_MUTEX_LOCK(x) mutex_enter(&(x)) |
283 | #define _PROP_MUTEX_UNLOCK(x) mutex_exit(&(x)) |
284 | |
285 | #define _PROP_RWLOCK_DECL(x) krwlock_t x ; |
286 | #define _PROP_RWLOCK_INIT(x) rw_init(&(x)) |
287 | #define _PROP_RWLOCK_RDLOCK(x) rw_enter(&(x), RW_READER) |
288 | #define _PROP_RWLOCK_WRLOCK(x) rw_enter(&(x), RW_WRITER) |
289 | #define _PROP_RWLOCK_UNLOCK(x) rw_exit(&(x)) |
290 | #define _PROP_RWLOCK_DESTROY(x) rw_destroy(&(x)) |
291 | |
292 | #define _PROP_ONCE_DECL(x) static ONCE_DECL(x); |
293 | #define _PROP_ONCE_RUN(x,f) RUN_ONCE(&(x), f) |
294 | |
295 | #include <sys/atomic.h> |
296 | |
297 | #define _PROP_ATOMIC_INC32(x) atomic_inc_32(x) |
298 | #define _PROP_ATOMIC_DEC32(x) atomic_dec_32(x) |
299 | #define _PROP_ATOMIC_INC32_NV(x, v) v = atomic_inc_32_nv(x) |
300 | #define _PROP_ATOMIC_DEC32_NV(x, v) v = atomic_dec_32_nv(x) |
301 | |
302 | #elif defined(_STANDALONE) |
303 | |
304 | /* |
305 | * proplib in a standalone environment... |
306 | */ |
307 | |
308 | #include <lib/libsa/stand.h> |
309 | |
310 | void * _prop_standalone_calloc(size_t); |
311 | void * _prop_standalone_realloc(void *, size_t); |
312 | |
313 | #define _PROP_ASSERT(x) /* nothing */ |
314 | |
315 | #define _PROP_MALLOC(s, t) alloc((s)) |
316 | #define _PROP_CALLOC(s, t) _prop_standalone_calloc((s)) |
317 | #define _PROP_REALLOC(v, s, t) _prop_standalone_realloc((v), (s)) |
318 | #define _PROP_FREE(v, t) dealloc((v), 0) /* XXX */ |
319 | |
320 | #define _PROP_POOL_GET(p) alloc((p)) |
321 | #define _PROP_POOL_PUT(p, v) dealloc((v), (p)) |
322 | |
323 | #define _PROP_POOL_INIT(p, s, d) static const size_t p = s; |
324 | |
325 | #define _PROP_MALLOC_DEFINE(t, s, l) /* nothing */ |
326 | |
327 | #define _PROP_MUTEX_DECL_STATIC(x) /* nothing */ |
328 | #define _PROP_MUTEX_INIT(x) /* nothing */ |
329 | #define _PROP_MUTEX_LOCK(x) /* nothing */ |
330 | #define _PROP_MUTEX_UNLOCK(x) /* nothing */ |
331 | |
332 | #define _PROP_RWLOCK_DECL(x) /* nothing */ |
333 | #define _PROP_RWLOCK_INIT(x) /* nothing */ |
334 | #define _PROP_RWLOCK_RDLOCK(x) /* nothing */ |
335 | #define _PROP_RWLOCK_WRLOCK(x) /* nothing */ |
336 | #define _PROP_RWLOCK_UNLOCK(x) /* nothing */ |
337 | #define _PROP_RWLOCK_DESTROY(x) /* nothing */ |
338 | |
339 | #define _PROP_ONCE_DECL(x) _PROP_NOTHREAD_ONCE_DECL(x) |
340 | #define _PROP_ONCE_RUN(x,f) _PROP_NOTHREAD_ONCE_RUN(x,f) |
341 | |
342 | #define _PROP_ATOMIC_INC32(x) ++*(x) |
343 | #define _PROP_ATOMIC_DEC32(x) --*(x) |
344 | #define _PROP_ATOMIC_INC32_NV(x, v) v = ++*(x) |
345 | #define _PROP_ATOMIC_DEC32_NV(x, v) v = --*(x) |
346 | |
347 | #else |
348 | |
349 | /* |
350 | * proplib in user space... |
351 | */ |
352 | |
353 | #include <assert.h> |
354 | #include <string.h> |
355 | #include <stdio.h> |
356 | #include <stdlib.h> |
357 | #include <stddef.h> |
358 | |
359 | #define _PROP_ASSERT(x) /*LINTED*/assert(x) |
360 | |
361 | #define _PROP_MALLOC(s, t) malloc((s)) |
362 | #define _PROP_CALLOC(s, t) calloc(1, (s)) |
363 | #define _PROP_REALLOC(v, s, t) realloc((v), (s)) |
364 | #define _PROP_FREE(v, t) free((v)) |
365 | |
366 | #define _PROP_POOL_GET(p) malloc((p)) |
367 | #define _PROP_POOL_PUT(p, v) free((v)) |
368 | |
369 | #define _PROP_POOL_INIT(p, s, d) static const size_t p = s; |
370 | |
371 | #define _PROP_MALLOC_DEFINE(t, s, l) /* nothing */ |
372 | |
373 | #if defined(__NetBSD__) && defined(_LIBPROP) |
374 | /* |
375 | * Use the same mechanism as libc; we get pthread mutexes for threaded |
376 | * programs and do-nothing stubs for non-threaded programs. |
377 | */ |
378 | #include <sys/atomic.h> |
379 | #include "reentrant.h" |
380 | #define _PROP_MUTEX_DECL_STATIC(x) static mutex_t x; |
381 | #define _PROP_MUTEX_INIT(x) mutex_init(&(x), NULL) |
382 | #define _PROP_MUTEX_LOCK(x) mutex_lock(&(x)) |
383 | #define _PROP_MUTEX_UNLOCK(x) mutex_unlock(&(x)) |
384 | |
385 | #define _PROP_RWLOCK_DECL(x) rwlock_t x ; |
386 | #define _PROP_RWLOCK_INIT(x) rwlock_init(&(x), NULL) |
387 | #define _PROP_RWLOCK_RDLOCK(x) rwlock_rdlock(&(x)) |
388 | #define _PROP_RWLOCK_WRLOCK(x) rwlock_wrlock(&(x)) |
389 | #define _PROP_RWLOCK_UNLOCK(x) rwlock_unlock(&(x)) |
390 | #define _PROP_RWLOCK_DESTROY(x) rwlock_destroy(&(x)) |
391 | |
392 | #define _PROP_ONCE_DECL(x) \ |
393 | static pthread_once_t x = PTHREAD_ONCE_INIT; |
394 | #define _PROP_ONCE_RUN(x,f) thr_once(&(x), (void(*)(void))f); |
395 | |
396 | #define _PROP_ATOMIC_INC32(x) atomic_inc_32(x) |
397 | #define _PROP_ATOMIC_DEC32(x) atomic_dec_32(x) |
398 | #define _PROP_ATOMIC_INC32_NV(x, v) v = atomic_inc_32_nv(x) |
399 | #define _PROP_ATOMIC_DEC32_NV(x, v) v = atomic_dec_32_nv(x) |
400 | |
401 | #elif defined(HAVE_NBTOOL_CONFIG_H) |
402 | /* |
403 | * None of NetBSD's build tools are multi-threaded. |
404 | */ |
405 | #define _PROP_MUTEX_DECL_STATIC(x) /* nothing */ |
406 | #define _PROP_MUTEX_INIT(x) /* nothing */ |
407 | #define _PROP_MUTEX_LOCK(x) /* nothing */ |
408 | #define _PROP_MUTEX_UNLOCK(x) /* nothing */ |
409 | |
410 | #define _PROP_RWLOCK_DECL(x) /* nothing */ |
411 | #define _PROP_RWLOCK_INIT(x) /* nothing */ |
412 | #define _PROP_RWLOCK_RDLOCK(x) /* nothing */ |
413 | #define _PROP_RWLOCK_WRLOCK(x) /* nothing */ |
414 | #define _PROP_RWLOCK_UNLOCK(x) /* nothing */ |
415 | #define _PROP_RWLOCK_DESTROY(x) /* nothing */ |
416 | |
417 | #define _PROP_ONCE_DECL(x) _PROP_NOTHREAD_ONCE_DECL(x) |
418 | #define _PROP_ONCE_RUN(x,f) _PROP_NOTHREAD_ONCE_RUN(x,f) |
419 | |
420 | #define _PROP_ATOMIC_INC32(x) ++*(x) |
421 | #define _PROP_ATOMIC_DEC32(x) --*(x) |
422 | #define _PROP_ATOMIC_INC32_NV(x, v) v = ++*(x) |
423 | #define _PROP_ATOMIC_DEC32_NV(x, v) v = --*(x) |
424 | |
425 | #else |
426 | /* |
427 | * Use pthread mutexes everywhere else. |
428 | */ |
429 | #include <pthread.h> |
430 | #define _PROP_MUTEX_DECL_STATIC(x) static pthread_mutex_t x; |
431 | #define _PROP_MUTEX_INIT(x) pthread_mutex_init(&(x), NULL) |
432 | #define _PROP_MUTEX_LOCK(x) pthread_mutex_lock(&(x)) |
433 | #define _PROP_MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x)) |
434 | |
435 | #define _PROP_RWLOCK_DECL(x) pthread_rwlock_t x ; |
436 | #define _PROP_RWLOCK_INIT(x) pthread_rwlock_init(&(x), NULL) |
437 | #define _PROP_RWLOCK_RDLOCK(x) pthread_rwlock_rdlock(&(x)) |
438 | #define _PROP_RWLOCK_WRLOCK(x) pthread_rwlock_wrlock(&(x)) |
439 | #define _PROP_RWLOCK_UNLOCK(x) pthread_rwlock_unlock(&(x)) |
440 | #define _PROP_RWLOCK_DESTROY(x) pthread_rwlock_destroy(&(x)) |
441 | |
442 | #define _PROP_ONCE_DECL(x) \ |
443 | static pthread_once_t x = PTHREAD_ONCE_INIT; |
444 | #define _PROP_ONCE_RUN(x,f) pthread_once(&(x),(void(*)(void))f) |
445 | |
446 | #define _PROP_NEED_REFCNT_MTX |
447 | |
448 | #define _PROP_ATOMIC_INC32(x) \ |
449 | do { \ |
450 | pthread_mutex_lock(&_prop_refcnt_mtx); \ |
451 | (*(x))++; \ |
452 | pthread_mutex_unlock(&_prop_refcnt_mtx); \ |
453 | } while (/*CONSTCOND*/0) |
454 | |
455 | #define _PROP_ATOMIC_DEC32(x) \ |
456 | do { \ |
457 | pthread_mutex_lock(&_prop_refcnt_mtx); \ |
458 | (*(x))--; \ |
459 | pthread_mutex_unlock(&_prop_refcnt_mtx); \ |
460 | } while (/*CONSTCOND*/0) |
461 | |
462 | #define _PROP_ATOMIC_INC32_NV(x, v) \ |
463 | do { \ |
464 | pthread_mutex_lock(&_prop_refcnt_mtx); \ |
465 | v = ++(*(x)); \ |
466 | pthread_mutex_unlock(&_prop_refcnt_mtx); \ |
467 | } while (/*CONSTCOND*/0) |
468 | |
469 | #define _PROP_ATOMIC_DEC32_NV(x, v) \ |
470 | do { \ |
471 | pthread_mutex_lock(&_prop_refcnt_mtx); \ |
472 | v = --(*(x)); \ |
473 | pthread_mutex_unlock(&_prop_refcnt_mtx); \ |
474 | } while (/*CONSTCOND*/0) |
475 | |
476 | #endif |
477 | #endif /* _KERNEL */ |
478 | |
479 | /* |
480 | * Language features. |
481 | */ |
482 | #if defined(__NetBSD__) |
483 | #include <sys/cdefs.h> |
484 | #define _PROP_ARG_UNUSED __unused |
485 | #else |
486 | #define _PROP_ARG_UNUSED /* delete */ |
487 | #endif /* __NetBSD__ */ |
488 | |
489 | #endif /* _PROPLIB_PROP_OBJECT_IMPL_H_ */ |
490 | |