static void pse51_shm_put(pse51_shm_t * shm, unsigned dec) { spl_t s; xnlock_get_irqsave(&nklock, s); while (dec--) pse51_node_put(&shm->nodebase); if (pse51_node_removed_p(&shm->nodebase)) { xnlock_put_irqrestore(&nklock, s); pse51_shm_destroy(shm, 0); xnfree(shm); } else xnlock_put_irqrestore(&nklock, s); }
/** * Close a named semaphore. * * This service closes the semaphore @a sm. The semaphore is destroyed only when * unlinked with a call to the sem_unlink() service and when each call to * sem_open() matches a call to this service. * * When a semaphore is destroyed, the memory it used is returned to the system * heap, so that further references to this semaphore are not guaranteed to * fail, as is the case for unnamed semaphores. * * This service fails if @a sm is an unnamed semaphore. * * @param sm the semaphore to be closed. * * @retval 0 on success; * @retval -1 with @a errno set if: * - EINVAL, the semaphore @a sm is invalid or is an unnamed semaphore. * * @see * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/sem_close.html"> * Specification.</a> * */ int sem_close(sem_t * sm) { struct __shadow_sem *shadow = &((union __xeno_sem *)sm)->shadow_sem; nsem_t *named_sem; spl_t s; int err; xnlock_get_irqsave(&nklock, s); if (shadow->magic != PSE51_NAMED_SEM_MAGIC || shadow->sem->magic != PSE51_SEM_MAGIC) { err = EINVAL; goto error; } named_sem = sem2named_sem(shadow->sem); err = pse51_node_put(&named_sem->nodebase); if (err) goto error; if (pse51_node_removed_p(&named_sem->nodebase)) { /* unlink was called, and this semaphore is no longer referenced. */ pse51_mark_deleted(shadow); pse51_mark_deleted(&named_sem->sembase); xnlock_put_irqrestore(&nklock, s); sem_destroy_inner(&named_sem->sembase, pse51_kqueues(1)); } else if (!pse51_node_ref_p(&named_sem->nodebase)) { /* this semaphore is no longer referenced, but not unlinked. */ pse51_mark_deleted(shadow); xnlock_put_irqrestore(&nklock, s); } else xnlock_put_irqrestore(&nklock, s); return 0; error: xnlock_put_irqrestore(&nklock, s); thread_set_errno(err); return -1; }