1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 #include <kproc/extern.h>
27 #include <kproc/cond.h>
28 #include <klib/rc.h>
29 #include <sysalloc.h>
30 #include <atomic32.h>
31
32 #include <stdlib.h>
33
34
35 /*--------------------------------------------------------------------------
36 * KCondition
37 * a POSIX-style condition object
38 */
39 struct KCondition
40 {
41 atomic32_t refcount;
42 };
43
44
45 /* Whack
46 */
47 static
KConditionWhack(KCondition * self)48 rc_t KConditionWhack ( KCondition *self )
49 {
50 free ( self );
51 return 0;
52 }
53
54
55 /* Make
56 * create a condition
57 */
KConditionMake(KCondition ** condp)58 LIB_EXPORT rc_t CC KConditionMake ( KCondition **condp )
59 {
60 rc_t rc;
61 if ( condp == NULL )
62 rc = RC ( rcPS, rcCondition, rcConstructing, rcParam, rcNull );
63 else
64 {
65 KCondition *cond = malloc ( sizeof * cond );
66 if ( cond == NULL )
67 rc = RC ( rcPS, rcCondition, rcConstructing, rcMemory, rcExhausted );
68 else
69 {
70 atomic32_set ( & cond -> refcount, 1 );
71 * condp = cond;
72 return 0;
73 }
74
75 * condp = NULL;
76 }
77 return rc;
78 }
79
80
81 /* AddRef
82 * Release
83 */
KConditionAddRef(const KCondition * cself)84 LIB_EXPORT rc_t CC KConditionAddRef ( const KCondition *cself )
85 {
86 if ( cself != NULL )
87 atomic32_inc ( & ( ( KCondition* ) cself ) -> refcount );
88 return 0;
89 }
90
KConditionRelease(const KCondition * cself)91 LIB_EXPORT rc_t CC KConditionRelease ( const KCondition *cself )
92 {
93 KCondition *self = ( KCondition* ) cself;
94 if ( cself != NULL )
95 {
96 if ( atomic32_dec_and_test ( & self -> refcount ) )
97 return KConditionWhack ( self );
98 }
99 return 0;
100 }
101
102
103 /* Wait
104 * block on external lock until signaled
105 */
KConditionWait(KCondition * self,struct KLock * lock)106 LIB_EXPORT rc_t CC KConditionWait ( KCondition *self, struct KLock *lock )
107 {
108 if ( self == NULL )
109 return RC ( rcPS, rcCondition, rcWaiting, rcSelf, rcNull );
110 if ( lock == NULL )
111 return RC ( rcPS, rcCondition, rcWaiting, rcLock, rcNull );
112
113 return RC ( rcPS, rcCondition, rcWaiting, rcThread, rcDeadlock );
114 }
115
KConditionTimedWait(KCondition * self,struct KLock * lock,struct timeout_t * tm)116 LIB_EXPORT rc_t CC KConditionTimedWait ( KCondition *self, struct KLock *lock, struct timeout_t *tm )
117 {
118 if ( self == NULL )
119 return RC ( rcPS, rcCondition, rcWaiting, rcSelf, rcNull );
120 if ( lock == NULL )
121 return RC ( rcPS, rcCondition, rcWaiting, rcLock, rcNull );
122 if ( tm == NULL )
123 return RC ( rcPS, rcCondition, rcWaiting, rcTimeout, rcNull );
124
125 return RC ( rcPS, rcCondition, rcWaiting, rcThread, rcDeadlock );
126 }
127
128
129 /* Signal
130 * signal waiting threads
131 * awaken at most a single thread
132 */
KConditionSignal(KCondition * self)133 LIB_EXPORT rc_t CC KConditionSignal ( KCondition *self )
134 {
135 if ( self == NULL )
136 return RC ( rcPS, rcCondition, rcSignaling, rcSelf, rcNull );
137
138 return RC ( rcPS, rcCondition, rcSignaling, rcThread, rcDeadlock );
139 }
140
141
142 /* Broadcast
143 * signal waiting threads
144 * awaken all waiting thread
145 */
KConditionBroadcast(KCondition * self)146 LIB_EXPORT rc_t CC KConditionBroadcast ( KCondition *self )
147 {
148 if ( self == NULL )
149 return RC ( rcPS, rcCondition, rcSignaling, rcSelf, rcNull );
150
151 return RC ( rcPS, rcCondition, rcSignaling, rcThread, rcDeadlock );
152 }
153