/** * Open a shared memory object. * * This service establishes a connection between a shared memory object and a * file descriptor. Further use of this descriptor will allow to dimension and * map the shared memory into the calling context address space. * * One of the following access mode should be set in @a oflags: * - O_RDONLY, meaning that the shared memory object may only be mapped with the * PROT_READ flag; * - O_WRONLY, meaning that the shared memory object may only be mapped with the * PROT_WRITE flag; * - O_RDWR, meaning that the shared memory object may be mapped with the * PROT_READ | PROT_WRITE flag. * * If no shared memory object named @a name exists, and @a oflags has the @a * O_CREAT bit set, the shared memory object is created by this function. * * If @a oflags has the two bits @a O_CREAT and @a O_EXCL set and the shared * memory object alread exists, this service fails. * * If @a oflags has the bit @a O_TRUNC set, the shared memory exists and is not * currently mapped, its size is truncated to 0. * * If @a oflags has the bit @a O_DIRECT set, the shared memory will be suitable * for direct memory access (allocated in physically contiguous memory). * * @a name may be any arbitrary string, in which slashes have no particular * meaning. However, for portability, using a name which starts with a slash and * contains no other slash is recommended. * * @param name name of the shared memory object to open; * * @param oflags flags. * * @param mode ignored. * * @return a file descriptor on success; * @return -1 with @a errno set if: * - ENAMETOOLONG, the length of the @a name argument exceeds 64 characters; * - EEXIST, the bits @a O_CREAT and @a O_EXCL were set in @a oflags and the * shared memory object already exists; * - ENOENT, the bit @a O_CREAT is not set in @a oflags and the shared memory * object does not exist; * - ENOSPC, insufficient memory exists in the system heap to create the shared * memory object, increase CONFIG_XENO_OPT_SYS_HEAPSZ; * - EPERM, the caller context is invalid; * - EINVAL, the O_TRUNC flag was specified and the shared memory object is * currently mapped; * - EMFILE, too many descriptors are currently open. * * @par Valid contexts: * - kernel module initialization or cleanup routine; * - user-space thread (Xenomai threads switch to secondary mode). * * @see * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/shm_open.html"> * Specification.</a> * */ int shm_open(const char *name, int oflags, mode_t mode) { pse51_node_t *node; pse51_desc_t *desc; pse51_shm_t *shm; int err, fd; spl_t s; /* From root context only. */ if (xnpod_asynch_p() || !xnpod_root_p()) { thread_set_errno(EPERM); return -1; } xnlock_get_irqsave(&nklock, s); err = pse51_node_get(&node, name, PSE51_SHM_MAGIC, oflags); xnlock_put_irqrestore(&nklock, s); if (err) goto error; if (node) { shm = node2shm(node); goto got_shm; } /* We must create the shared memory object, not yet allocated. */ shm = (pse51_shm_t *) xnmalloc(sizeof(*shm)); if (!shm) { err = ENOSPC; goto error; } xnlock_get_irqsave(&nklock, s); err = pse51_node_add(&shm->nodebase, name, PSE51_SHM_MAGIC); if (err && err != EEXIST) goto err_unlock; if (err == EEXIST) { /* same shm was created in the mean time, rollback. */ err = pse51_node_get(&node, name, PSE51_SHM_MAGIC, oflags); err_unlock: xnlock_put_irqrestore(&nklock, s); xnfree(shm); if (err) goto error; shm = node2shm(node); goto got_shm; } pse51_shm_init(shm); xnlock_put_irqrestore(&nklock, s); got_shm: err = pse51_desc_create(&desc, &shm->nodebase, oflags & (PSE51_PERMS_MASK | O_DIRECT)); if (err) goto err_shm_put; fd = pse51_desc_fd(desc); if ((oflags & O_TRUNC) && ftruncate(fd, 0)) { close(fd); return -1; } return fd; err_shm_put: pse51_shm_put(shm, 1); error: thread_set_errno(err); return -1; }
/** * Open a named semaphore. * * This service establishes a connection between the semaphore named @a name and * the calling context (kernel-space as a whole, or user-space process). * * If no semaphore named @a name exists and @a oflags has the @a O_CREAT bit * set, the semaphore is created by this function, using two more arguments: * - a @a mode argument, of type @b mode_t, currently ignored; * - a @a value argument, of type @b unsigned, specifying the initial value of * the created semaphore. * * If @a oflags has the two bits @a O_CREAT and @a O_EXCL set and the semaphore * already exists, this service fails. * * @a name may be any arbitrary string, in which slashes have no particular * meaning. However, for portability, using a name which starts with a slash and * contains no other slash is recommended. * * If sem_open() is called from the same context (kernel-space as a whole, or * user-space process) several times with the same value of @a name, the same * address is returned. * * @param name the name of the semaphore to be created; * * @param oflags flags. * * @return the address of the named semaphore on success; * @return SEM_FAILED with @a errno set if: * - ENAMETOOLONG, the length of the @a name argument exceeds 64 characters; * - EEXIST, the bits @a O_CREAT and @a O_EXCL were set in @a oflags and the * named semaphore already exists; * - ENOENT, the bit @a O_CREAT is not set in @a oflags and the named semaphore * does not exist; * - ENOSPC, insufficient memory exists in the system heap to create the * semaphore, increase CONFIG_XENO_OPT_SYS_HEAPSZ; * - EINVAL, the @a value argument exceeds @a SEM_VALUE_MAX. * * @see * <a href="http://www.opengroup.org/onlinepubs/000095399/functions/sem_open.html"> * Specification.</a> * */ sem_t *sem_open(const char *name, int oflags, ...) { pse51_node_t *node; nsem_t *named_sem; unsigned value; mode_t mode; va_list ap; spl_t s; int err; xnlock_get_irqsave(&nklock, s); err = pse51_node_get(&node, name, PSE51_NAMED_SEM_MAGIC, oflags); xnlock_put_irqrestore(&nklock, s); if (err) goto error; if (node) { named_sem = node2sem(node); goto got_sem; } named_sem = (nsem_t *) xnmalloc(sizeof(*named_sem)); if (!named_sem) { err = ENOSPC; goto error; } named_sem->sembase.is_named = 1; named_sem->descriptor.shadow_sem.sem = &named_sem->sembase; va_start(ap, oflags); mode = va_arg(ap, int); (void)mode; /* unused */ value = va_arg(ap, unsigned); va_end(ap); xnlock_get_irqsave(&nklock, s); err = pse51_sem_init_inner(&named_sem->sembase, 1, value); if (err) { xnlock_put_irqrestore(&nklock, s); xnfree(named_sem); goto error; } err = pse51_node_add(&named_sem->nodebase, name, PSE51_NAMED_SEM_MAGIC); if (err && err != EEXIST) goto err_put_lock; if (err == EEXIST) { err = pse51_node_get(&node, name, PSE51_NAMED_SEM_MAGIC, oflags); if (err) goto err_put_lock; xnlock_put_irqrestore(&nklock, s); sem_destroy_inner(&named_sem->sembase, pse51_kqueues(named_sem->sembase.pshared)); named_sem = node2sem(node); goto got_sem; } xnlock_put_irqrestore(&nklock, s); got_sem: /* Set the magic, needed both at creation and when re-opening a semaphore that was closed but not unlinked. */ named_sem->descriptor.shadow_sem.magic = PSE51_NAMED_SEM_MAGIC; return &named_sem->descriptor.native_sem; err_put_lock: xnlock_put_irqrestore(&nklock, s); sem_destroy_inner(&named_sem->sembase, pse51_kqueues(named_sem->sembase.pshared)); error: thread_set_errno(err); return SEM_FAILED; }