14 return KE_ILLEGAL_CONTEXT;
17 if (sema_params->attr & ~(SA_THFIFO | SA_THPRI | SA_IHTHPRI)) {
18 return KE_ILLEGAL_ATTR;
23 sema = heap_alloc(TAG_SEMA,
sizeof(*sema));
29 sema->tag.id = ++thctx.sema_id;
30 sema->event.attr = sema_params->attr;
31 sema->event.option = sema_params->option;
32 sema->count = sema_params->initial;
33 sema->initial_count = sema_params->initial;
34 sema->max_count = sema_params->max;
36 list_init(&sema->event.waiters);
38 list_insert(&thctx.semaphore, &sema->sema_list);
42 return MAKE_HANDLE(sema);
45int DeleteSema(
int semid)
53 return KE_ILLEGAL_CONTEXT;
58 sema = HANDLE_PTR(semid);
59 if (!HANDLE_VERIFY(semid, TAG_SEMA)) {
61 return KE_UNKNOWN_SEMID;
64 list_for_each_safe (waiter, &sema->event.waiters, queue) {
65 waiter->saved_regs->v0 = KE_WAIT_DELETE;
66 waiter->status = THS_READY;
67 list_remove(&waiter->queue);
68 readyq_insert_back(waiter);
71 waiter_count = sema->event.waiter_count;
72 list_remove(&sema->sema_list);
73 heap_free(&sema->tag);
76 thctx.run_next = NULL;
77 return thread_leave(KE_OK, 0, state, 0);
85int SignalSema(
int semid)
92 return KE_ILLEGAL_CONTEXT;
97 sema = HANDLE_PTR(semid);
98 if (!HANDLE_VERIFY(semid, TAG_SEMA)) {
100 return KE_UNKNOWN_SEMID;
103 if (sema->event.waiter_count > 0) {
104 thread = list_first_entry(&sema->event.waiters,
struct thread, queue);
105 sema->event.waiter_count--;
106 list_remove(&
thread->queue);
107 thread->status = THS_READY;
109 return thread_start(
thread, state);
112 if (sema->count >= sema->max_count) {
124int iSignalSema(
int semid)
130 return KE_ILLEGAL_CONTEXT;
133 sema = HANDLE_PTR(semid);
134 if (!HANDLE_VERIFY(semid, TAG_SEMA)) {
135 return KE_UNKNOWN_SEMID;
138 if (sema->event.waiter_count > 0) {
139 thread = list_first_entry(&sema->event.waiters,
struct thread, queue);
140 sema->event.waiter_count--;
141 list_remove(&
thread->queue);
142 thread->saved_regs->v0 = KE_OK;
143 thread->status = THS_READY;
144 readyq_insert_back(
thread);
150 if (sema->count >= sema->max_count) {
159int WaitSema(
int semid)
166 return KE_ILLEGAL_CONTEXT;
169 if (
CpuSuspendIntr(&state) == KE_CPUDI && (thctx.debug_flags & 8)) {
170 Kprintf(
"WARNING: DelayThread KE_CAN_NOT_WAIT\n");
173 check_thread_stack();
175 sema = HANDLE_PTR(semid);
176 if (!HANDLE_VERIFY(semid, TAG_SEMA)) {
178 return KE_UNKNOWN_SEMID;
181 thread = thctx.current_thread;
183 if (sema->count >= 1) {
189 thread->status = THS_WAIT;
190 thread->wait_type = TSW_SEMA;
191 thread->wait_event = &sema->event;
192 thctx.run_next = NULL;
193 sema->event.waiter_count++;
195 if (sema->event.attr & SA_THPRI) {
198 waitlist_insert(
thread, &sema->event,
thread->priority);
200 list_insert(&sema->event.waiters, &
thread->queue);
203 return thread_leave(KE_OK, 0, state, 1);
206int PollSema(
int semid)
212 return KE_ILLEGAL_CONTEXT;
217 sema = HANDLE_PTR(semid);
218 if (!HANDLE_VERIFY(semid, TAG_SEMA)) {
220 return KE_UNKNOWN_SEMID;
223 if (sema->count == 0) {
240 return KE_ILLEGAL_CONTEXT;
245 sema = HANDLE_PTR(semid);
246 if (!HANDLE_VERIFY(semid, TAG_SEMA)) {
248 return KE_UNKNOWN_SEMID;
251 sema_get_status(sema,
info);
263 return KE_ILLEGAL_CONTEXT;
266 sema = HANDLE_PTR(semid);
267 if (!HANDLE_VERIFY(semid, TAG_SEMA)) {
268 return KE_UNKNOWN_SEMID;
271 sema_get_status(sema,
info);
278 info->attr = sema->event.attr;
279 info->current = sema->count;
280 info->max = sema->max_count;
281 info->initial = sema->initial_count;
282 info->numWaitThreads = sema->event.waiter_count;
283 info->option = sema->event.option;
int CpuResumeIntr(int state)
int QueryIntrContext(void)
int CpuSuspendIntr(int *state)