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