diff --git a/init/init.c b/init/init.c index b4a15e9..00be603 100644 --- a/init/init.c +++ b/init/init.c @@ -24,12 +24,28 @@ void app_proc1 (void) { process_quit (); } +void app_proc2 (void) { + letter = 'd'; + + for (;;) { + mutex_lock (MUTEX); + + for (int i = 0; i < 3; i++) + test (letter); + + mutex_unlock (MUTEX); + } + + process_quit (); +} + void app_main (void) { mutex_create (MUTEX); letter = 'a'; process_spawn (&app_proc1); + process_spawn (&app_proc2); for (;;) { mutex_lock (MUTEX); diff --git a/kernel/proc/mutex.c b/kernel/proc/mutex.c index d99596e..b063416 100644 --- a/kernel/proc/mutex.c +++ b/kernel/proc/mutex.c @@ -44,13 +44,15 @@ void proc_mutexes_cleanup (struct proc* proc) { spin_unlock (&proc->procgroup->lock, &ctxpg); } -void proc_cleanup_resource_mutex (struct proc_resource* resource) { +bool proc_cleanup_resource_mutex (struct proc_resource* resource) { struct proc_mutex* mutex = &resource->u.mutex; spin_lock_ctx_t ctxmt, ctxsq; spin_lock (&mutex->resource->lock, &ctxmt); spin_lock (&mutex->suspension_q.lock, &ctxsq); + bool reschedule = PROC_NO_RESCHEDULE; + while (mutex->suspension_q.proc_list != NULL) { struct list_node_link* node = mutex->suspension_q.proc_list; struct proc_sq_entry* sq_entry = list_entry (node, struct proc_sq_entry, sq_link); @@ -60,7 +62,7 @@ void proc_cleanup_resource_mutex (struct proc_resource* resource) { spin_unlock (&mutex->suspension_q.lock, &ctxsq); spin_unlock (&mutex->resource->lock, &ctxmt); - proc_sq_resume (suspended_proc, sq_entry); + reschedule = reschedule || proc_sq_resume (suspended_proc, sq_entry); /* reacquire */ spin_lock (&mutex->resource->lock, &ctxmt); @@ -72,23 +74,23 @@ void proc_cleanup_resource_mutex (struct proc_resource* resource) { spin_unlock (&mutex->suspension_q.lock, &ctxsq); spin_unlock (&mutex->resource->lock, &ctxmt); + + return reschedule; } -void proc_mutex_lock (struct proc* proc, struct proc_mutex* mutex) { +bool proc_mutex_lock (struct proc* proc, struct proc_mutex* mutex) { spin_lock_ctx_t ctxmt; - for (;;) { - spin_lock (&mutex->resource->lock, &ctxmt); + spin_lock (&mutex->resource->lock, &ctxmt); - if (!mutex->locked || mutex->owner == proc) { - mutex->locked = true; - mutex->owner = proc; - spin_unlock (&mutex->resource->lock, &ctxmt); - return; - } - - proc_sq_suspend (proc, &mutex->suspension_q, &mutex->resource->lock, &ctxmt); + if (!mutex->locked || mutex->owner == proc) { + mutex->locked = true; + mutex->owner = proc; + spin_unlock (&mutex->resource->lock, &ctxmt); + return PROC_NO_RESCHEDULE; } + + return proc_sq_suspend (proc, &mutex->suspension_q, &mutex->resource->lock, &ctxmt); } bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex) { @@ -98,7 +100,7 @@ bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex) { if (mutex->owner != proc) { spin_unlock (&mutex->resource->lock, &ctxmt); - return false; + return PROC_NO_RESCHEDULE; } spin_lock (&mutex->suspension_q.lock, &ctxsq); @@ -115,9 +117,7 @@ bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex) { spin_unlock (&mutex->suspension_q.lock, &ctxsq); spin_unlock (&mutex->resource->lock, &ctxmt); - proc_sq_resume (resumed_proc, sq_entry); - - return true; + return proc_sq_resume (resumed_proc, sq_entry); } mutex->locked = false; @@ -126,5 +126,5 @@ bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex) { spin_unlock (&mutex->suspension_q.lock, &ctxsq); spin_unlock (&mutex->resource->lock, &ctxmt); - return true; + return PROC_NEED_RESCHEDULE; } diff --git a/kernel/proc/mutex.h b/kernel/proc/mutex.h index 3ba0d09..70c87de 100644 --- a/kernel/proc/mutex.h +++ b/kernel/proc/mutex.h @@ -15,8 +15,8 @@ struct proc_mutex { struct proc* owner; }; -void proc_cleanup_resource_mutex (struct proc_resource* resource); -void proc_mutex_lock (struct proc* proc, struct proc_mutex* mutex); +bool proc_cleanup_resource_mutex (struct proc_resource* resource); +bool proc_mutex_lock (struct proc* proc, struct proc_mutex* mutex); bool proc_mutex_unlock (struct proc* proc, struct proc_mutex* mutex); void proc_mutexes_cleanup (struct proc* proc); diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index bba14ad..a6fb984 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -17,6 +17,9 @@ #include /* USTACK_SIZE */ #endif +#define PROC_NEED_RESCHEDULE true +#define PROC_NO_RESCHEDULE false + /* process states */ #define PROC_READY 0 #define PROC_DEAD 1 diff --git a/kernel/proc/resource.c b/kernel/proc/resource.c index 1d38932..6bb7b54 100644 --- a/kernel/proc/resource.c +++ b/kernel/proc/resource.c @@ -51,7 +51,9 @@ struct proc_resource* proc_create_resource_mutex (struct procgroup* procgroup, i return resource; } -void proc_delete_resource (struct proc_resource* resource) { - resource->ops.cleanup (resource); +bool proc_delete_resource (struct proc_resource* resource) { + bool reschedule = resource->ops.cleanup (resource); free (resource); + + return reschedule; } diff --git a/kernel/proc/resource.h b/kernel/proc/resource.h index 7e83627..f57f207 100644 --- a/kernel/proc/resource.h +++ b/kernel/proc/resource.h @@ -21,12 +21,12 @@ struct proc_resource { struct proc_mutex mutex; } u; struct { - void (*cleanup) (struct proc_resource* resource); + bool (*cleanup) (struct proc_resource* resource); } ops; }; struct proc_resource* proc_find_resource (struct procgroup* procgroup, int rid); struct proc_resource* proc_create_resource_mutex (struct procgroup* procgroup, int rid); -void proc_delete_resource (struct proc_resource* resource); +bool proc_delete_resource (struct proc_resource* resource); #endif // _KERNEL_PROC_RESOURCE_H diff --git a/kernel/proc/suspension_q.c b/kernel/proc/suspension_q.c index aee909b..a634ba2 100644 --- a/kernel/proc/suspension_q.c +++ b/kernel/proc/suspension_q.c @@ -8,7 +8,7 @@ #include #include -void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock_t* resource_lock, +bool proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock_t* resource_lock, spin_lock_ctx_t* ctxrl) { spin_lock_ctx_t ctxpr, ctxcpu, ctxsq; struct cpu* cpu = proc->cpu; @@ -16,7 +16,7 @@ void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock struct proc_sq_entry* sq_entry = malloc (sizeof (*sq_entry)); if (!sq_entry) { spin_unlock (resource_lock, ctxrl); - return; + return PROC_NO_RESCHEDULE; } sq_entry->proc = proc; @@ -48,10 +48,10 @@ void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock spin_unlock (&proc->lock, &ctxpr); spin_unlock (&cpu->lock, &ctxcpu); - cpu_request_sched (cpu); + return PROC_NEED_RESCHEDULE; } -void proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry) { +bool proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry) { spin_lock_ctx_t ctxsq, ctxpr, ctxcpu; struct cpu* cpu = cpu_find_lightest (); struct proc_suspension_q* sq = sq_entry->sq; @@ -80,7 +80,7 @@ void proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry) { free (sq_entry); - cpu_request_sched (cpu); + return PROC_NEED_RESCHEDULE; } void proc_sqs_cleanup (struct proc* proc) { diff --git a/kernel/proc/suspension_q.h b/kernel/proc/suspension_q.h index 0accd79..7e86e63 100644 --- a/kernel/proc/suspension_q.h +++ b/kernel/proc/suspension_q.h @@ -19,8 +19,8 @@ struct proc_sq_entry { }; void proc_sqs_cleanup (struct proc* proc); -void proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock_t* resource_lock, +bool proc_sq_suspend (struct proc* proc, struct proc_suspension_q* sq, spin_lock_t* resource_lock, spin_lock_ctx_t* ctxrl); -void proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry); +bool proc_sq_resume (struct proc* proc, struct proc_sq_entry* sq_entry); #endif // _KERNEL_PROC_SUSPENTION_Q_H diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index 78121f1..292445b 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -123,7 +123,8 @@ DEFINE_SYSCALL (sys_mutex_delete) { if (mutex_resource == NULL) return SYSRESULT (-ST_NOT_FOUND); - proc_delete_resource (mutex_resource); + if (proc_delete_resource (mutex_resource) == PROC_NEED_RESCHEDULE) + proc_sched (); return SYSRESULT (ST_OK); } @@ -137,7 +138,8 @@ DEFINE_SYSCALL (sys_mutex_lock) { if (mutex_resource == NULL) return SYSRESULT (-ST_NOT_FOUND); - proc_mutex_lock (proc, &mutex_resource->u.mutex); + if (proc_mutex_lock (proc, &mutex_resource->u.mutex) == PROC_NEED_RESCHEDULE) + proc_sched (); return SYSRESULT (ST_OK); } @@ -151,8 +153,10 @@ DEFINE_SYSCALL (sys_mutex_unlock) { if (mutex_resource == NULL) return SYSRESULT (-ST_NOT_FOUND); - return SYSRESULT (proc_mutex_unlock (proc, &mutex_resource->u.mutex) ? ST_OK - : -ST_PERMISSION_ERROR); + if (proc_mutex_unlock (proc, &mutex_resource->u.mutex) == PROC_NEED_RESCHEDULE) + proc_sched (); + + return SYSRESULT (ST_OK); } static syscall_handler_func_t handler_table[] = {