Exemplo n.º 1
0
/* Must be called nklock locked, irq off. */
static void pse51_shm_destroy(pse51_shm_t * shm, int force)
{
	spl_t ignored;

	removeq(&pse51_shmq, &shm->link);
	xnlock_clear_irqon(&nklock);

	down(&shm->maplock);

	if (shm->addr) {
		xnheap_free(&shm->heapbase, shm->addr);

		xnheap_destroy_mapped(&shm->heapbase, NULL, NULL);

		shm->addr = NULL;
		shm->size = 0;
	}

	if (force) {
		xnholder_t *holder;

		while ((holder = getq(&shm->mappings))) {
			up(&shm->maplock);
			xnfree(link2map(holder));
			down(&shm->maplock);
		}
	}

	up(&shm->maplock);
	xnlock_get_irqsave(&nklock, ignored);
}
Exemplo n.º 2
0
static int _shm_free(unsigned long name)
{
	int ret = 0;
	xnholder_t *holder;
	xnshm_a_t *p;
	spl_t s;

	xnlock_get_irqsave(&nklock, s);

	holder = getheadq(&xnshm_allocq);

	while (holder != NULL) {
		p = link2shma(holder);

		if (p->name == name && --p->ref == 0) {
#ifdef CONFIG_XENO_OPT_REGISTRY
			if (p->handle)
				xnregistry_remove(p->handle);
#endif /* CONFIG_XENO_OPT_REGISTRY */
			if (p->heap == &kheap)
				xnheap_free(&kheap, p->chunk);
			else {
				/* Should release lock here? 
				 * Can destroy_mapped suspend ?
				 * [YES!]
				 */
#ifdef CONFIG_XENO_OPT_PERVASIVE
				ret = xnheap_destroy_mapped(p->heap, NULL, NULL);
#else /* !CONFIG_XENO_OPT_PERVASIVE */
				ret =
				    xnheap_destroy(p->heap,
						   &__heap_flush_private, NULL);
#endif /* !CONFIG_XENO_OPT_PERVASIVE */
				if (ret)
					goto unlock_and_exit;
				xnheap_free(&kheap, p->heap);
			}
			removeq(&xnshm_allocq, &p->link);
			ret = p->size;
			xnheap_free(&kheap, p);
			break;
		}

		holder = nextq(&xnshm_allocq, holder);
	}

      unlock_and_exit:

	xnlock_put_irqrestore(&nklock, s);

	return ret;
}
Exemplo n.º 3
0
int rt_heap_delete_inner(RT_HEAP *heap, void __user *mapaddr)
{
	int err = 0;
	spl_t s;

	if (!xnpod_root_p())
		return -EPERM;

	xnlock_get_irqsave(&nklock, s);

	heap = xeno_h2obj_validate(heap, XENO_HEAP_MAGIC, RT_HEAP);

	if (!heap) {
		err = xeno_handle_error(heap, XENO_HEAP_MAGIC, RT_HEAP);
		xnlock_put_irqrestore(&nklock, s);
		return err;
	}

	xeno_mark_deleted(heap);

	/* Get out of the nklocked section before releasing the heap
	   memory, since we are about to invoke Linux kernel
	   services. */

	xnlock_put_irqrestore(&nklock, s);

	/*
	 * The heap descriptor has been marked as deleted before we
	 * released the superlock thus preventing any sucessful
	 * subsequent calls of rt_heap_delete(), so now we can
	 * actually destroy it safely.
	 */

#ifdef CONFIG_XENO_OPT_PERVASIVE
	if (heap->mode & H_MAPPABLE)
		err = xnheap_destroy_mapped(&heap->heap_base,
					    __heap_post_release, mapaddr);
	else
#endif /* CONFIG_XENO_OPT_PERVASIVE */
		err = xnheap_destroy(&heap->heap_base, &__heap_flush_private, NULL);

	xnlock_get_irqsave(&nklock, s);

	if (err)
		heap->magic = XENO_HEAP_MAGIC;
	else if (!(heap->mode & H_MAPPABLE))
		__heap_post_release(&heap->heap_base);

	xnlock_put_irqrestore(&nklock, s);

	return err;
}
Exemplo n.º 4
0
static int _shm_free(unsigned long name)
{
	xnholder_t *holder;
	xnshm_a_t *p;
	int ret;
	spl_t s;

	xnlock_get_irqsave(&nklock, s);

	holder = getheadq(&xnshm_allocq);

	while (holder != NULL) {
		p = link2shma(holder);

		if (p->name == name && --p->ref == 0) {
			removeq(&xnshm_allocq, &p->link);
			if (p->handle)
				xnregistry_remove(p->handle);

			xnlock_put_irqrestore(&nklock, s);

			if (p->heap == &kheap)
				xnheap_free(&kheap, p->chunk);
			else {
#ifdef CONFIG_XENO_OPT_PERVASIVE
				xnheap_destroy_mapped(p->heap,
						      __heap_flush_shared,
						      NULL);
#else /* !CONFIG_XENO_OPT_PERVASIVE */
				xnheap_destroy(p->heap,
					       &__heap_flush_private, NULL);
				xnheap_free(&kheap, p->heap);
#endif /* !CONFIG_XENO_OPT_PERVASIVE */
			}
			ret = p->size;
			xnheap_free(&kheap, p);

			return ret;
		}

		holder = nextq(&xnshm_allocq, holder);
	}

	xnlock_put_irqrestore(&nklock, s);

	return 0;
}
Exemplo n.º 5
0
int rt_heap_delete_inner(RT_HEAP *heap, void __user *mapaddr)
{
	int err;
	spl_t s;

	if (!xnpod_root_p())
		return -EPERM;

	xnlock_get_irqsave(&nklock, s);

	heap = xeno_h2obj_validate(heap, XENO_HEAP_MAGIC, RT_HEAP);

	if (!heap) {
		err = xeno_handle_error(heap, XENO_HEAP_MAGIC, RT_HEAP);
		xnlock_put_irqrestore(&nklock, s);
		return err;
	}

	xeno_mark_deleted(heap);

	/* Get out of the nklocked section before releasing the heap
	   memory, since we are about to invoke Linux kernel
	   services. */

	xnlock_put_irqrestore(&nklock, s);

	/*
	 * The heap descriptor has been marked as deleted before we
	 * released the superlock thus preventing any subsequent call
	 * to rt_heap_delete() to succeed, so now we can actually
	 * destroy it safely.
	 */

#ifndef __XENO_SIM__
	if (heap->mode & H_MAPPABLE)
		xnheap_destroy_mapped(&heap->heap_base,
				      __heap_post_release, mapaddr);
	else
#endif
	{
		xnheap_destroy(&heap->heap_base, &__heap_flush_private, NULL);
		__heap_post_release(&heap->heap_base);
	}

	return 0;
}
Exemplo n.º 6
0
void __rtai_shm_pkg_cleanup(void)
{
#if 0
	xnholder_t *holder;
	xnshm_a_t *p;
	char szName[6];

	// Garbage collector : to be added : lock problem 
	holder = getheadq(&xnshm_allocq);

	while (holder != NULL) {
		p = link2shma(holder);

		if (p) {
			num2nam(p->name, szName);
			printk
			    ("[RTAI -SHM] Cleanup of unfreed memory %s( %d ref.)\n",
			     szName, p->ref);
			if (p->heap == &kheap)
				xnheap_free(&kheap, p->chunk);
			else {
				/* FIXME: MUST release lock here.
				 */
#ifdef CONFIG_XENO_OPT_PERVASIVE
				xnheap_destroy_mapped(p->heap, NULL, NULL);
#else /* !CONFIG_XENO_OPT_PERVASIVE */
				xnheap_destroy(p->heap, &__heap_flush_private,
					       NULL);
#endif /* !CONFIG_XENO_OPT_PERVASIVE */
				xnheap_free(&kheap, p->heap);
			}
			removeq(&xnshm_allocq, &p->link);
			xnheap_free(&kheap, p);
		}

		holder = nextq(&xnshm_allocq, holder);
	}
#endif
}
Exemplo n.º 7
0
void __exit __xeno_sys_exit(void)
{
	xnpod_shutdown(XNPOD_NORMAL_EXIT);

#ifndef __XENO_SIM__
	/* Must take place before xnpod_umount(). */
	xnshadow_cleanup();
#endif

	xntbase_umount();
	xnpod_umount();

	xnarch_exit();

#ifndef __XENO_SIM__
	xnheap_umount();
#ifdef CONFIG_XENO_OPT_PIPE
	xnpipe_umount();
#endif
	xnheap_destroy_mapped(&__xnsys_global_ppd.sem_heap, NULL, NULL);
#endif /* !__XENO_SIM__ */

	xnloginfo("real-time nucleus unloaded.\n");
}
Exemplo n.º 8
0
/**
 * Truncate a file or shared memory object to a specified length.
 *
 * When used in kernel-space, this service set to @a len the size of a shared
 * memory object opened with the shm_open() service. In user-space this service
 * falls back to Linux regular ftruncate service for file descriptors not
 * obtained with shm_open(). When this service is used to increase the size of a
 * shared memory object, the added space is zero-filled.
 *
 * Shared memory are suitable for direct memory access (allocated in physically
 * contiguous memory) if O_DIRECT was passed to shm_open.
 *
 * Shared memory objects may only be resized if they are not currently mapped.
 *
 * @param fd file descriptor;
 *
 * @param len new length of the underlying file or shared memory object.
 *
 * @retval 0 on success;
 * @retval -1 with @a errno set if:
 * - EBADF, @a fd is not a valid file descriptor;
 * - EPERM, the caller context is invalid;
 * - EINVAL, the specified length is invalid;
 * - EINVAL, the architecture can not honour the O_DIRECT flag;
 * - EINTR, this service was interrupted by a signal;
 * - EBUSY, @a fd is a shared memory object descriptor and the underlying shared
 *   memory is currently mapped;
 * - EFBIG, allocation of system memory failed.
 *
 * @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/ftruncate.html">
 * Specification.</a>
 * 
 */
int ftruncate(int fd, off_t len)
{
	unsigned desc_flags;
	pse51_desc_t *desc;
	pse51_shm_t *shm;
	int err;
	spl_t s;

	xnlock_get_irqsave(&nklock, s);
	shm = pse51_shm_get(&desc, fd, 1);

	if (IS_ERR(shm)) {
		err = -PTR_ERR(shm);
		xnlock_put_irqrestore(&nklock, s);
		goto error;
	}

	if (xnpod_asynch_p() || !xnpod_root_p()) {
		err = EPERM;
		xnlock_put_irqrestore(&nklock, s);
		goto err_shm_put;
	}

	if (len < 0) {
		err = EINVAL;
		xnlock_put_irqrestore(&nklock, s);
		goto err_shm_put;
	}

	desc_flags = pse51_desc_getflags(desc);
	xnlock_put_irqrestore(&nklock, s);

	if (down_interruptible(&shm->maplock)) {
		err = EINTR;
		goto err_shm_put;
	}

	/* Allocate one more page for alignment (the address returned by mmap
	   must be aligned on a page boundary). */
	if (len)
#ifdef CONFIG_XENO_OPT_PERVASIVE
		len = xnheap_rounded_size(len + PAGE_SIZE, PAGE_SIZE);
#else /* !CONFIG_XENO_OPT_PERVASIVE */
		len = xnheap_rounded_size(len + PAGE_SIZE, XNHEAP_PAGE_SIZE);
#endif /* !CONFIG_XENO_OPT_PERVASIVE */

	err = 0;
	if (emptyq_p(&shm->mappings)) {
		/* Temporary storage, in order to preserve the memory contents upon
		   resizing, if possible. */
		void *addr = NULL;
		size_t size = 0;

		if (shm->addr) {
			if (len == xnheap_extentsize(&shm->heapbase)) {
				/* Size unchanged, skip copy and reinit. */
				err = 0;
				goto err_up;
			}

			size = xnheap_max_contiguous(&shm->heapbase);
			addr = xnarch_alloc_host_mem(size);
			if (!addr) {
				err = ENOMEM;
				goto err_up;
			}

			memcpy(addr, shm->addr, size);

			xnheap_free(&shm->heapbase, shm->addr);
			xnheap_destroy_mapped(&shm->heapbase, NULL, NULL);

			shm->addr = NULL;
			shm->size = 0;
		}

		if (len) {
			int flags = XNARCH_SHARED_HEAP_FLAGS |
				((desc_flags & O_DIRECT) ? GFP_DMA : 0);

			err = -xnheap_init_mapped(&shm->heapbase, len, flags);
			if (err)
				goto err_up;

			xnheap_set_label(&shm->heapbase,
					 "posix shm: %s", shm->nodebase.name);

			shm->size = xnheap_max_contiguous(&shm->heapbase);
			shm->addr = xnheap_alloc(&shm->heapbase, shm->size);
			/* Required. */
			memset(shm->addr, '\0', shm->size);

			/* Copy the previous contents. */
			if (addr)
				memcpy(shm->addr, addr,
				       shm->size < size ? shm->size : size);

			shm->size -= PAGE_SIZE;
		}

		if (addr)
			xnarch_free_host_mem(addr, size);
	} else if (len != xnheap_extentsize(&shm->heapbase))
		err = EBUSY;

      err_up:
	up(&shm->maplock);

      err_shm_put:
	pse51_shm_put(shm, 1);

	if (!err)
		return 0;

      error:
	thread_set_errno(err == ENOMEM ? EFBIG : err);
	return -1;
}
Exemplo n.º 9
0
static int __sc_pcreate(struct task_struct *curr, struct pt_regs *regs)
{
	u_long ptsize, bsize;
	vrtx_pdesc_t pdesc;
	xnheap_t *ptheap;
	vrtxpt_t *pt;
	int err, pid;
	char *ptaddr;
	spl_t s;

	if (!__xn_access_ok
	    (curr, VERIFY_WRITE, __xn_reg_arg4(regs), sizeof(pdesc)))
		return -EFAULT;

	ptheap = (xnheap_t *)xnmalloc(sizeof(*ptheap));

	if (!ptheap)
		return ER_MEM;

	/* Suggested partition ID. */
	pid = __xn_reg_arg1(regs);
	/* Size of partition space -- account for the heap mgmt overhead. */
	ptsize = __xn_reg_arg2(regs);
	/* Shared heaps use the natural page size (PAGE_SIZE) */
	ptsize = xnheap_rounded_size(ptsize, PAGE_SIZE);
	/* Block size. */
	bsize = __xn_reg_arg3(regs);

	err = xnheap_init_mapped(ptheap, ptsize, 0);

	if (err)
		goto free_heap;

	/* Allocate the partition space as a single shared heap block. */
	ptaddr = xnheap_alloc(ptheap, ptsize);
	pid = sc_pcreate(pid, ptaddr, ptsize, bsize, &err);

	if (err)
		goto unmap_pt;

	xnlock_get_irqsave(&nklock, s);

	pt = xnmap_fetch(vrtx_pt_idmap, pid);

	if (pt) {		/* Paranoid. */
		pt->mm = curr->mm;
		pt->sysheap = ptheap;
		pdesc.pid = pid;
		pdesc.ptcb = ptheap;
		pdesc.ptsize = xnheap_extentsize(ptheap);

		xnlock_put_irqrestore(&nklock, s);

		__xn_copy_to_user(curr, (void __user *)__xn_reg_arg4(regs),
				  &pdesc, sizeof(pdesc));
		return 0;
	}

	xnlock_put_irqrestore(&nklock, s);

	err = ER_PID;

unmap_pt:

	xnheap_destroy_mapped(ptheap, NULL, NULL);

free_heap:

	xnfree(ptheap);

	return err;
}