Mutexes and "fairness" - one task hogs the mutex
Posted: Mon Nov 05, 2012 7:06 am
I've recently implemented mutexes - or at least I hope I have - in my kernel. I'm testing it in part by running two copies of this task/process:
Here's the mutex implementation:
The problem I'm having is that the first process locks the mutex, and essentially holds it forever. Later processes barely have any chance of locking the mutex, since the only chance they'll ever have is when the scheduler switches away from task #1 BETWEEN mutex_unlock() and the mutex_lock() executed soon thereafter.
When a second task does manage to grab the mutex, clearly, THAT task starts hogging it instead.
Is this something to be expected, or should a good OS solve this? And, more importantly, how?
Also, if I'm doing something else wrong, please point that out.
Code: Select all
static mutex_t *test_mutex = NULL;
static void mutex_test(void *data, uint32 length) {
if (test_mutex == NULL)
test_mutex = mutex_create();
while (true) {
mutex_lock(test_mutex);
printk("locked mutex in pid %d @ %u\n", getpid(), gettickcount());
sleep(500); // milliseconds
mutex_unlock(test_mutex);
printk("unlocked mutex in pid %d @ %u\n", getpid(), gettickcount());
}
}
Code: Select all
void mutex_lock(mutex_t *mutex) {
assert(mutex != NULL);
uint8 success = 0;
while (success == 0) {
asm volatile("LOCK BTSL $0, %[mutex];"
"SETNCB %[success];" // sets success to 1 if the mutex was locked; 0 otherwise
:
[mutex]"=m"(mutex->mutex),
[success]"=m"(success)
: : "cc", "memory");
if (success) {
mutex->owner = (task_t *)current_task;
}
else {
if (task_switching)
asm volatile("int $0x7e"); // yield this time slice
}
}
}
void mutex_unlock(mutex_t *mutex) {
assert(mutex != NULL);
assert(mutex->mutex != 0); // mutex is locked
assert(mutex->owner == current_task);
mutex->mutex = 0;
mutex->owner = NULL;
}
When a second task does manage to grab the mutex, clearly, THAT task starts hogging it instead.
Is this something to be expected, or should a good OS solve this? And, more importantly, how?
Also, if I'm doing something else wrong, please point that out.