mirror of
https://github.com/drasko/codezero.git
synced 2026-02-28 01:33:13 +01:00
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:
@@ -56,7 +56,7 @@ BEGIN_PROC(__l4_mutex_unlock)
|
||||
swp r2, r3, [r0]
|
||||
cmp r2, r1 @ Check lock had original tid value
|
||||
movne r0, #L4_MUTEX_CONTENDED @ Indicate contention
|
||||
movne r0, #L4_MUTEX_SUCCESS @ Indicate no contention
|
||||
moveq r0, #L4_MUTEX_SUCCESS @ Indicate no contention
|
||||
cmp r2, #L4_MUTEX_UNLOCKED @ Or - was it already unlocked?
|
||||
1:
|
||||
beq 1b @ If so busy-spin to indicate bug.
|
||||
|
||||
@@ -50,18 +50,28 @@ void l4_mutex_init(struct l4_mutex *m)
|
||||
int l4_mutex_lock(struct l4_mutex *m)
|
||||
{
|
||||
l4id_t tid = self_tid();
|
||||
int err;
|
||||
|
||||
while(__l4_mutex_lock(m, tid) == L4_MUTEX_CONTENDED)
|
||||
l4_mutex_control(&m->lock, L4_MUTEX_LOCK);
|
||||
while(__l4_mutex_lock(m, tid) == L4_MUTEX_CONTENDED) {
|
||||
if ((err = l4_mutex_control(&m->lock, L4_MUTEX_LOCK)) < 0) {
|
||||
printf("%s: Error: %d\n", __FUNCTION__, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int l4_mutex_unlock(struct l4_mutex *m)
|
||||
{
|
||||
l4id_t tid = self_tid();
|
||||
int err;
|
||||
|
||||
if (__l4_mutex_unlock(m, tid) == L4_MUTEX_CONTENDED)
|
||||
l4_mutex_control(&m->lock, L4_MUTEX_UNLOCK);
|
||||
if (__l4_mutex_unlock(m, tid) == L4_MUTEX_CONTENDED) {
|
||||
if ((err = l4_mutex_control(&m->lock, L4_MUTEX_UNLOCK)) < 0) {
|
||||
printf("%s: Error: %d\n", __FUNCTION__, err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,9 +52,9 @@ void main(void)
|
||||
ipc_full_test();
|
||||
ipc_extended_test();
|
||||
}
|
||||
// if (parent_of_all == getpid()) {
|
||||
// user_mutex_test();
|
||||
// }
|
||||
if (parent_of_all == getpid()) {
|
||||
user_mutex_test();
|
||||
}
|
||||
exectest();
|
||||
|
||||
while (1)
|
||||
|
||||
@@ -68,11 +68,10 @@ int user_mutex_test(void)
|
||||
|
||||
/* Initialize buffer with unique child value */
|
||||
printf("Initializing shared page with child values.\n");
|
||||
BUG();
|
||||
shared_page->child_has_run = 0;
|
||||
shared_page->parent_has_run = 0;
|
||||
for (int i = 0; i < buf_size; i++)
|
||||
shared_page->page_rest[i] = 'c';
|
||||
shared_page->page_rest[i] = 0;
|
||||
|
||||
/* Fork the current task */
|
||||
if ((child = fork()) < 0) {
|
||||
@@ -88,17 +87,20 @@ int user_mutex_test(void)
|
||||
/* Child locks and produces */
|
||||
if (child == 0) {
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int x = 0; x < 255; x++) {
|
||||
/* Lock */
|
||||
printf("Child locking page.\n");
|
||||
l4_mutex_lock(&shared_page->mutex);
|
||||
|
||||
printf("Child locked page.\n");
|
||||
|
||||
l4_thread_switch(0);
|
||||
/* Get sample value */
|
||||
char val = shared_page->page_rest[0];
|
||||
//char val = shared_page->page_rest[0];
|
||||
|
||||
/* Write a unique child value to whole buffer */
|
||||
for (int i = 0; i < buf_size; i++) {
|
||||
#if 0
|
||||
/* Check sample is same in all */
|
||||
if (shared_page->page_rest[i] != val) {
|
||||
printf("Sample values dont match. "
|
||||
@@ -107,22 +109,26 @@ int user_mutex_test(void)
|
||||
shared_page->page_rest[i], val);
|
||||
goto out_err;
|
||||
}
|
||||
shared_page->page_rest[i] = 'c';
|
||||
#endif
|
||||
shared_page->page_rest[i]--;
|
||||
}
|
||||
printf("Child produced.\n");
|
||||
printf("Child produced. Unlocking...\n");
|
||||
/* Unlock */
|
||||
l4_mutex_unlock(&shared_page->mutex);
|
||||
printf("Child unlocked page.\n");
|
||||
}
|
||||
/* Sync with the parent */
|
||||
l4_send(parent, L4_IPC_TAG_SYNC);
|
||||
|
||||
/* Parent locks and consumes */
|
||||
} else {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
for (int x = 0; x < 255; x++) {
|
||||
printf("Parent locking page.\n");
|
||||
|
||||
/* Lock the page */
|
||||
l4_mutex_lock(&shared_page->mutex);
|
||||
printf("Parent locked page.\n");
|
||||
l4_thread_switch(0);
|
||||
|
||||
// printf("Parent reading:\n");
|
||||
|
||||
@@ -130,6 +136,7 @@ int user_mutex_test(void)
|
||||
for (int i = 0; i < buf_size; i++) {
|
||||
// printf("%c", shared_page->page_rest[i]);
|
||||
/* Test that child has produced */
|
||||
#if 0
|
||||
if (shared_page->page_rest[i] != 'c') {
|
||||
printf("Child not produced. "
|
||||
"page_rest[%d] = %c, "
|
||||
@@ -138,14 +145,22 @@ int user_mutex_test(void)
|
||||
BUG();
|
||||
goto out_err;
|
||||
}
|
||||
#endif
|
||||
/* Consume the page */
|
||||
shared_page->page_rest[i] = 'P';
|
||||
shared_page->page_rest[i]++;
|
||||
}
|
||||
// printf("\n\n");
|
||||
printf("Parent consumed.\n");
|
||||
printf("Parent consumed. Unlocking...\n");
|
||||
l4_mutex_unlock(&shared_page->mutex);
|
||||
printf("Parent unlocked page.\n");
|
||||
}
|
||||
/* Sync with the child */
|
||||
l4_receive(child);
|
||||
|
||||
printf("Parent checking validity of values.\n");
|
||||
for (int i = 0; i < 255; i++)
|
||||
if (shared_page->page_rest[i] != 0)
|
||||
goto out_err;
|
||||
|
||||
printf("USER MUTEX TEST: -- PASSED --\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user