1 /*-------------------------------------------------------------
3 cond.c -- Thread subsystem V
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
28 -------------------------------------------------------------*/
35 #include "lwp_threadq.h"
36 #include "lwp_objmgr.h"
37 #include "lwp_config.h"
40 #define LWP_OBJTYPE_COND 5
42 #define LWP_CHECK_COND(hndl) \
44 if(((hndl)==LWP_COND_NULL) || (LWP_OBJTYPE(hndl)!=LWP_OBJTYPE_COND)) \
48 typedef struct _cond_st
{
51 lwp_thrqueue wait_queue
;
54 lwp_objinfo _lwp_cond_objects
;
56 extern int clock_gettime(struct timespec
*tp
);
57 extern void timespec_subtract(const struct timespec
*tp_start
,const struct timespec
*tp_end
,struct timespec
*result
);
59 void __lwp_cond_init()
61 __lwp_objmgr_initinfo(&_lwp_cond_objects
,LWP_MAX_CONDVARS
,sizeof(cond_st
));
64 static __inline__ cond_st
* __lwp_cond_open(cond_t cond
)
67 return (cond_st
*)__lwp_objmgr_get(&_lwp_cond_objects
,LWP_OBJMASKID(cond
));
70 static __inline__
void __lwp_cond_free(cond_st
*cond
)
72 __lwp_objmgr_close(&_lwp_cond_objects
,&cond
->object
);
73 __lwp_objmgr_free(&_lwp_cond_objects
,&cond
->object
);
76 static cond_st
* __lwp_cond_allocate()
80 __lwp_thread_dispatchdisable();
81 cond
= (cond_st
*)__lwp_objmgr_allocate(&_lwp_cond_objects
);
83 __lwp_objmgr_open(&_lwp_cond_objects
,&cond
->object
);
86 __lwp_thread_dispatchenable();
90 static s32
__lwp_cond_waitsupp(cond_t cond
,mutex_t mutex
,u64 timeout
,u8 timedout
)
92 u32 status
,mstatus
,level
;
95 thecond
= __lwp_cond_open(cond
);
96 if(!thecond
) return -1;
98 if(thecond
->lock
!=LWP_MUTEX_NULL
&& thecond
->lock
!=mutex
) {
99 __lwp_thread_dispatchenable();
104 LWP_MutexUnlock(mutex
);
106 thecond
->lock
= mutex
;
107 _CPU_ISR_Disable(level
);
108 __lwp_threadqueue_csenter(&thecond
->wait_queue
);
109 _thr_executing
->wait
.ret_code
= 0;
110 _thr_executing
->wait
.queue
= &thecond
->wait_queue
;
111 _thr_executing
->wait
.id
= cond
;
112 _CPU_ISR_Restore(level
);
113 __lwp_threadqueue_enqueue(&thecond
->wait_queue
,timeout
);
114 __lwp_thread_dispatchenable();
116 status
= _thr_executing
->wait
.ret_code
;
117 if(status
&& status
!=ETIMEDOUT
)
120 __lwp_thread_dispatchenable();
124 mstatus
= LWP_MutexLock(mutex
);
131 static s32
__lwp_cond_signalsupp(cond_t cond
,u8 isbroadcast
)
133 lwp_cntrl
*thethread
;
136 thecond
= __lwp_cond_open(cond
);
137 if(!thecond
) return -1;
140 thethread
= __lwp_threadqueue_dequeue(&thecond
->wait_queue
);
141 if(!thethread
) thecond
->lock
= LWP_MUTEX_NULL
;
142 } while(isbroadcast
&& thethread
);
143 __lwp_thread_dispatchenable();
147 s32
LWP_CondInit(cond_t
*cond
)
153 ret
= __lwp_cond_allocate();
154 if(!ret
) return ENOMEM
;
156 ret
->lock
= LWP_MUTEX_NULL
;
157 __lwp_threadqueue_init(&ret
->wait_queue
,LWP_THREADQ_MODEFIFO
,LWP_STATES_WAITING_FOR_CONDVAR
,ETIMEDOUT
);
159 *cond
= (cond_t
)(LWP_OBJMASKTYPE(LWP_OBJTYPE_COND
)|LWP_OBJMASKID(ret
->object
.id
));
160 __lwp_thread_dispatchenable();
165 s32
LWP_CondWait(cond_t cond
,mutex_t mutex
)
167 return __lwp_cond_waitsupp(cond
,mutex
,LWP_THREADQ_NOTIMEOUT
,FALSE
);
170 s32
LWP_CondSignal(cond_t cond
)
172 return __lwp_cond_signalsupp(cond
,FALSE
);
175 s32
LWP_CondBroadcast(cond_t cond
)
177 return __lwp_cond_signalsupp(cond
,TRUE
);
180 s32
LWP_CondTimedWait(cond_t cond
,mutex_t mutex
,const struct timespec
*abstime
)
182 u64 timeout
= LWP_THREADQ_NOTIMEOUT
;
183 bool timedout
= FALSE
;
185 if(abstime
) timeout
= __lwp_wd_calc_ticks(abstime
);
186 return __lwp_cond_waitsupp(cond
,mutex
,timeout
,timedout
);
189 s32
LWP_CondDestroy(cond_t cond
)
193 ptr
= __lwp_cond_open(cond
);
196 if(__lwp_threadqueue_first(&ptr
->wait_queue
)) {
197 __lwp_thread_dispatchenable();
200 __lwp_thread_dispatchenable();
202 __lwp_cond_free(ptr
);