Hi Gilles,

while rebasing my half-done ftrace instrumentation over next, I got
stuck reading nsem_open. Find my questions inline:

> static struct __shadow_sem __user *
> nsem_open(struct __shadow_sem __user *ushadow, const char *name, 
>       int oflags, mode_t mode, unsigned value)
> {
>       struct __shadow_sem shadow;
>       struct cobalt_sem *sem;
>       struct nsem *u, *v;
>       xnhandle_t handle;
>       spl_t s;
>       int rc;
> 
>       trace_xn_sys_sem_open(name, oflags, mode, value);
> 
>       if (name[0] != '/' || name[1] == '\0')
>               return ERR_PTR(-EINVAL);
> 
>   retry_bind:
>       rc = xnregistry_bind(&name[1], XN_NONBLOCK, XN_RELATIVE, &handle);
>       switch (rc) {
>       case 0:
>               /* Found */
>               if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
>                       return ERR_PTR(-EEXIST);
> 
>               xnlock_get_irqsave(&nsem_lock, s);
>               u = nsem_hash_search(handle, current->mm);
>               if (u) {
>                       ++u->refs;
>                       xnlock_put_irqrestore(&nsem_lock, s);
>                       return u->usem;
>               }
>               xnlock_put_irqrestore(&nsem_lock, s);
> 
>               xnlock_get_irqsave(&nklock, s);
>               sem = xnregistry_fetch(handle);
>               if (sem && sem->magic != COBALT_SEM_MAGIC) {
>                       xnlock_put_irqrestore(&nklock, s);
>                       return ERR_PTR(-EINVAL);
>               }
>                       
>               if (sem) {
>                       ++sem->refs;
>                       xnlock_put_irqrestore(&nklock, s);
>               } else {
>                       xnlock_put_irqrestore(&nklock, s);
>                       goto retry_bind;
>               }
>               break;
>               
>       case -EWOULDBLOCK:
>               /* Not found */
>               if ((oflags & O_CREAT) == 0)
>                       return ERR_PTR(-ENOENT);
> 
>               rc = cobalt_sem_init_inner
>                       (&name[1], &shadow, SEM_PSHARED, value);
>               if (rc < 0) {
>                       if (rc == -EEXIST)
>                               goto retry_bind;
>                       return ERR_PTR(rc);
>               }
> 
>               if (__xn_safe_copy_to_user(ushadow, &shadow, sizeof(shadow))) {
>                       cobalt_sem_destroy_inner(shadow.handle);
>                       return ERR_PTR(-EFAULT);
>               }
>               handle = shadow.handle;
>               sem = xnregistry_fetch(handle);
>               ++sem->refs;

Why doesn't this lookup and referencing require nklock protection? After
cobalt_sem_init_inner, sem is now globally visible, so someone else
(like a competing nsem_open) could fetch it and reference it, no?

>       }
> 
>       u = xnmalloc(sizeof(*u));
>       if (u == NULL) 
>               return ERR_PTR(-ENOMEM);
> 
>       u->sem = sem;
>       u->mm = current->mm;
>       u->usem = ushadow;
>       u->refs = 1;
> 
>       xnlock_get_irqsave(&nsem_lock, s);
>       v = nsem_hash_search(handle, current->mm);
>       if (v) {
>               ++v->refs;
>               xnlock_put_irqrestore(&nsem_lock, s);
>               xnlock_get_irqsave(&nklock, s);
>               --sem->refs;
>               xnlock_put_irqrestore(&nklock, s);
> 
>               if (rc == -EWOULDBLOCK)
>                       cobalt_sem_destroy_inner(sem->handle);

I'm still not sure I fully understand the reason (and safety) of this
release. We get here when we lost the race to enter handle in the
current process' nsem hash table, right? So v != u, ok. But both v and u
must point to a sem object with the same handle value, otherwise they
wouldn't end up in the same hash table slot. But which of those sem
objects is now registered with the xnregistry? I mean, is this destroy
really working on the right one, the one we created in the current context?

> 
>               xnfree(u);
>               u = v;
>       } else {
>               nsem_hash_enter(handle, u);
>               list_add(&u->link, &cobalt_process_context()->usems);
>               xnlock_put_irqrestore(&nsem_lock, s);
>       }
> 
>       trace_xn_sys_sem_open_return(handle);
> 
>       return u->usem;
> }

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SES-DE
Corporate Competence Center Embedded Linux

_______________________________________________
Xenomai mailing list
[email protected]
http://www.xenomai.org/mailman/listinfo/xenomai

Reply via email to