sem.c
Go to the documentation of this file.00001
00039 #include "sem.h"
00040 #include <cpu/irq.h>
00041 #include <kern/proc.h>
00042 #include <kern/proc_p.h>
00043 #include <kern/signal.h>
00044 #include <cfg/debug.h>
00045
00046 INLINE void sem_verify(struct Semaphore *s)
00047 {
00048 (void)s;
00049 ASSERT(s);
00050 LIST_ASSERT_VALID(&s->wait_queue);
00051 ASSERT(s->nest_count >= 0);
00052 ASSERT(s->nest_count < 128);
00053 }
00054
00055
00059 void sem_init(struct Semaphore *s)
00060 {
00061 LIST_INIT(&s->wait_queue);
00062 s->owner = NULL;
00063 s->nest_count = 0;
00064 }
00065
00066
00078 bool sem_attempt(struct Semaphore *s)
00079 {
00080 bool result = false;
00081
00082 proc_forbid();
00083 sem_verify(s);
00084 if ((!s->owner) || (s->owner == CurrentProcess))
00085 {
00086 s->owner = CurrentProcess;
00087 s->nest_count++;
00088 result = true;
00089 }
00090 proc_permit();
00091
00092 return result;
00093 }
00094
00095
00113 void sem_obtain(struct Semaphore *s)
00114 {
00115 proc_forbid();
00116 sem_verify(s);
00117
00118
00119 if (UNLIKELY(s->owner && (s->owner != CurrentProcess)))
00120 {
00121
00122 ADDTAIL(&s->wait_queue, (Node *)CurrentProcess);
00123
00124
00125
00126
00127
00128
00129 proc_permit();
00130 proc_switch();
00131 }
00132 else
00133 {
00134 ASSERT(LIST_EMPTY(&s->wait_queue));
00135
00136
00137 s->owner = CurrentProcess;
00138 s->nest_count++;
00139 proc_permit();
00140 }
00141 }
00142
00143
00157 void sem_release(struct Semaphore *s)
00158 {
00159 proc_forbid();
00160 sem_verify(s);
00161
00162 ASSERT(s->owner == CurrentProcess);
00163
00164
00165
00166
00167
00168 if (--s->nest_count == 0)
00169 {
00170 Process *proc;
00171
00172
00173 s->owner = NULL;
00174
00175
00176 if (UNLIKELY((proc = (Process *)list_remHead(&s->wait_queue))))
00177 {
00178 s->nest_count = 1;
00179 s->owner = proc;
00180 ATOMIC(SCHED_ENQUEUE(proc));
00181 }
00182 }
00183
00184 proc_permit();
00185 }