diff options
-rw-r--r-- | include/sys/schedule.h | 2 | ||||
-rw-r--r-- | include/util/mutex.h | 4 | ||||
-rw-r--r-- | kernel/sys/schedule.c | 2 | ||||
-rw-r--r-- | kernel/util/mutex.c | 68 |
4 files changed, 23 insertions, 53 deletions
diff --git a/include/sys/schedule.h b/include/sys/schedule.h index d03d39f..7ffe716 100644 --- a/include/sys/schedule.h +++ b/include/sys/schedule.h @@ -25,7 +25,7 @@ struct Thread { void* mptr; unsigned long offset; unsigned char old_priority; - unsigned char c_reserved; + unsigned char highest_mutex; unsigned short s_reserved; }; diff --git a/include/util/mutex.h b/include/util/mutex.h index a52e62e..cef4c60 100644 --- a/include/util/mutex.h +++ b/include/util/mutex.h @@ -20,14 +20,14 @@ struct Mutex { struct MutexManager { struct Queue free; - struct Queue used; + unsigned long used_mutexes; }; void mutex_init(void); void uart_mutexes(void); struct Mutex* create_mutex(void* addr); unsigned char delete_mutex(struct Mutex* m); -void lock_mutex(struct Mutex* m); +unsigned char lock_mutex(struct Mutex* m); void unlock_mutex(struct Mutex* m); #endif diff --git a/kernel/sys/schedule.c b/kernel/sys/schedule.c index 3157c5d..142ffaf 100644 --- a/kernel/sys/schedule.c +++ b/kernel/sys/schedule.c @@ -21,6 +21,7 @@ void init_scheduler(void) usrloopthread.old_priority = -1; usrloopthread.status = THREAD_READY; usrloopthread.offset = -1; + usrloopthread.highest_mutex = 0; scheduler.rthread = &usrloopthread; // Initialize Scheduling Queues @@ -56,6 +57,7 @@ void init_scheduler(void) struct Thread* t = &threads[i]; t->offset = i; t->sp_base = 0x20000000 - STACK_SIZE*i; + t->highest_mutex = 0; thread_entries[i].value = t; thread_entries[i].next = &thread_entries[(i+1)]; thread_entries[i].entry_type = VALUE_ENTRY; diff --git a/kernel/util/mutex.c b/kernel/util/mutex.c index 8e85f8f..997d85d 100644 --- a/kernel/util/mutex.c +++ b/kernel/util/mutex.c @@ -21,13 +21,6 @@ void mutex_init(void) mutex_manager.free.end.next = &mutex_entries[MAX_MUTEXS-1]; mutex_entries[MAX_MUTEXS-1].next = &mutex_manager.free.end; mutex_manager.free.end.entry_type = END_ENTRY; - // Initialize In-use Mutexs - mutex_manager.used.start.value = 0; - mutex_manager.used.start.next = &mutex_manager.used.end; - mutex_manager.used.start.entry_type = START_ENTRY; - mutex_manager.used.end.value = 0; - mutex_manager.used.end.next = &mutex_manager.used.start; - mutex_manager.used.end.entry_type = END_ENTRY; } struct Mutex* create_mutex(void* addr) @@ -38,70 +31,45 @@ struct Mutex* create_mutex(void* addr) struct Mutex* m = e->value; m->pid = 0; m->addr = addr; - push_to_queue(e, &mutex_manager.used); + mutex_manager.used_mutexes++; return e->value; } unsigned char delete_mutex(struct Mutex* m) { - struct Entry* entry = find_value(m, &mutex_manager.used); - if (entry == 0) + unsigned long spacing = (unsigned long)&mutexs[1] - (unsigned long)&mutexs[0]; + unsigned long difference = (unsigned long)m - (unsigned long)&mutexs[0]; + unsigned long index = difference/spacing; + if (index >= MAX_MUTEXS) return 1; - // Remove it from the queue - struct Entry* theentry = remove_next_from_queue(entry); + struct Entry* entry = &mutex_entries[index]; // Add it to the free queue - prepend_to_queue(theentry, &mutex_manager.free); + prepend_to_queue(entry, &mutex_manager.free); return 0; } void uart_mutexes(void) { - struct Entry* entry = mutex_manager.used.start.next; - while (entry->entry_type == VALUE_ENTRY) - { - struct Mutex* m = entry->value; - uart_hex((unsigned long)m); - uart_char(' '); - uart_hex(m->pid); - uart_char(' '); - uart_hexn((unsigned long)m->addr); - entry = entry->next; - } - unsigned long count = 0; - entry = mutex_manager.free.start.next; - while (entry->entry_type == VALUE_ENTRY) { - count++; - entry = entry->next; - } - uart_hexn(count); + uart_hexn(mutex_manager.used_mutexes); } -void lock_mutex(struct Mutex* m) +unsigned char lock_mutex(struct Mutex* m) { struct Thread* rthread = scheduler.rthread; - unsigned long rpid = rthread->pid; unsigned long mode = getmode() & 0x1F; if (mode == 0x10) { - // Find this mutex - struct Entry* mentry = find_value(m, &mutex_manager.used); + unsigned long spacing = (unsigned long)&mutexs[1] - (unsigned long)&mutexs[0]; + unsigned long difference = (unsigned long)m - (unsigned long)&mutexs[0]; + unsigned long index = difference/spacing; // If it is not a managed mutex, break away - if (mentry == 0) - return; - struct Entry* entry = mutex_manager.used.start.next; - // Ensure this thread locks all mutexs sequentially - // To avoid a deadlock - while (entry->entry_type == VALUE_ENTRY) { - struct Mutex* vmutex = entry->value; - // If this thread had locked it - // Toggle the lock to prevent deadlock - if (vmutex->pid == rpid) { - sys1(SYS_UNLOCK, vmutex); - sys1(SYS_LOCK, vmutex); - } - entry = entry->next; - } + if (index >= MAX_MUTEXS) + return 1; + if ((unsigned char) index > rthread->highest_mutex) + return 2; sys1(SYS_LOCK, m); + return 0; } + return 3; } void unlock_mutex(struct Mutex* m) |