Module: xenomai-3 Branch: master Commit: b9d2168c3567f86e5721a71d0046ac243a2a45a4 URL: http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=b9d2168c3567f86e5721a71d0046ac243a2a45a4
Author: Philippe Gerum <r...@xenomai.org> Date: Wed Mar 18 20:59:40 2015 +0100 cobalt/posix/sem: use resource management API --- kernel/cobalt/posix/nsem.c | 28 ++++----- kernel/cobalt/posix/process.c | 8 +-- kernel/cobalt/posix/sem.c | 125 ++++++++++++++++++----------------------- kernel/cobalt/posix/sem.h | 13 ++--- 4 files changed, 74 insertions(+), 100 deletions(-) diff --git a/kernel/cobalt/posix/nsem.c b/kernel/cobalt/posix/nsem.c index 4ed2e80..0cc6860 100644 --- a/kernel/cobalt/posix/nsem.c +++ b/kernel/cobalt/posix/nsem.c @@ -28,15 +28,14 @@ DEFINE_PRIVATE_XNLOCK(named_sem_lock); -struct named_sem { +struct cobalt_named_sem { struct cobalt_sem *sem; struct cobalt_sem_shadow __user *usem; unsigned int refs; struct xnid id; - struct filename *filename; }; -static struct named_sem * +static struct cobalt_named_sem * sem_search(struct cobalt_process *process, xnhandle_t handle) { struct xnid *i; @@ -45,7 +44,7 @@ sem_search(struct cobalt_process *process, xnhandle_t handle) if (i == NULL) return NULL; - return container_of(i, struct named_sem, id); + return container_of(i, struct cobalt_named_sem, id); } static struct cobalt_sem_shadow __user * @@ -56,7 +55,7 @@ sem_open(struct cobalt_process *process, { const char *name = filename->name; struct cobalt_sem_shadow shadow; - struct named_sem *u, *v; + struct cobalt_named_sem *u, *v; struct cobalt_sem *sem; xnhandle_t handle; spl_t s; @@ -117,6 +116,7 @@ sem_open(struct cobalt_process *process, __cobalt_sem_destroy(shadow.handle); return ERR_PTR(-EFAULT); } + sem->pathname = filename; handle = shadow.handle; break; @@ -131,7 +131,6 @@ sem_open(struct cobalt_process *process, u->sem = sem; u->usem = ushadow; u->refs = 1; - u->filename = filename; xnlock_get_irqsave(&named_sem_lock, s); v = sem_search(process, handle); @@ -141,7 +140,6 @@ sem_open(struct cobalt_process *process, xnlock_get_irqsave(&nklock, s); --sem->refs; xnlock_put_irqrestore(&nklock, s); - putname(filename); xnfree(u); u = v; @@ -157,7 +155,7 @@ sem_open(struct cobalt_process *process, static int sem_close(struct cobalt_process *process, xnhandle_t handle) { - struct named_sem *u; + struct cobalt_named_sem *u; spl_t s; int err; @@ -178,7 +176,6 @@ static int sem_close(struct cobalt_process *process, xnhandle_t handle) __cobalt_sem_destroy(handle); - putname(u->filename); xnfree(u); return 1; @@ -187,12 +184,6 @@ static int sem_close(struct cobalt_process *process, xnhandle_t handle) return err; } -void __cobalt_sem_unlink(xnhandle_t handle) -{ - if (__cobalt_sem_destroy(handle) == -EBUSY) - xnregistry_unlink(xnregistry_key(handle)); -} - struct cobalt_sem_shadow __user * __cobalt_sem_open(struct cobalt_sem_shadow __user *usm, const char __user *u_name, @@ -264,7 +255,8 @@ static inline int sem_unlink(const char *name) if (ret == -EWOULDBLOCK) return -ENOENT; - __cobalt_sem_unlink(handle); + if (__cobalt_sem_destroy(handle) == -EBUSY) + xnregistry_unlink(xnregistry_key(handle)); return 0; } @@ -289,9 +281,9 @@ COBALT_SYSCALL(sem_unlink, lostage, static void reclaim_named_sem(void *arg, struct xnid *i) { struct cobalt_process *process = arg; - struct named_sem *u; + struct cobalt_named_sem *u; - u = container_of(i, struct named_sem, id); + u = container_of(i, struct cobalt_named_sem, id); u->refs = 1; sem_close(process, xnid_key(i)); } diff --git a/kernel/cobalt/posix/process.c b/kernel/cobalt/posix/process.c index f473dc1..c2d65f0 100644 --- a/kernel/cobalt/posix/process.c +++ b/kernel/cobalt/posix/process.c @@ -1404,14 +1404,14 @@ static void cobalt_process_detach(void *arg) { struct cobalt_process *process = arg; + cobalt_nsem_reclaim(process); + cobalt_timer_reclaim(process); + cobalt_sched_reclaim(process); cobalt_reclaim_resource(process, cobalt_cond_reclaim, cond); cobalt_reclaim_resource(process, cobalt_mutex_reclaim, mutex); cobalt_reclaim_resource(process, cobalt_event_reclaim, event); cobalt_reclaim_resource(process, cobalt_monitor_reclaim, monitor); - cobalt_nsem_reclaim(process); - cobalt_timer_reclaim(process); - cobalt_sem_reclaim(process); - cobalt_sched_reclaim(process); + cobalt_reclaim_resource(process, cobalt_sem_reclaim, sem); detach_process(process); /* * The cobalt_process descriptor release may be deferred until diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c index 3f18a4c..e63967f 100644 --- a/kernel/cobalt/posix/sem.c +++ b/kernel/cobalt/posix/sem.c @@ -40,17 +40,17 @@ int __cobalt_sem_destroy(xnhandle_t handle) sem = xnregistry_lookup(handle, NULL); if (!cobalt_obj_active(sem, COBALT_SEM_MAGIC, typeof(*sem))) { ret = -EINVAL; - goto unlock_error; + goto fail; } + if (--sem->refs) { ret = -EBUSY; - unlock_error: - xnlock_put_irqrestore(&nklock, s); - return ret; + goto fail; } cobalt_mark_deleted(sem); - list_del(&sem->link); + xnregistry_remove(sem->resnode.handle); + cobalt_del_resource(&sem->resnode); if (xnsynch_destroy(&sem->synchbase) == XNSYNCH_RESCHED) { xnsched_run(); ret = 1; @@ -58,13 +58,19 @@ int __cobalt_sem_destroy(xnhandle_t handle) xnlock_put_irqrestore(&nklock, s); + if (sem->pathname) + putname(sem->pathname); + cobalt_umm_free(&cobalt_ppd_get(!!(sem->flags & SEM_PSHARED))->umm, sem->state); - xnregistry_remove(sem->handle); xnfree(sem); return ret; +fail: + xnlock_put_irqrestore(&nklock, s); + + return ret; } struct cobalt_sem * @@ -73,9 +79,9 @@ __cobalt_sem_init(const char *name, struct cobalt_sem_shadow *sm, { struct cobalt_sem_state *state; struct cobalt_sem *sem, *osem; - struct cobalt_resources *rs; struct cobalt_ppd *sys_ppd; - int ret, sflags; + int ret, sflags, pshared; + struct list_head *semq; spl_t s; if ((flags & SEM_PULSE) != 0 && value > 0) { @@ -89,7 +95,8 @@ __cobalt_sem_init(const char *name, struct cobalt_sem_shadow *sm, goto out; } - sys_ppd = cobalt_ppd_get(!!(flags & SEM_PSHARED)); + pshared = !!(flags & SEM_PSHARED); + sys_ppd = cobalt_ppd_get(pshared); state = cobalt_umm_alloc(&sys_ppd->umm, sizeof(*state)); if (state == NULL) { ret = -EAGAIN; @@ -98,45 +105,28 @@ __cobalt_sem_init(const char *name, struct cobalt_sem_shadow *sm, xnlock_get_irqsave(&nklock, s); - rs = cobalt_current_resources(!!(flags & SEM_PSHARED)); - if (list_empty(&rs->semq)) - goto do_init; - - if (sm->magic != COBALT_SEM_MAGIC && - sm->magic != COBALT_NAMED_SEM_MAGIC) - goto do_init; - - /* - * Make sure we are not reinitializing a valid semaphore. As a - * special exception, we allow reinitializing a shared - * anonymous semaphore. Rationale: if the process creating - * such semaphore exits, we may assume that other processes - * sharing that semaphore won't be able to keep on running. - */ - osem = xnregistry_lookup(sm->handle, NULL); - if (!cobalt_obj_active(osem, COBALT_SEM_MAGIC, typeof(*osem))) - goto do_init; - - if ((flags & SEM_PSHARED) == 0 || sm->magic != COBALT_SEM_MAGIC) { - ret = -EBUSY; - goto err_lock_put; + semq = &cobalt_current_resources(pshared)->semq; + if (!list_empty(semq) && + (sm->magic == COBALT_SEM_MAGIC || + sm->magic == COBALT_NAMED_SEM_MAGIC)) { + osem = xnregistry_lookup(sm->handle, NULL); + if (cobalt_obj_active(osem, COBALT_SEM_MAGIC, typeof(*osem))) { + ret = -EBUSY; + goto err_lock_put; + } } - xnlock_put_irqrestore(&nklock, s); - __cobalt_sem_destroy(sm->handle); - xnlock_get_irqsave(&nklock, s); - do_init: if (value > (unsigned)SEM_VALUE_MAX) { ret = -EINVAL; goto err_lock_put; } - ret = xnregistry_enter(name ?: "", sem, &sem->handle, NULL); + ret = xnregistry_enter(name ?: "", sem, &sem->resnode.handle, NULL); if (ret < 0) goto err_lock_put; sem->magic = COBALT_SEM_MAGIC; - list_add_tail(&sem->link, &rs->semq); + cobalt_add_resource(&sem->resnode, sem, pshared); sflags = flags & SEM_FIFO ? 0 : XNSYNCH_PRIO; xnsynch_init(&sem->synchbase, sflags, NULL); @@ -144,17 +134,18 @@ __cobalt_sem_init(const char *name, struct cobalt_sem_shadow *sm, atomic_set(&state->value, value); state->flags = flags; sem->flags = flags; - sem->scope = rs; sem->refs = name ? 2 : 1; + sem->pathname = NULL; sm->magic = name ? COBALT_NAMED_SEM_MAGIC : COBALT_SEM_MAGIC; - sm->handle = sem->handle; + sm->handle = sem->resnode.handle; sm->state_offset = cobalt_umm_offset(&sys_ppd->umm, state); if (flags & SEM_PSHARED) sm->state_offset = -sm->state_offset; xnlock_put_irqrestore(&nklock, s); - trace_cobalt_psem_init(name ?: "anon", sem->handle, flags, value); + trace_cobalt_psem_init(name ?: "anon", + sem->resnode.handle, flags, value); return sem; @@ -187,7 +178,7 @@ static int sem_destroy(struct cobalt_sem_shadow *sm) goto error; } - if (sem_kqueue(sem) != sem->scope) { + if (sem_kqueue(sem) != sem->resnode.scope) { ret = -EPERM; goto error; } @@ -202,7 +193,7 @@ static int sem_destroy(struct cobalt_sem_shadow *sm) cobalt_mark_deleted(sm); xnlock_put_irqrestore(&nklock, s); - ret = __cobalt_sem_destroy(sem->handle); + ret = __cobalt_sem_destroy(sem->resnode.handle); return warn ? ret : 0; @@ -219,7 +210,7 @@ static inline int sem_trywait_inner(struct cobalt_sem *sem) return -EINVAL; #if XENO_DEBUG(USER) - if (sem->scope != sem_kqueue(sem)) + if (sem->resnode.scope != sem_kqueue(sem)) return -EPERM; #endif @@ -241,14 +232,13 @@ static int sem_trywait(xnhandle_t handle) return err; } -static int sem_post_inner(struct cobalt_sem *sem, - struct cobalt_resources *ownq, int bcast) +static int sem_post_inner(struct cobalt_sem *sem, int bcast) { if (sem == NULL || sem->magic != COBALT_SEM_MAGIC) return -EINVAL; #if XENO_DEBUG(USER) - if (ownq && ownq != sem_kqueue(sem)) + if (sem->resnode.scope && sem->resnode.scope != sem_kqueue(sem)) return -EPERM; #endif @@ -291,7 +281,7 @@ static int sem_wait(xnhandle_t handle) if (info & XNRMID) { ret = -EINVAL; } else if (info & XNBREAK) { - sem_post_inner(sem, sem->scope, 0); + sem_post_inner(sem, 0); ret = -EINTR; } out: @@ -371,13 +361,13 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem, static int sem_post(xnhandle_t handle) { - struct cobalt_sem *sm; + struct cobalt_sem *sem; int ret; spl_t s; xnlock_get_irqsave(&nklock, s); - sm = xnregistry_lookup(handle, NULL); - ret = sem_post_inner(sm, sm->scope, 0); + sem = xnregistry_lookup(handle, NULL); + ret = sem_post_inner(sem, 0); xnlock_put_irqrestore(&nklock, s); return ret; @@ -397,7 +387,7 @@ static int sem_getvalue(xnhandle_t handle, int *value) return -EINVAL; } - if (sem->scope != sem_kqueue(sem)) { + if (sem->resnode.scope != sem_kqueue(sem)) { xnlock_put_irqrestore(&nklock, s); return -EPERM; } @@ -510,7 +500,7 @@ COBALT_SYSCALL(sem_destroy, current, COBALT_SYSCALL(sem_broadcast_np, current, (struct cobalt_sem_shadow __user *u_sem)) { - struct cobalt_sem *sm; + struct cobalt_sem *sem; xnhandle_t handle; spl_t s; int err; @@ -519,8 +509,8 @@ COBALT_SYSCALL(sem_broadcast_np, current, trace_cobalt_psem_broadcast(u_sem->handle); xnlock_get_irqsave(&nklock, s); - sm = xnregistry_lookup(handle, NULL); - err = sem_post_inner(sm, sm->scope, 1); + sem = xnregistry_lookup(handle, NULL); + err = sem_post_inner(sem, 1); xnlock_put_irqrestore(&nklock, s); return err; @@ -609,24 +599,17 @@ COBALT_SYSCALL(sem_inquire, current, return ret ?: nrwait; } -void cobalt_sem_reclaim(struct cobalt_process *process) +void cobalt_sem_reclaim(struct cobalt_resnode *node, spl_t s) { - struct cobalt_resources *p = &process->resources; - struct cobalt_sem *sem, *tmp; - spl_t s; - - xnlock_get_irqsave(&nklock, s); - - if (list_empty(&p->semq)) - goto out; + struct cobalt_sem *sem; + xnhandle_t handle; + int named, ret; - list_for_each_entry_safe(sem, tmp, &p->semq, link) { - xnlock_put_irqrestore(&nklock, s); - if (sem->flags & SEM_NAMED) - __cobalt_sem_unlink(sem->handle); - __cobalt_sem_destroy(sem->handle); - xnlock_get_irqsave(&nklock, s); - } -out: + sem = container_of(node, struct cobalt_sem, resnode); + named = (sem->flags & SEM_NAMED) != 0; + handle = node->handle; xnlock_put_irqrestore(&nklock, s); + ret = __cobalt_sem_destroy(handle); + if (named && ret == -EBUSY) + xnregistry_unlink(xnregistry_key(handle)); } diff --git a/kernel/cobalt/posix/sem.h b/kernel/cobalt/posix/sem.h index 56a4da4..a95b6c4 100644 --- a/kernel/cobalt/posix/sem.h +++ b/kernel/cobalt/posix/sem.h @@ -23,19 +23,19 @@ #include <cobalt/kernel/thread.h> #include <cobalt/kernel/registry.h> #include <xenomai/posix/syscall.h> +#include <xenomai/posix/process.h> struct cobalt_process; +struct filename; struct cobalt_sem { unsigned int magic; struct xnsynch synchbase; - /** semq */ - struct list_head link; struct cobalt_sem_state *state; int flags; - struct cobalt_resources *scope; - xnhandle_t handle; unsigned int refs; + struct filename *pathname; + struct cobalt_resnode resnode; }; /* Copied from Linuxthreads semaphore.h. */ @@ -70,8 +70,6 @@ int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem, int __cobalt_sem_destroy(xnhandle_t handle); -void __cobalt_sem_unlink(xnhandle_t handle); - void cobalt_nsem_reclaim(struct cobalt_process *process); struct cobalt_sem * @@ -121,6 +119,7 @@ COBALT_SYSCALL_DECL(sem_inquire, pid_t __user *u_waitlist, size_t waitsz)); -void cobalt_sem_reclaim(struct cobalt_process *process); +void cobalt_sem_reclaim(struct cobalt_resnode *node, + spl_t s); #endif /* !_COBALT_POSIX_SEM_H */ _______________________________________________ Xenomai-git mailing list Xenomai-git@xenomai.org http://www.xenomai.org/mailman/listinfo/xenomai-git