static RTAI_SYSCALL_MODE void rt_set_heap(unsigned long name, void *adr) { void *heap, *hptr; int size; RT_TASK *task; heap = rt_get_adr(name); hptr = ALIGN2PAGE(heap); size = ((abs(rt_get_type(name)) - sizeof(rtheap_t) - (hptr - heap)) & PAGE_MASK); heap = hptr + size; if (!atomic_cmpxchg((atomic_t *)hptr, 0, name)) { rtheap_init(heap, hptr, size, PAGE_SIZE, 0); } RTAI_TASK(return); if (name == GLOBAL_HEAP_ID) { task->heap[GLOBAL].heap = &rtai_global_heap; task->heap[GLOBAL].kadr = rtai_global_heap_adr; task->heap[GLOBAL].uadr = adr; } else { task->heap[SPECIFIC].heap = heap; task->heap[SPECIFIC].kadr = hptr; task->heap[SPECIFIC].uadr = adr; } }
static int rtai_shm_f_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) #endif { switch (cmd) { case SHM_ALLOC: { TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_MALLOC, ((unsigned long *)arg)[0], cmd, current->pid); return rt_shm_alloc_usp(((unsigned long *)arg)[0], ((long *)arg)[1], ((long *)arg)[2]); } case SHM_FREE: { TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_FREE, arg, cmd, current->pid); return _rt_shm_free(arg, rt_get_type(arg)); } case SHM_SIZE: { TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_GET_SIZE, arg, cmd, current->pid); return rt_shm_size((unsigned long *)((unsigned long *)arg)[0]); } #ifdef CONFIG_RTAI_MALLOC case HEAP_SET: { rt_set_heap(((unsigned long *)arg)[0], (void *)((unsigned long *)arg)[1]); return 0; } #endif } return 0; }
static RTAI_SYSCALL_MODE int rt_shm_alloc_usp(unsigned long name, int size, int suprt) { TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_MALLOC, name, size, current->pid); if (_rt_shm_alloc(name, size, suprt)) { current->rtai_tskext(TSKEXT1) = (void *)name; return abs(rt_get_type(name)); } return 0; }
static int rtai_shm_f_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long name; int size; if (!vma->vm_ops) { vma->vm_ops = &rtai_shm_vm_ops; vma->vm_flags |= VM_LOCKED; name = (unsigned long)(vma->vm_private_data = current->rtai_tskext(TSKEXT1)); current->rtai_tskext(TSKEXT1) = current->rtai_tskext(TSKEXT0) ? current : NULL; return (size = rt_get_type(name)) < 0 ? rkmmap(ALIGN2PAGE(rt_get_adr(name)), -size, vma) : rvmmap(rt_get_adr(name), size, vma); } return -EFAULT; }
static RTAI_SYSCALL_MODE int rt_shm_size(unsigned long *arg) { int size; struct vm_area_struct *vma; size = abs(rt_get_type(*arg)); for (vma = (current->mm)->mmap; vma; vma = vma->vm_next) { if (vma->vm_private_data == (void *)*arg && (vma->vm_end - vma->vm_start) == size) { *arg = vma->vm_start; return size; } } return 0; }
static void rtai_shm_vm_close(struct vm_area_struct *vma) { _rt_shm_free((unsigned long)vma->vm_private_data, rt_get_type((unsigned long)vma->vm_private_data)); }
RTAI_SYSCALL_MODE int rt_shm_free(unsigned long name) { TRACE_RTAI_SHM(TRACE_RTAI_EV_SHM_KFREE, name, 0, 0); return _rt_shm_free(name, rt_get_type(name)); }
void linux_process_termination(void) { RT_TASK *task2delete, *task2unblock, *base_linux_tasks[NR_RT_CPUS]; int cpu, slot, nr_task_lists; pid_t my_pid; struct task_struct *ltsk; unsigned long num; void *adr; /* * Linux is just about to schedule *ltsk out of existence. * With this feature, LXRT frees the real time resources allocated * by the task ltsk. */ ltsk = current; rt_get_base_linux_task(base_linux_tasks); nr_task_lists = rt_sched_type() == MUP_SCHED ? NR_RT_CPUS : 1; rt_global_cli(); for (cpu = 0; cpu < nr_task_lists; cpu++) { task2delete = base_linux_tasks[cpu]; // Try to find if RTAI was aware of this dying Linux task. while ((task2delete = task2delete->next) && task2delete->lnxtsk != ltsk); // First let's free the registered resources. for (slot = 1; slot <= MAX_SLOTS; slot++) { if ((num = is_process_registered(ltsk)) > 0) { adr = rt_get_adr(num); switch (rt_get_type(num)) { case IS_SEM: rt_printk("LXRT Informed releases SEM %p\n", adr); rt_sem_delete(adr); rt_free(adr); break; case IS_MBX: rt_printk("LXRT Informed releases MBX %p\n", adr); rt_mbx_delete(adr); rt_free(adr); break; case IS_PRX: rt_printk("LXRT Informed releases PRX %p\n", adr); rt_Proxy_detach(rttask2pid(adr)); break; // to do: case IS_SHMEM: } rt_drg_on_adr(adr); } } // Synchronous IPC pid may need to be released if ((my_pid = rttask2pid(task2delete))) { rt_printk("Release vc %04X\n", my_pid); rt_vc_release(my_pid); } if (!task2delete) { continue; // The user deleted the task but forgot to delete the resources. } // Other RTAI tasks may be SEND, RPC or RETURN blocked on task2delete. Loop: task2unblock = base_linux_tasks[cpu]; while ((task2unblock = task2unblock->next)) { if (!(task2unblock->state & (SEND | RPC | RETURN))) { continue; } else if (task2unblock->msg_queue.task == task2delete) { task2unblock->state &= ~(SEND | RPC | RETURN | DELAYED); LXRT_RESUME(task2unblock); rt_global_cli(); goto Loop; } } // To do: other RTAI tasks may want to be informed as well. // Ok, let's delete the task. if (!rt_task_delete(task2delete)) { rt_printk("LXRT Informed releases RT %p, lnxpid %d (%p), name %s.\n", task2delete, ltsk->pid, ltsk, ltsk->comm); rt_free(task2delete->msg_buf[0]); rt_free(task2delete); rt_drg_on_adr(task2delete); break; } } rt_global_sti(); }