fix issue with HBC stub + 64B L2 cache (tueidj)
[libogc.git] / libogc / cond.c
blobd7555825f00e6d407ecf74f44666392f02baf253
1 /*-------------------------------------------------------------
3 cond.c -- Thread subsystem V
5 Copyright (C) 2004
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
26 distribution.
28 -------------------------------------------------------------*/
31 #include <stdlib.h>
32 #include <errno.h>
33 #include "asm.h"
34 #include "mutex.h"
35 #include "lwp_threadq.h"
36 #include "lwp_objmgr.h"
37 #include "lwp_config.h"
38 #include "cond.h"
40 #define LWP_OBJTYPE_COND 5
42 #define LWP_CHECK_COND(hndl) \
43 { \
44 if(((hndl)==LWP_COND_NULL) || (LWP_OBJTYPE(hndl)!=LWP_OBJTYPE_COND)) \
45 return NULL; \
48 typedef struct _cond_st {
49 lwp_obj object;
50 mutex_t lock;
51 lwp_thrqueue wait_queue;
52 } cond_st;
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)
66 LWP_CHECK_COND(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()
78 cond_st *cond;
80 __lwp_thread_dispatchdisable();
81 cond = (cond_st*)__lwp_objmgr_allocate(&_lwp_cond_objects);
82 if(cond) {
83 __lwp_objmgr_open(&_lwp_cond_objects,&cond->object);
84 return cond;
86 __lwp_thread_dispatchenable();
87 return NULL;
90 static s32 __lwp_cond_waitsupp(cond_t cond,mutex_t mutex,u64 timeout,u8 timedout)
92 u32 status,mstatus,level;
93 cond_st *thecond;
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();
100 return EINVAL;
104 LWP_MutexUnlock(mutex);
105 if(!timedout) {
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)
118 return status;
119 } else {
120 __lwp_thread_dispatchenable();
121 status = ETIMEDOUT;
124 mstatus = LWP_MutexLock(mutex);
125 if(mstatus)
126 return EINVAL;
128 return status;
131 static s32 __lwp_cond_signalsupp(cond_t cond,u8 isbroadcast)
133 lwp_cntrl *thethread;
134 cond_st *thecond;
136 thecond = __lwp_cond_open(cond);
137 if(!thecond) return -1;
139 do {
140 thethread = __lwp_threadqueue_dequeue(&thecond->wait_queue);
141 if(!thethread) thecond->lock = LWP_MUTEX_NULL;
142 } while(isbroadcast && thethread);
143 __lwp_thread_dispatchenable();
144 return 0;
147 s32 LWP_CondInit(cond_t *cond)
149 cond_st *ret;
151 if(!cond) return -1;
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();
162 return 0;
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)
191 cond_st *ptr;
193 ptr = __lwp_cond_open(cond);
194 if(!ptr) return -1;
196 if(__lwp_threadqueue_first(&ptr->wait_queue)) {
197 __lwp_thread_dispatchenable();
198 return EBUSY;
200 __lwp_thread_dispatchenable();
202 __lwp_cond_free(ptr);
203 return 0;