1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME:
80**
81**      rpcmutex.h
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**  A veneer over CMA (or anything else for that matter) to assist with
90**  mutex and condition variable support for the runtime.  This provides
91**  some isolation from the underlying mechanisms to allow us to (more)
92**  easily slip in alternate facilities, and more importantly add features
93**  that we'd like to have in the areas of correctness and debugging
94**  of code using these locks as well as statistics gathering.  Note
95**  that this package contains a "condition variable" veneer as well,
96**  since condition variables and mutexes are tightly integrated (i.e.
97**  condition variables have an associated mutex).
98**
99**  This package provides the following PRIVATE data types and operations:
100**
101**      rpc_mutex_t m;
102**      rpc_cond_t c;
103**
104**      void RPC_MUTEX_INIT(m)
105**      void RPC_MUTEX_DELETE(m)
106**      void RPC_MUTEX_LOCK(m)
107**      void RPC_MUTEX_TRY_LOCK(m,bp)
108**      void RPC_MUTEX_UNLOCK(m)
109**      void RPC_MUTEX_LOCK_ASSERT(m)
110**      void RPC_MUTEX_UNLOCK_ASSERT(m)
111**
112**      void RPC_COND_INIT(c,m)
113**      void RPC_COND_DELETE(c,m)
114**      void RPC_COND_WAIT(c,m)
115**      void RPC_COND_TIMED_WAIT(c,m,t)
116**      void RPC_COND_SIGNAL(c,m)
117**
118**  This code is controlled by debug switch "rpc_e_dbg_mutex".  At levels 1
119**  or higher, statistics gathering is enabled.  At levels 5 or higher,
120**  assertion checking, ownership tracking, deadlock detection, etc. are
121**  enabled.
122**
123**
124*/
125
126#ifndef _RPCMUTEX_H
127#define _RPCMUTEX_H	1
128
129/*
130 * The rpc_mutex_t data type.
131 *
132 * If debugging isn't configured, this is just a unadorned mutex, else we adorn
133 * the struct with goodies to enable assertion checking, deadlock detection
134 * and statistics gathering.
135 */
136
137typedef struct rpc_mutex_stats_t
138{
139    unsigned32 busy;            /* total lock requests when already locked */
140    unsigned32 lock;            /* total locks */
141    unsigned32 try_lock;        /* total try_locks */
142    unsigned32 unlock;          /* total unlocks */
143    unsigned32 init;            /* total inits */
144    unsigned32 deletes;         /* total deletes */
145    unsigned32 lock_assert;     /* total lock_asserts */
146    unsigned32 unlock_assert;
147} rpc_mutex_stats_t, *rpc_mutex_stats_p_t;
148#define RPC_MUTEX_STATUS_INITIALIZER {0, 0, 0, 0, 0, 0, 0, 0}
149
150typedef struct rpc_mutex_t
151{
152    dcethread_mutex m;          /* the unadorned mutex lock */
153#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
154    unsigned is_locked:1;       /* T=> locked */
155    dcethread* owner;            /* current owner if locked */
156    char *locker_file;          /* last locker */
157    int locker_line;            /* last locker */
158    rpc_mutex_stats_t stats;
159#endif /* RPC_MUTEX_DEBUG OR RPC_MUTEX_STATS */
160} rpc_mutex_t, *rpc_mutex_p_t;
161#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
162# define RPC_MUTEX_INITIALIZER {DCETHREAD_MUTEX_INITIALIZER, 0, 0, NULL, 0, RPC_MUTEX_STATUS_INITIALIZER}
163#else
164# define RPC_MUTEX_INITIALIZER {DCETHREAD_MUTEX_INITIALIZER}
165#endif
166
167/*
168 * The rpc_cond_t (condition variable) data type.
169 */
170
171typedef struct rpc_cond_stats_t
172{
173    unsigned32 init;            /* total inits */
174    unsigned32 deletes;          /* total deletes */
175    unsigned32 wait;            /* total waits */
176    unsigned32 signals;         /* total signals + broadcasts */
177} rpc_cond_stats_t, *rpc_cond_stats_p_t;
178#define RPC_COND_STATS_INITIALIZER {0, 0, 0, 0}
179
180typedef struct rpc_cond_t
181{
182    dcethread_cond c;           /* the unadorned condition variable */
183    rpc_mutex_p_t mp;           /* the cv's associated mutex */
184    rpc_cond_stats_t stats;
185} rpc_cond_t, *rpc_cond_p_t;
186#define RPC_COND_INITIALIZER {DCETHREAD_COND_INITIALIZER, NULL, RPC_COND_STATS_INITIALIZER}
187
188/*
189 * Some relatively efficient generic mutex operations that are controllable
190 * at run time as well as compile time.  The "real" support routines
191 * can be found in rpcmutex.c .
192 */
193
194/*
195 * R P C _ M U T E X _ I N I T
196 *
197 * We always need to call the support routine so that the stats, etc
198 * get initialized.
199 */
200
201#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
202
203#  define RPC_MUTEX_INIT(mutex)  \
204    { \
205        if (! rpc__mutex_init(&(mutex))) \
206        { \
207            rpc_dce_svc_printf ( \
208                __FILE__, __LINE__, \
209                "%s", \
210                rpc_svc_mutex, \
211                svc_c_sev_fatal | svc_c_action_abort, \
212                rpc_m_call_failed_no_status, \
213                "RPC_MUTEX_INIT/rpc__mutex_init" ); \
214        } \
215    }
216#else
217#  define RPC_MUTEX_INIT(mutex) \
218    { \
219        RPC_LOG_MUTEX_INIT_NTR; \
220        dcethread_mutex_init_throw(&(mutex).m, NULL); \
221        RPC_LOG_MUTEX_INIT_XIT; \
222    }
223#endif /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
224
225/*
226 * R P C _ M U T E X _ D E L E T E
227 */
228
229#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
230#  define RPC_MUTEX_DELETE(mutex)  \
231    { \
232        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
233        { \
234            if (! rpc__mutex_delete(&(mutex))) \
235            { \
236                rpc_dce_svc_printf ( \
237                    __FILE__, __LINE__, \
238                    "%s", \
239                    rpc_svc_mutex, \
240                    svc_c_sev_fatal | svc_c_action_abort, \
241                    rpc_m_call_failed_no_status, \
242                    "RPC_MUTEX_DELETE/rpc__mutex_delete" ); \
243            } \
244        } else { \
245            dcethread_mutex_destroy_throw(&(mutex).m); \
246        } \
247    }
248#else
249#  define RPC_MUTEX_DELETE(mutex) \
250    { \
251        RPC_LOG_MUTEX_DELETE_NTR; \
252        dcethread_mutex_destroy_throw(&(mutex).m); \
253        RPC_LOG_MUTEX_DELETE_XIT; \
254    }
255#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
256
257/*
258 * R P C _ M U T E X _ L O C K
259 */
260
261#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
262
263#  define RPC_MUTEX_LOCK(mutex)  \
264    { \
265        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
266        { \
267            if (! rpc__mutex_lock(&(mutex), __FILE__, __LINE__)) \
268            { \
269                rpc_dce_svc_printf ( \
270                    __FILE__, __LINE__, \
271                    "%s", \
272                    rpc_svc_mutex, \
273                    svc_c_sev_fatal | svc_c_action_abort, \
274                    rpc_m_call_failed_no_status, \
275                    "RPC_MUTEX_LOCK/rpc__mutex_lock" ); \
276            } \
277        } else { \
278            RPC_LOG_MUTEX_LOCK_NTR; \
279            dcethread_mutex_lock_throw(&(mutex).m); \
280            RPC_LOG_MUTEX_LOCK_XIT; \
281        } \
282    }
283#else
284#  define RPC_MUTEX_LOCK(mutex) \
285    { \
286        RPC_LOG_MUTEX_LOCK_NTR; \
287        dcethread_mutex_lock_throw(&(mutex).m); \
288        RPC_LOG_MUTEX_LOCK_XIT; \
289    }
290#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
291
292/*
293 * R P C _ M U T E X _ T R Y _ L O C K
294 */
295
296#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
297
298#  define RPC_MUTEX_TRY_LOCK(mutex,bp)  \
299    { \
300        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
301        { \
302            if (! rpc__mutex_try_lock(&(mutex), (bp), __FILE__, __LINE__)) \
303            { \
304                rpc_dce_svc_printf ( \
305                    __FILE__, __LINE__, \
306                    "%s", \
307                    rpc_svc_mutex, \
308                    svc_c_sev_fatal | svc_c_action_abort, \
309                    rpc_m_call_failed_no_status, \
310                    "RPC_MUTEX_TRY_LOCK/rpc__mutex_try_lock" ); \
311            } \
312        } else { \
313            *(bp) = dcethread_mutex_trylock_throw(&(mutex).m); \
314        } \
315    }
316#else
317#  define RPC_MUTEX_TRY_LOCK(mutex,bp) \
318    { \
319        RPC_LOG_MUTEX_TRY_LOCK_NTR; \
320        *(bp) = dcethread_mutex_trylock_throw(&(mutex).m); \
321        RPC_LOG_MUTEX_TRY_LOCK_XIT; \
322    }
323#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
324
325/*
326 * R P C _ M U T E X _ U N L O C K
327 */
328
329#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
330
331#  define RPC_MUTEX_UNLOCK(mutex)  \
332    { \
333        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
334        { \
335            if (! rpc__mutex_unlock(&(mutex))) \
336            { \
337                rpc_dce_svc_printf ( \
338                    __FILE__, __LINE__, \
339                    "%s", \
340                    rpc_svc_mutex, \
341                    svc_c_sev_fatal | svc_c_action_abort, \
342                    rpc_m_call_failed_no_status, \
343                    "RPC_MUTEX_UNLOCK/rpc__mutex_unlock" ); \
344            } \
345        } else { \
346            dcethread_mutex_unlock_throw(&(mutex).m); \
347        } \
348    }
349#else
350#  define RPC_MUTEX_UNLOCK(mutex) \
351    { \
352        RPC_LOG_MUTEX_UNLOCK_NTR; \
353        dcethread_mutex_unlock_throw(&(mutex).m); \
354        RPC_LOG_MUTEX_UNLOCK_XIT; \
355    }
356#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
357
358/*
359 * R P C _ M U T E X _ L O C K _ A S S E R T
360 */
361
362#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
363
364#  define RPC_MUTEX_LOCK_ASSERT(mutex)  \
365    { \
366        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
367        { \
368            if (! rpc__mutex_lock_assert(&(mutex))) \
369            { \
370                rpc_dce_svc_printf ( \
371                    __FILE__, __LINE__, \
372                    "%s", \
373                    rpc_svc_mutex, \
374                    svc_c_sev_fatal | svc_c_action_abort, \
375                    rpc_m_call_failed_no_status, \
376                    "RPC_MUTEX_LOCK_ASSERT/rpc__mutex_lock_assert" ); \
377            } \
378        } \
379    }
380#else
381#  define RPC_MUTEX_LOCK_ASSERT(mutex)      { }
382#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
383
384/*
385 * R P C _ M U T E X _ U N L O C K _ A S S E R T
386 */
387
388#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
389
390#  define RPC_MUTEX_UNLOCK_ASSERT(mutex)  \
391    { \
392        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
393        { \
394            if (! rpc__mutex_unlock_assert(&(mutex))) \
395            { \
396                rpc_dce_svc_printf ( \
397                    __FILE__, __LINE__, \
398                    "%s", \
399                    rpc_svc_mutex, \
400                    svc_c_sev_fatal | svc_c_action_abort, \
401                    rpc_m_call_failed_no_status, \
402                    "RPC_MUTEX_UNLOCK_ASSERT/rpc__mutex_unlock_assert" ); \
403            } \
404        } \
405    }
406#else
407#  define RPC_MUTEX_UNLOCK_ASSERT(mutex)    { }
408#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
409
410/*
411 *  R P C _ C O N D _ I N I T
412 */
413
414#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
415
416#  define RPC_COND_INIT(cond,mutex)  \
417    { \
418        if (! rpc__cond_init(&(cond), &(mutex))) \
419        { \
420            rpc_dce_svc_printf ( \
421                __FILE__, __LINE__, \
422                "%s", \
423                rpc_svc_mutex, \
424                svc_c_sev_fatal | svc_c_action_abort, \
425                rpc_m_call_failed_no_status, \
426                "RPC_COND_INIT/rpc__cond_init" ); \
427        } \
428    }
429#else
430#  define RPC_COND_INIT(cond,mutex) \
431    { \
432        RPC_LOG_COND_INIT_NTR; \
433        dcethread_cond_init_throw(&(cond).c, NULL);  \
434        RPC_LOG_COND_INIT_XIT; \
435    }
436#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
437
438/*
439 *  R P C _ C O N D _ D E L E T E
440 */
441
442#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
443
444#  define RPC_COND_DELETE(cond,mutex)  \
445    { \
446        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
447        { \
448            if (! rpc__cond_delete(&(cond), &(mutex))) \
449            { \
450                rpc_dce_svc_printf ( \
451                    __FILE__, __LINE__, \
452                    "%s", \
453                    rpc_svc_mutex, \
454                    svc_c_sev_fatal | svc_c_action_abort, \
455                    rpc_m_call_failed_no_status, \
456                    "RPC_COND_DELETE/rpc__cond_delete" ); \
457            } \
458        } else { \
459            dcethread_cond_destroy_throw(&(cond).c); \
460        } \
461    }
462#else
463#  define RPC_COND_DELETE(cond,mutex) \
464    { \
465      RPC_LOG_COND_DELETE_NTR; \
466      dcethread_cond_destroy_throw(&(cond).c); \
467      RPC_LOG_COND_DELETE_XIT; \
468  }
469#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
470
471/*
472 *  R P C _ C O N D _ W A I T
473 */
474
475#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
476
477#  define RPC_COND_WAIT(cond,mutex)  \
478    { \
479        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
480        { \
481            if (! rpc__cond_wait(&(cond), &(mutex), __FILE__, __LINE__)) \
482            { \
483                rpc_dce_svc_printf ( \
484                    __FILE__, __LINE__, \
485                    "%s", \
486                    rpc_svc_mutex, \
487                    svc_c_sev_fatal | svc_c_action_abort, \
488                    rpc_m_call_failed_no_status, \
489                    "RPC_COND_WAIT/rpc__cond_wait" ); \
490            } \
491        } else { \
492            dcethread_cond_wait_throw(&(cond).c, &(mutex).m); \
493        } \
494    }
495#else
496#  define RPC_COND_WAIT(cond,mutex) \
497    { \
498        RPC_LOG_COND_WAIT_NTR; \
499        dcethread_cond_wait_throw(&(cond).c, &(mutex).m); \
500        RPC_LOG_COND_WAIT_XIT; \
501    }
502#endif
503
504/*
505 *  R P C _ C O N D _ T I M E D _ W A I T
506 */
507
508#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
509
510#  define RPC_COND_TIMED_WAIT(cond,mutex,time)  \
511    { \
512        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
513        { \
514            if (! rpc__cond_timed_wait(&(cond), &(mutex), (time), __FILE__, __LINE__)) \
515            { \
516                rpc_dce_svc_printf ( \
517                    __FILE__, __LINE__, \
518                    "%s", \
519                    rpc_svc_mutex, \
520                    svc_c_sev_fatal | svc_c_action_abort, \
521                    rpc_m_call_failed_no_status, \
522                    "RPC_COND_TIMED_WAIT/rpc__cond_timed_wait" ); \
523            } \
524        } else { \
525            dcethread_cond_timedwait_throw(&(cond).c, &(mutex).m, (time)); \
526        } \
527    }
528#else
529#  define RPC_COND_TIMED_WAIT(cond,mutex,time) \
530    { \
531        RPC_LOG_COND_TIMED_WAIT_NTR; \
532        dcethread_cond_timedwait_throw(&(cond).c, &(mutex).m, (time)); \
533        RPC_LOG_COND_TIMED_WAIT_XIT; \
534    }
535#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
536
537/*
538 *  R P C _ _ C O N D _ S I G N A L
539 */
540
541#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
542
543#  define RPC_COND_SIGNAL(cond,mutex)  \
544    { \
545        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
546        { \
547            if (! rpc__cond_signal(&(cond), &(mutex))) \
548            { \
549                rpc_dce_svc_printf ( \
550                    __FILE__, __LINE__, \
551                    "%s", \
552                    rpc_svc_mutex, \
553                    svc_c_sev_fatal | svc_c_action_abort, \
554                    rpc_m_call_failed_no_status, \
555                    "RPC_COND_SIGNAL/rpc__cond_signal" ); \
556            } \
557        } else { \
558            dcethread_cond_signal_throw(&(cond).c); \
559        } \
560    }
561#else
562#  define RPC_COND_SIGNAL(cond,mutex) \
563    { \
564        RPC_LOG_COND_SIGNAL_NTR; \
565        dcethread_cond_signal_throw(&(cond).c); \
566        RPC_LOG_COND_SIGNAL_XIT; \
567    }
568#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
569
570/*
571 *  R P C _ _ C O N D _ B R O A D C A S T
572 */
573
574#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
575
576#  define RPC_COND_BROADCAST(cond,mutex)  \
577    { \
578        if (RPC_DBG(rpc_es_dbg_mutex, 1)) \
579        { \
580            if (! rpc__cond_broadcast(&(cond), &(mutex))) \
581            { \
582                rpc_dce_svc_printf ( \
583                    __FILE__, __LINE__, \
584                    "%s", \
585                    rpc_svc_mutex, \
586                    svc_c_sev_fatal | svc_c_action_abort, \
587                    rpc_m_call_failed_no_status, \
588                    "RPC_COND_BROADCAST/rpc__cond_broadcast" ); \
589            } \
590        } else { \
591            dcethread_cond_broadcast_throw(&(cond).c); \
592        } \
593    }
594#else
595#  define RPC_COND_BROADCAST(cond,mutex) \
596    { \
597        RPC_LOG_COND_BROADCAST_NTR; \
598        dcethread_cond_broadcast_throw(&(cond).c); \
599        RPC_LOG_COND_BROADCAST_XIT; \
600    }
601#endif  /* RPC_MUTEX_DEBUG or RPC_MUTEX_STATS */
602
603/* ===================================================================== */
604
605#if defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS)
606
607/*
608 * Prototypes for the support routines.
609 */
610
611boolean rpc__mutex_init ( rpc_mutex_p_t  /*mp*/ );
612
613boolean rpc__mutex_delete ( rpc_mutex_p_t  /*mp*/ );
614
615boolean rpc__mutex_lock (
616        rpc_mutex_p_t  /*mp*/,
617        char * /*file*/,
618        int  /*line*/
619    );
620
621boolean rpc__mutex_try_lock (
622        rpc_mutex_p_t  /*mp*/,
623        boolean * /*bp*/,
624        char * /*file*/,
625        int  /*line*/
626    );
627
628boolean rpc__mutex_unlock ( rpc_mutex_p_t  /*mp*/ );
629
630boolean rpc__mutex_lock_assert ( rpc_mutex_p_t  /*mp*/);
631
632boolean rpc__mutex_unlock_assert ( rpc_mutex_p_t  /*mp*/);
633
634boolean rpc__cond_init (
635        rpc_cond_p_t  /*cp*/,
636        rpc_mutex_p_t  /*mp*/
637    );
638
639boolean rpc__cond_delete (
640        rpc_cond_p_t  /*cp*/,
641        rpc_mutex_p_t  /*mp*/
642    );
643
644boolean rpc__cond_wait (
645        rpc_cond_p_t  /*cp*/,
646        rpc_mutex_p_t  /*mp*/,
647        char * /*file*/,
648        int  /*line*/
649    );
650
651boolean rpc__cond_timed_wait (
652        rpc_cond_p_t  /*cp*/,
653        rpc_mutex_p_t  /*mp*/,
654        struct timespec * /*wtime*/,
655        char * /*file*/,
656        int  /*line*/
657    );
658
659boolean rpc__cond_signal (
660        rpc_cond_p_t  /*cp*/,
661        rpc_mutex_p_t  /*mp*/
662    );
663
664boolean rpc__cond_broadcast (
665        rpc_cond_p_t  /*cp*/,
666        rpc_mutex_p_t  /*mp*/
667    );
668
669#else
670
671#ifdef MIREK_NOT_DEFINED
672static void rpc__mutex_none (void);
673#endif
674#endif /* defined(RPC_MUTEX_DEBUG) || defined(RPC_MUTEX_STATS) */
675
676/* ===================================================================== */
677
678#endif /* _RPCMUTEX_H */
679