⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 2 页
字号:
    return apc;}/** * @fn int rthal_apc_free (int apc) * * @brief Releases an APC slot. * * This service deallocates an APC slot obtained by rthal_apc_alloc(). * * @param apc The APC id. to release, as returned by a successful call * to the rthal_apc_alloc() service. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a apc is invalid. * * Environments: * * This service can be called from: * * - Any domain context. */int rthal_apc_free (int apc){    if (apc < 0 || apc >= RTHAL_NR_APCS ||	!test_and_clear_bit(apc,&rthal_apc_map))	return -EINVAL;    return 0;}/** * @fn int rthal_apc_schedule (int apc) *                            * @brief Schedule an APC invocation. * * This service marks the APC as pending for the Linux domain, so that * its handler will be called as soon as possible, when the Linux * domain gets back in control. * * When posted from the Linux domain, the APC handler is fired as soon * as the interrupt mask is explicitely cleared by some kernel * code. When posted from the Xenomai domain, the APC handler is * fired as soon as the Linux domain is resumed, i.e. after Xenomai has * completed all its pending duties. * * @param apc The APC id. to schedule. * * @return 0 or 1 are returned upon success, the former meaning that * the APC was already pending. Otherwise: * * - -EINVAL is returned if @a apc is invalid. * * Environments: * * This service can be called from: * * - Any domain context, albeit the usual calling place is from the * Xenomai domain. */int rthal_apc_schedule (int apc){    rthal_declare_cpuid;    if (apc < 0 || apc >= RTHAL_NR_APCS)	return -EINVAL;    rthal_load_cpuid();	/* Migration would be harmless here. */    if (!test_and_set_bit(apc,&rthal_apc_pending[cpuid]))	{	rthal_schedule_irq(rthal_apc_virq);	return 1;	}    return 0;	/* Already pending. */}#ifdef CONFIG_PROC_FSstruct proc_dir_entry *rthal_proc_root;static int hal_read_proc (char *page,			  char **start,			  off_t off,			  int count,			  int *eof,			  void *data){    int len, major, minor, patchlevel;#ifdef CONFIG_IPIPE    major = IPIPE_MAJOR_NUMBER;    minor = IPIPE_MINOR_NUMBER;    patchlevel = IPIPE_PATCH_NUMBER;#else /* !CONFIG_IPIPE */    /* Canonicalize the Adeos relno-candidate information to some       major.minor.patchlevel format to be parser-friendly. */    major = ADEOS_MAJOR_NUMBER;    if (ADEOS_MINOR_NUMBER < 255)	{	--major;	minor = 99;	patchlevel = ADEOS_MINOR_NUMBER;	}    else	{	minor = 0;	patchlevel = 0;	}#endif /* CONFIG_IPIPE */    len = sprintf(page,"%d.%d-%.2d\n",major,minor,patchlevel);    len -= off;    if (len <= off + count) *eof = 1;    *start = page + off;    if(len > count) len = count;    if(len < 0) len = 0;    return len;}static int faults_read_proc (char *page,			     char **start,			     off_t off,			     int count,			     int *eof,			     void *data){    int len = 0, cpu, trap;    char *p = page;    p += sprintf(p,"TRAP ");    for_each_online_cpu(cpu) {	p += sprintf(p,"        CPU%d",cpu);    }    for (trap = 0; rthal_fault_labels[trap] != NULL; trap++) {	if (!*rthal_fault_labels[trap])	    continue;	p += sprintf(p,"\n%3d: ",trap);	for_each_online_cpu(cpu) {	    p += sprintf(p,"%12d",			 rthal_realtime_faults[cpu][trap]);	}	p += sprintf(p,"    (%s)",rthal_fault_labels[trap]);    }    p += sprintf(p,"\n");    len = p - page - off;    if (len <= off + count) *eof = 1;    *start = page + off;    if (len > count) len = count;    if (len < 0) len = 0;    return len;}static int apc_read_proc (char *page,			     char **start,			     off_t off,			     int count,			     int *eof,			     void *data){    int len = 0, cpu, apc;    char *p = page;    p += sprintf(p,"APC ");    for_each_online_cpu(cpu) {	p += sprintf(p,"         CPU%d",cpu);    }    for (apc = 0; apc < BITS_PER_LONG; apc++)	{	if (!test_bit(apc,&rthal_apc_map))	    continue;	/* Not hooked. */	p += sprintf(p,"\n%3d: ",apc);	for_each_online_cpu(cpu) {	    p += sprintf(p,"%12lu",			 rthal_apc_table[apc].hits[cpu]);	}	p += sprintf(p,"    (%s)",rthal_apc_table[apc].name);	}    p += sprintf(p,"\n");    len = p - page - off;    if (len <= off + count) *eof = 1;    *start = page + off;    if (len > count) len = count;    if (len < 0) len = 0;    return len;}struct proc_dir_entry *__rthal_add_proc_leaf (const char *name,					      read_proc_t rdproc,					      write_proc_t wrproc,					      void *data,					      struct proc_dir_entry *parent){    int mode = wrproc ? 0644 : 0444;    struct proc_dir_entry *entry;    entry = create_proc_entry(name,mode,parent);    if (entry)	{	entry->nlink = 1;	entry->data = data;	entry->read_proc = rdproc;	entry->write_proc = wrproc;	entry->owner = THIS_MODULE;	}    return entry;}static int rthal_proc_register (void){    rthal_proc_root = create_proc_entry("xenomai",S_IFDIR, 0);    if (!rthal_proc_root)	{	printk(KERN_ERR "Xenomai: Unable to initialize /proc/xenomai.\n");	return -1;        }    rthal_proc_root->owner = THIS_MODULE;    __rthal_add_proc_leaf("hal",		  &hal_read_proc,		  NULL,		  NULL,		  rthal_proc_root);    __rthal_add_proc_leaf("faults",		  &faults_read_proc,		  NULL,		  NULL,		  rthal_proc_root);    __rthal_add_proc_leaf("apc",		  &apc_read_proc,		  NULL,		  NULL,		  rthal_proc_root);    rthal_nmi_proc_register();    return 0;}static void rthal_proc_unregister (void){    rthal_nmi_proc_unregister();    remove_proc_entry("hal",rthal_proc_root);    remove_proc_entry("faults",rthal_proc_root);    remove_proc_entry("apc",rthal_proc_root);    remove_proc_entry("xenomai",NULL);}#endif /* CONFIG_PROC_FS */int rthal_init (void){    int err;#ifdef CONFIG_SMP    /* The nucleus also sets the same CPU affinity so that both       modules keep their execution sequence on SMP boxen. */    set_cpus_allowed(current,cpumask_of_cpu(0));#endif /* CONFIG_SMP */    err = rthal_arch_init();    if (err)	goto out;    /* The arch-dependent support must have updated the frequency args       as required. */    rthal_tunables.cpu_freq = rthal_cpufreq_arg;    rthal_tunables.timer_freq = rthal_timerfreq_arg;    /* Allocate a virtual interrupt to handle apcs within the Linux       domain. */    rthal_apc_virq = rthal_alloc_virq();    if (!rthal_apc_virq)    {        printk(KERN_ERR "Xenomai: No virtual interrupt available.\n");	    err = -EBUSY;        goto out_arch_cleanup;    }    err = rthal_virtualize_irq(rthal_current_domain,			       rthal_apc_virq,			       &rthal_apc_trampoline,			       NULL,			       NULL,			       IPIPE_HANDLE_MASK);    if (err)    {        printk(KERN_ERR "Xenomai: Failed to virtualize IRQ.\n");        goto out_free_irq;    }#ifdef CONFIG_PREEMPT_RT    {    int cpu;    for_each_online_cpu(cpu) {       rthal_apc_servers[cpu] =	   kthread_create(&rthal_apc_thread,(void *)(unsigned long)cpu,"apc/%d",cpu);       if (!rthal_apc_servers[cpu])	   goto out_kthread_stop;       wake_up_process(rthal_apc_servers[cpu]);      }    }#endif /* CONFIG_PREEMPT_RT */#ifdef CONFIG_PROC_FS    rthal_proc_register();#endif /* CONFIG_PROC_FS */    err = rthal_register_domain(&rthal_domain,				"Xenomai",				RTHAL_DOMAIN_ID,				RTHAL_ROOT_PRIO + 100,				&rthal_domain_entry);    if (!err)    	rthal_init_done = 1;    else     {        printk(KERN_ERR "Xenomai: Domain registration failed.\n");        goto out_proc_unregister;    }    return 0;out_proc_unregister:#ifdef CONFIG_PROC_FS    rthal_proc_unregister();#endif#ifdef CONFIG_PREEMPT_RTout_kthread_stop:    {    int cpu;    for_each_online_cpu(cpu) {        if (rthal_apc_servers[cpu])            kthread_stop(rthal_apc_servers[cpu]);      }    }#endif /* CONFIG_PREEMPT_RT */    rthal_virtualize_irq(rthal_current_domain,rthal_apc_virq,NULL,NULL,NULL,0);   out_free_irq:    rthal_free_virq(rthal_apc_virq); out_arch_cleanup:    rthal_arch_cleanup(); out:    return err;}void rthal_exit (void){#ifdef CONFIG_SMP    /* The nucleus also sets the same CPU affinity so that both       modules keep their execution sequence on SMP boxen. */    set_cpus_allowed(current,cpumask_of_cpu(0));#endif /* CONFIG_SMP */#ifdef CONFIG_PROC_FS    rthal_proc_unregister();#endif /* CONFIG_PROC_FS */    if (rthal_apc_virq)	{	rthal_virtualize_irq(rthal_current_domain,rthal_apc_virq,NULL,NULL,NULL,0);	rthal_free_virq(rthal_apc_virq);#ifdef CONFIG_PREEMPT_RT	{	int cpu;	for_each_online_cpu(cpu) {            kthread_stop(rthal_apc_servers[cpu]);	  }	}#endif /* CONFIG_PREEMPT_RT */	}    if (rthal_init_done)	rthal_unregister_domain(&rthal_domain);    rthal_arch_cleanup();}/** * @fn int rthal_irq_enable(unsigned irq) *                            * @brief Enable an interrupt source. * * Enables an interrupt source at PIC level. Since Adeos masks and * acknowledges the associated interrupt source upon IRQ receipt, this * action is usually needed whenever the HAL handler does not * propagate the IRQ event to the Linux domain, thus preventing the * regular Linux interrupt handling code from re-enabling said * source. After this call has returned, IRQs from the given source * will be enabled again. * * @param irq The interrupt source to enable.  This value is * architecture-dependent. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a irq is invalid. * * - Other error codes might be returned in case some internal error * happens at the Adeos level. Such error might caused by conflicting * Adeos requests made by third-party code. * * Environments: * * This service can be called from: * * - Any domain context. *//** * @fn int rthal_irq_disable(unsigned irq) *                            * @brief Disable an interrupt source. * * Disables an interrupt source at PIC level. After this call has * returned, no more IRQs from the given source will be allowed, until * the latter is enabled again using rthal_irq_enable(). * * @param irq The interrupt source to disable.  This value is * architecture-dependent. * * @return 0 is returned upon success. Otherwise: * * - -EINVAL is returned if @a irq is invalid. * * - Other error codes might be returned in case some internal error * happens at the Adeos level. Such error might caused by conflicting * Adeos requests made by third-party code. * * Environments: * * This service can be called from: * * - Any domain context. *//*!  * \fn int rthal_timer_request(void (*handler)(void),unsigned long nstick) * \brief Grab the hardware timer. * * rthal_timer_request() grabs and tunes the hardware timer so that a * user-defined routine is called according to a given frequency. On * architectures that provide a oneshot-programmable time source, the * hardware timer can operate either in aperiodic or periodic * mode. Using the aperiodic mode still allows to run periodic timings * over it: the underlying hardware simply needs to be reprogrammed * after each tick using the appropriate interval value * * The time interval that elapses between two consecutive invocations * of the handler is called a tick. The user-supplied handler will * always be invoked on behalf of the Xenomai domain for each incoming * tick. * * @param handler The address of the tick handler which will process * each incoming tick. * * @param nstick The timer period in nanoseconds. If this parameter is * zero, the underlying hardware timer is set to operate in * oneshot-programming mode. In this mode, timing accuracy is higher - * since it is not rounded to a constant time slice - at the expense * of a lesser efficicency due to the timer chip programming * duties. On the other hand, the shorter the period, the higher the * overhead induced by the periodic mode, since the handler will end * up consuming a lot of CPU power to process useless ticks. * * @return 0 is returned on success. Otherwise: * * - -EBUSY is returned if the hardware timer has already been * grabbed.  rthal_timer_request() must be issued before * rthal_timer_request() is called again. * * Environments: * * This service can be called from: * * - Linux domain context. *//*!  * \fn void rthal_timer_release(void) * \brief Release the hardware timer. * * Releases the hardware timer, thus reverting the effect of a * previous call to rthal_timer_request(). In case the timer hardware * is shared with Linux, a periodic setup suitable for the Linux * kernel will be reset. * * Environments: * * This service can be called from: * * - Linux domain context. *//*@}*/EXPORT_SYMBOL(rthal_irq_request);EXPORT_SYMBOL(rthal_irq_release);EXPORT_SYMBOL(rthal_irq_enable);EXPORT_SYMBOL(rthal_irq_disable);EXPORT_SYMBOL(rthal_irq_end);EXPORT_SYMBOL(rthal_irq_host_request);EXPORT_SYMBOL(rthal_irq_host_release);EXPORT_SYMBOL(rthal_irq_host_pend);EXPORT_SYMBOL(rthal_irq_affinity);EXPORT_SYMBOL(rthal_trap_catch);EXPORT_SYMBOL(rthal_timer_request);EXPORT_SYMBOL(rthal_timer_release);EXPORT_SYMBOL(rthal_timer_calibrate);EXPORT_SYMBOL(rthal_apc_alloc);EXPORT_SYMBOL(rthal_apc_free);EXPORT_SYMBOL(rthal_apc_schedule);EXPORT_SYMBOL(rthal_critical_enter);EXPORT_SYMBOL(rthal_critical_exit);EXPORT_SYMBOL(rthal_domain);EXPORT_SYMBOL(rthal_tunables);EXPORT_SYMBOL(rthal_cpu_realtime);#ifdef CONFIG_PROC_FSEXPORT_SYMBOL(rthal_proc_root);#endif /* CONFIG_PROC_FS */EXPORT_SYMBOL(rthal_init);EXPORT_SYMBOL(rthal_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -