Пример #1
0
/**
 * 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;
}
Пример #2
0
/**
 * 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;
}