1 /* Author: Domen Puncer <domen@cba.si>. License: WTFPL, see file LICENSE */
10 void sem_init(struct sem
*sem
, int count
)
13 list_init(&sem
->tasks
);
14 lock_init(&sem
->lock
);
17 __attribute__ ((warn_unused_result
)) int down(struct sem
*sem
, u32 timeout
)
19 /* count and list operations are protected by lock */
21 list_add_tail(&sem
->tasks
, ¤t
->waiting
);
23 //printf("%s: %p, count:%i\n", __func__, sem, sem->count);
25 // SMP: while (TAS(&foo)) ;
29 current
->dont_reschedule
= 0;
30 list_del(¤t
->waiting
);
33 //printf("%s: %p, count:%i, ok\n", __func__, sem, sem->count);
39 /* if up() is called here, don't reschedule will be set, and
40 * sched_timeout will return */
42 timeout
= sched_timeout(timeout
);
45 } while (timeout
> 0);
47 list_del(¤t
->waiting
);
48 //printf("%s: %p, count:%i, fail\n", __func__, sem, sem->count);
54 void up(struct sem
*sem
)
59 // SMP: while (TAS(&foo)) ;
60 if (!list_empty(&sem
->tasks
)) {
61 task
= list_entry(sem
->tasks
.next
, struct task
, waiting
);
62 task
->dont_reschedule
= 1;
64 // fprintf(stderr, "waking %s\n", task->name);
68 //printf("%s: %p, count:%i\n", __func__, sem, sem->count);
71 /* also call scheduler? well... maybe, but only !in_interrupt() */
73 /* must call scheduler, to get the woken task running */
75 arch_sched_next_interrupt(1); /* now, this is ok, since we only schedule it. but it's still some delay that i don't like */
77 // arch_task_switch(task);
78 // ^ this is problematic... if up() is called from interrupt, then it's not quite normal to call SVC here, were not in task context! fuck
82 /* mutexes are similar... except that multiple consecutive up() will only enable one down() to succeed */
83 // TODO rewrite w/o lock if possible - but it's needed for list? maybe not
84 void mutex_init(struct mutex
*mutex
, int locked
)
86 mutex
->locked
= locked
;
87 list_init(&mutex
->tasks
);
88 lock_init(&mutex
->lock
);
91 __attribute__ ((warn_unused_result
)) int mutex_down(struct mutex
*mutex
, u32 timeout
)
93 /* count and list operations are protected by lock */
95 list_add_tail(&mutex
->tasks
, ¤t
->waiting
);
101 current
->dont_reschedule
= 0;
102 list_del(¤t
->waiting
);
103 unlock(&mutex
->lock
);
106 unlock(&mutex
->lock
);
108 /* if up() is called here, don't reschedule will be set, and
109 * sched_timeout will return */
111 timeout
= sched_timeout(timeout
);
114 } while (timeout
> 0);
116 list_del(¤t
->waiting
);
117 unlock(&mutex
->lock
);
122 __attribute__ ((warn_unused_result
)) int mutex_downtry(struct mutex
*mutex
)
124 /* count and list operations are protected by lock */
127 if (!mutex
->locked
) {
130 unlock(&mutex
->lock
);
134 unlock(&mutex
->lock
);
139 void mutex_up(struct mutex
*mutex
)
144 if (!list_empty(&mutex
->tasks
)) {
145 task
= list_entry(mutex
->tasks
.next
, struct task
, waiting
);
146 task
->dont_reschedule
= 1;
151 unlock(&mutex
->lock
);
153 /* must call scheduler, to get the woken task running */
155 arch_sched_next_interrupt(1); /* now, this is ok, since we only schedule it. but it's still some delay that i don't like */