Mutex implementation almost working.

- Fixed a wrong instruction in mutex.S user library
- Added support for blocking lock/unlock
- Divided waiting into wait_on_prepare and wait_on_prepared_wait
  so that mutex_control lock is released after getting in the waitqueue.
- Declaring waitqueue on the stack should be done outside wait_on_prepare

Issues:
- Tests can be simplified for atomic data access instead of producer/consumer.
- kmalloc variable sized memory caches are not freed properly. Currently only the
  last slot can be freed, occupied correctly. it should be done in any slot, i.e.
  1, 2, 3, 4 instead of just 5.
- Need to add a mutex to kmalloc.
This commit is contained in:
Bahadir Balban
2009-06-01 14:11:40 +03:00
parent 2bd26ce684
commit 33200c92df
8 changed files with 172 additions and 38 deletions

View File

@@ -35,14 +35,51 @@ void task_unset_wqh(struct ktcb *task)
}
/*
* Initiate wait on current task that
* has already been placed in a waitqueue
*/
int wait_on_prepared_wait(void)
{
/* Simply scheduling should initate wait */
schedule();
/* Did we wake up normally or get interrupted */
if (current->flags & TASK_INTERRUPTED) {
current->flags &= ~TASK_INTERRUPTED;
return -EINTR;
}
/* No errors */
return 0;
}
/*
* Do all preparations to sleep but return without sleeping.
* This is useful if the task needs to get in the waitqueue before
* it releases a lock.
*/
int wait_on_prepare(struct waitqueue_head *wqh, struct waitqueue *wq)
{
spin_lock(&wqh->slock);
wqh->sleepers++;
list_add_tail(&wq->task_list, &wqh->task_list);
task_set_wqh(current, wqh, wq);
sched_prepare_sleep();
printk("(%d) waiting on wqh at: 0x%p\n",
current->tid, wqh);
spin_unlock(&wqh->slock);
return 0;
}
/* Sleep without any condition */
int wait_on(struct waitqueue_head *wqh)
{
CREATE_WAITQUEUE_ON_STACK(wq, current);
spin_lock(&wqh->slock);
task_set_wqh(current, wqh, &wq);
wqh->sleepers++;
list_add_tail(&wq.task_list, &wqh->task_list);
task_set_wqh(current, wqh, &wq);
sched_prepare_sleep();
printk("(%d) waiting on wqh at: 0x%p\n",
current->tid, wqh);
@@ -95,10 +132,10 @@ void wake_up(struct waitqueue_head *wqh, unsigned int flags)
struct waitqueue,
task_list);
struct ktcb *sleeper = wq->task;
task_unset_wqh(sleeper);
BUG_ON(list_empty(&wqh->task_list));
list_del_init(&wq->task_list);
wqh->sleepers--;
task_unset_wqh(sleeper);
if (flags & WAKEUP_INTERRUPT)
sleeper->flags |= TASK_INTERRUPTED;
printk("(%d) Waking up (%d)\n", current->tid, sleeper->tid);