system.h

00001 /*
00002  * Copyright (C) 2001,2002,2003,2004,2005 Philippe Gerum <rpm@xenomai.org>.
00003  * Copyright (C) 2004,2005 Gilles Chanteperdrix <gilles.chanteperdrix@laposte.net>.
00004  *
00005  * RTAI/fusion is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * RTAI/fusion is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with RTAI/fusion; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00018  * 02111-1307, USA.
00019  */
00020 
00021 #ifndef _RTAI_ASM_GENERIC_SYSTEM_H
00022 #define _RTAI_ASM_GENERIC_SYSTEM_H
00023 
00024 #ifdef __KERNEL__
00025 
00026 #include <linux/kernel.h>
00027 #include <linux/version.h>
00028 #include <linux/module.h>
00029 #include <linux/slab.h>
00030 #include <linux/errno.h>
00031 #include <linux/vmalloc.h>
00032 #include <asm/uaccess.h>
00033 #include <asm/param.h>
00034 #include <asm/mmu_context.h>
00035 #include <rtai_config.h>
00036 #include <nucleus/asm/hal.h>
00037 #include <nucleus/asm/atomic.h>
00038 #include <nucleus/shadow.h>
00039 
00040 #define module_param_value(parm) (parm)
00041 
00042 typedef unsigned long spl_t;
00043 
00044 #define splhigh(x)  rthal_local_irq_save(x)
00045 #ifdef CONFIG_SMP
00046 #define splexit(x)  rthal_local_irq_restore((x) & 1)
00047 #else /* !CONFIG_SMP */
00048 #define splexit(x)  rthal_local_irq_restore(x)
00049 #endif /* CONFIG_SMP */
00050 #define splnone()   rthal_local_irq_enable()
00051 #define spltest()   rthal_local_irq_test()
00052 #define splget(x)   rthal_local_irq_flags(x)
00053 #define splsync(x)  rthal_local_irq_sync(x)
00054 
00055 #if defined(CONFIG_SMP) && \
00056     (defined(CONFIG_RTAI_OPT_STATS) || defined(CONFIG_RTAI_OPT_DEBUG))
00057 
00058 typedef struct {
00059 
00060         unsigned long long spin_time;
00061         unsigned long long lock_time;
00062         const char *file;
00063         const char *function;
00064         unsigned line;
00065 
00066 } xnlockinfo_t;
00067 
00068 typedef struct {
00069 
00070     volatile unsigned long lock;
00071     const char *file;
00072     const char *function;
00073     unsigned line;
00074     int cpu;
00075     unsigned long long spin_time;
00076     unsigned long long lock_date;
00077 
00078 } xnlock_t;
00079 
00080 #define XNARCH_LOCK_UNLOCKED (xnlock_t) {       \
00081         0,                                      \
00082         NULL,                                   \
00083         NULL,                                   \
00084         0,                                      \
00085         -1,                                     \
00086         0LL,                                    \
00087         0LL,                                    \
00088 }
00089 
00090 #define CONFIG_RTAI_SPINLOCK_DEBUG  1
00091 
00092 #else /* !(CONFIG_RTAI_OPT_STATS && CONFIG_SMP) */
00093 
00094 typedef struct { volatile unsigned long lock; } xnlock_t;
00095 
00096 #define XNARCH_LOCK_UNLOCKED (xnlock_t) { 0 }
00097 
00098 #endif /* CONFIG_RTAI_OPT_STATS && CONFIG_SMP */
00099 
00100 #define XNARCH_NR_CPUS               RTHAL_NR_CPUS
00101 
00102 #define XNARCH_ROOT_STACKSZ   0 /* Only a placeholder -- no stack */
00103 
00104 #define XNARCH_PROMPT "RTAI: "
00105 #define xnarch_loginfo(fmt,args...)  printk(KERN_INFO XNARCH_PROMPT fmt , ##args)
00106 #define xnarch_logwarn(fmt,args...)  printk(KERN_WARNING XNARCH_PROMPT fmt , ##args)
00107 #define xnarch_logerr(fmt,args...)   printk(KERN_ERR XNARCH_PROMPT fmt , ##args)
00108 #define xnarch_printf(fmt,args...)   printk(KERN_INFO XNARCH_PROMPT fmt , ##args)
00109 
00110 #define xnarch_ullmod(ull,uld,rem)   ({ xnarch_ulldiv(ull,uld,rem); (*rem); })
00111 #define xnarch_uldiv(ull, d)         rthal_uldivrem(ull, d, NULL)
00112 #define xnarch_ulmod(ull, d)         ({ u_long _rem;                    \
00113                                         rthal_uldivrem(ull,d,&_rem); _rem; })
00114 
00115 #define xnarch_ullmul                rthal_ullmul
00116 #define xnarch_uldivrem              rthal_uldivrem
00117 #define xnarch_ulldiv                rthal_ulldiv
00118 #define xnarch_imuldiv               rthal_imuldiv
00119 #define xnarch_llimd                 rthal_llimd
00120 #define xnarch_get_cpu_tsc           rthal_rdtsc
00121 
00122 typedef cpumask_t xnarch_cpumask_t;
00123 
00124 #ifdef CONFIG_SMP
00125 #define xnarch_cpu_online_map            cpu_online_map
00126 #else
00127 #define xnarch_cpu_online_map            cpumask_of_cpu(0)
00128 #endif
00129 #define xnarch_num_online_cpus()          num_online_cpus()
00130 #define xnarch_cpu_set(cpu, mask)         cpu_set(cpu, mask)
00131 #define xnarch_cpu_clear(cpu, mask)       cpu_clear(cpu, mask)
00132 #define xnarch_cpus_clear(mask)           cpus_clear(mask)
00133 #define xnarch_cpu_isset(cpu, mask)       cpu_isset(cpu, mask)
00134 #define xnarch_cpus_and(dst, src1, src2)  cpus_and(dst, src1, src2)
00135 #define xnarch_cpus_equal(mask1, mask2)   cpus_equal(mask1, mask2)
00136 #define xnarch_cpus_empty(mask)           cpus_empty(mask)
00137 #define xnarch_cpumask_of_cpu(cpu)        cpumask_of_cpu(cpu)
00138 #define xnarch_cpu_test_and_set(cpu,mask) cpu_test_and_set(cpu,mask)
00139 
00140 #define xnarch_first_cpu(mask)            first_cpu(mask)
00141 #define XNARCH_CPU_MASK_ALL               CPU_MASK_ALL
00142 
00143 typedef struct xnarch_heapcb {
00144 
00145     atomic_t numaps;    /* # of active user-space mappings. */
00146 
00147     int kmflags;        /* Kernel memory flags (0 if vmalloc()). */
00148 
00149     void *heapbase;     /* Shared heap memory base. */
00150 
00151 } xnarch_heapcb_t;
00152 
00153 #ifdef __cplusplus
00154 extern "C" {
00155 #endif
00156 
00157 static inline long long xnarch_tsc_to_ns (long long ts) {
00158     return xnarch_llimd(ts,1000000000,RTHAL_CPU_FREQ);
00159 }
00160 
00161 static inline long long xnarch_ns_to_tsc (long long ns) {
00162     return xnarch_llimd(ns,RTHAL_CPU_FREQ,1000000000);
00163 }
00164 
00165 static inline unsigned long long xnarch_get_cpu_time (void) {
00166     return xnarch_tsc_to_ns(xnarch_get_cpu_tsc());
00167 }
00168 
00169 static inline unsigned long long xnarch_get_cpu_freq (void) {
00170     return RTHAL_CPU_FREQ;
00171 }
00172 
00173 static inline unsigned xnarch_current_cpu (void) {
00174     return rthal_processor_id();
00175 }
00176 
00177 #define xnarch_declare_cpuid  rthal_declare_cpuid
00178 #define xnarch_get_cpu(flags) rthal_get_cpu(flags)
00179 #define xnarch_put_cpu(flags) rthal_put_cpu(flags)
00180 
00181 #define xnarch_halt(emsg) \
00182 do { \
00183     rthal_emergency_console(); \
00184     xnarch_logerr("fatal: %s\n",emsg); \
00185     show_stack(NULL,NULL);                      \
00186     for (;;) cpu_relax();                       \
00187 } while(0)
00188 
00189 static inline int xnarch_setimask (int imask)
00190 
00191 {
00192     spl_t s;
00193     splhigh(s);
00194     splexit(!!imask);
00195     return !!s;
00196 }
00197 
00198 #ifdef CONFIG_SMP
00199 
00200 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00201 #define xnlock_get_irqsave(lock,x) \
00202     ((x) = __xnlock_get_irqsave(lock, __FILE__, __LINE__,__FUNCTION__))
00203 #else /* !CONFIG_RTAI_SPINLOCK_DEBUG */
00204 #define xnlock_get_irqsave(lock,x)  ((x) = __xnlock_get_irqsave(lock))
00205 #endif /* CONFIG_RTAI_SPINLOCK_DEBUG */
00206 #define xnlock_clear_irqoff(lock)   xnlock_put_irqrestore(lock,1)
00207 #define xnlock_clear_irqon(lock)    xnlock_put_irqrestore(lock,0)
00208 
00209 static inline void xnlock_init (xnlock_t *lock) {
00210 
00211     *lock = XNARCH_LOCK_UNLOCKED;
00212 }
00213 
00214 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00215 
00216 #define XNARCH_DEBUG_SPIN_LIMIT 3000000
00217 
00218 static inline spl_t __xnlock_get_irqsave (xnlock_t *lock,
00219                                           const char *file,
00220                                           unsigned line,
00221                                           const char *function)
00222 {
00223     unsigned spin_count = 0;
00224 #else /* !CONFIG_RTAI_SPINLOCK_DEBUG */
00225 static inline spl_t __xnlock_get_irqsave (xnlock_t *lock)
00226 {
00227 #endif /* CONFIG_RTAI_SPINLOCK_DEBUG */
00228     rthal_declare_cpuid;
00229     unsigned long flags;
00230 
00231     rthal_local_irq_save(flags);
00232 
00233     rthal_load_cpuid();
00234 
00235     if (!test_and_set_bit(cpuid,&lock->lock))
00236         {
00237 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00238         unsigned long long lock_date = rthal_rdtsc();
00239 #endif /* CONFIG_RTAI_SPINLOCK_DEBUG */
00240         while (test_and_set_bit(BITS_PER_LONG - 1,&lock->lock))
00241             /* Use an non-locking test in the inner loop, as Linux'es
00242                bit_spin_lock. */
00243             while (test_bit(BITS_PER_LONG - 1,&lock->lock))
00244                 {
00245                 cpu_relax();
00246 
00247 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00248                 if (++spin_count == XNARCH_DEBUG_SPIN_LIMIT)
00249                     {
00250                     rthal_emergency_console();
00251                     printk(KERN_ERR
00252                            "RTAI: stuck on nucleus lock %p\n"
00253                            "      waiter = %s:%u (%s(), CPU #%d)\n"
00254                            "      owner  = %s:%u (%s(), CPU #%d)\n",
00255                            lock,file,line,function,cpuid,
00256                            lock->file,lock->line,lock->function,lock->cpu);
00257                     show_stack(NULL,NULL);
00258                     for (;;)
00259                         cpu_relax();
00260                     }
00261 #endif /* CONFIG_RTAI_SPINLOCK_DEBUG */
00262                 }
00263 
00264 #ifdef CONFIG_RTAI_SPINLOCK_DEBUG
00265         lock->spin_time = rthal_rdtsc() - lock_date;
00266         lock->lock_date = lock_date;
00267         lock->file = file;
00268         lock->function = function;
00269         lock->line = line;
00270         lock->cpu = cpuid;
00271 #endif /* CONFIG_RTAI_SPINLOCK_DEBUG */
00272         }
00273     else
00274         flags |= 2;
00275 
00276     return flags;
00277 }
00278 
00279 static inline void xnlock_put_irqrestore (xnlock_t *lock, spl_t flags)
00280 
00281 {
00282     if (!(flags & 2))
00283         {
00284         rthal_declare_cpuid;
00285 
00286         rthal_local_irq_disable();
00287 
00288         rthal_load_cpuid();
00289 
00290         if (test_and_clear_bit(cpuid,&lock->lock))
00291             {
00292 #ifdef CONFIG_RTAI_OPT_STATS
00293             extern xnlockinfo_t xnlock_stats[];
00294 
00295             unsigned long long lock_time = rthal_rdtsc() - lock->lock_date;
00296 
00297             if (lock_time > xnlock_stats[cpuid].lock_time)
00298                 {
00299                 xnlock_stats[cpuid].lock_time = lock_time;
00300                 xnlock_stats[cpuid].spin_time = lock->spin_time;
00301                 xnlock_stats[cpuid].file = lock->file;
00302                 xnlock_stats[cpuid].function = lock->function;
00303                 xnlock_stats[cpuid].line = lock->line;
00304                 }
00305 #endif /* CONFIG_RTAI_OPT_STATS */
00306 
00307             clear_bit(BITS_PER_LONG - 1,&lock->lock);
00308             }
00309         }
00310 
00311     rthal_local_irq_restore(flags & 1);
00312 }
00313 
00314 #else /* !CONFIG_SMP */
00315 
00316 #define xnlock_init(lock)              do { } while(0)
00317 #define xnlock_get_irqsave(lock,x)     rthal_local_irq_save(x)
00318 #define xnlock_put_irqrestore(lock,x)  rthal_local_irq_restore(x)
00319 #define xnlock_clear_irqoff(lock)      rthal_local_irq_disable()
00320 #define xnlock_clear_irqon(lock)       rthal_local_irq_enable()
00321 
00322 #endif /* CONFIG_SMP */
00323 
00324 #ifdef XENO_POD_MODULE
00325 
00326 #ifdef CONFIG_SMP
00327 
00328 static inline int xnarch_send_ipi (xnarch_cpumask_t cpumask) {
00329 
00330     return rthal_send_ipi(RTHAL_SERVICE_IPI0, cpumask);
00331 }
00332 
00333 static inline int xnarch_hook_ipi (void (*handler)(void))
00334 
00335 {
00336     return rthal_virtualize_irq(&rthal_domain,
00337                                 RTHAL_SERVICE_IPI0,
00338                                 (void (*)(unsigned)) handler,
00339                                 NULL,
00340                                 IPIPE_HANDLE_MASK);
00341 }
00342 
00343 static inline int xnarch_release_ipi (void)
00344 
00345 {
00346     return rthal_virtualize_irq(&rthal_domain,
00347                                 RTHAL_SERVICE_IPI0,
00348                                 NULL,
00349                                 NULL,
00350                                 IPIPE_PASS_MASK);
00351 }
00352 
00353 static struct linux_semaphore xnarch_finalize_sync;
00354 
00355 static void xnarch_finalize_cpu(unsigned irq)
00356 {
00357     up(&xnarch_finalize_sync);
00358 }
00359 
00360 static inline void xnarch_notify_halt(void)
00361     
00362 {
00363     xnarch_cpumask_t other_cpus = cpu_online_map;
00364     unsigned cpu, nr_cpus = num_online_cpus();
00365     unsigned long flags;
00366     rthal_declare_cpuid;
00367 
00368     sema_init(&xnarch_finalize_sync,0);
00369 
00370     /* Here rthal_current_domain is in fact root, since xnarch_notify_halt is
00371        called from xnpod_shutdown, itself called from Linux
00372        context. */
00373 
00374     rthal_virtualize_irq(rthal_current_domain,
00375                          RTHAL_SERVICE_IPI2,
00376                          xnarch_finalize_cpu,
00377                          NULL,
00378                          IPIPE_HANDLE_MASK);
00379 
00380     rthal_lock_cpu(flags);
00381     cpu_clear(cpuid, other_cpus);
00382     rthal_send_ipi(RTHAL_SERVICE_IPI2, other_cpus);
00383     rthal_unlock_cpu(flags);
00384 
00385     for(cpu=0; cpu < nr_cpus-1; ++cpu)
00386         down(&xnarch_finalize_sync);
00387     
00388     rthal_virtualize_irq(rthal_current_domain,
00389                          RTHAL_SERVICE_IPI2,
00390                          NULL,
00391                          NULL,
00392                          IPIPE_PASS_MASK);
00393 }
00394 
00395 #else /* !CONFIG_SMP */
00396 
00397 static inline int xnarch_send_ipi (xnarch_cpumask_t cpumask) {
00398 
00399     return 0;
00400 }
00401 
00402 static inline int xnarch_hook_ipi (void (*handler)(void)) {
00403 
00404     return 0;
00405 }
00406 
00407 static inline int xnarch_release_ipi (void) {
00408 
00409     return 0;
00410 }
00411 
00412 #define xnarch_notify_halt() /* Nullified */
00413 
00414 #endif /* CONFIG_SMP */
00415 
00416 static inline void xnarch_notify_shutdown(void)
00417 
00418 {
00419 #ifdef CONFIG_SMP
00420     /* The HAL layer also sets the same CPU affinity so that both
00421        modules keep their execution sequence on SMP boxen. */
00422     set_cpus_allowed(current,cpumask_of_cpu(0));
00423 #endif /* CONFIG_SMP */
00424 #ifdef CONFIG_RTAI_OPT_FUSION
00425     xnshadow_release_events();
00426 #endif /* CONFIG_RTAI_OPT_FUSION */
00427     /* Wait for the currently processed events to drain. */
00428     set_current_state(TASK_UNINTERRUPTIBLE);
00429     schedule_timeout(50);
00430     xnarch_release_ipi();
00431 }
00432 
00433 static inline int xnarch_escalate (void)
00434 
00435 {
00436     extern int xnarch_escalation_virq;
00437 
00438     if (rthal_current_domain == rthal_root_domain)
00439         {
00440         spl_t s;
00441         splsync(s);
00442         rthal_trigger_irq(xnarch_escalation_virq);
00443         splexit(s);
00444         return 1;
00445         }
00446 
00447     return 0;
00448 }
00449 
00450 static void xnarch_notify_ready (void)
00451 
00452 {
00453 #ifdef CONFIG_RTAI_OPT_FUSION    
00454     xnshadow_grab_events();
00455 #endif /* CONFIG_RTAI_OPT_FUSION */
00456 }
00457 
00458 static inline unsigned long long xnarch_get_sys_time(void)
00459 {
00460     struct timeval tv;
00461     do_gettimeofday(&tv);
00462     return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000;
00463 }
00464 
00465 #endif /* XENO_POD_MODULE */
00466 
00467 #ifdef XENO_INTR_MODULE
00468 
00469 static inline int xnarch_hook_irq (unsigned irq,
00470                                    void (*handler)(unsigned irq,
00471                                                    void *cookie),
00472                                    int (*ackfn)(unsigned irq),
00473                                    void *cookie)
00474 {
00475     return rthal_irq_request(irq,handler,ackfn,cookie);
00476 }
00477 
00478 static inline int xnarch_release_irq (unsigned irq)
00479 
00480 {
00481     return rthal_irq_release(irq);
00482 }
00483 
00484 static inline int xnarch_enable_irq (unsigned irq)
00485 
00486 {
00487     return rthal_irq_enable(irq);
00488 }
00489 
00490 static inline int xnarch_disable_irq (unsigned irq)
00491 
00492 {
00493     return rthal_irq_disable(irq);
00494 }
00495 
00496 static inline void xnarch_chain_irq (unsigned irq)
00497 
00498 {
00499     rthal_irq_host_pend(irq);
00500 }
00501 
00502 static inline cpumask_t xnarch_set_irq_affinity (unsigned irq,
00503                                                  xnarch_cpumask_t affinity)
00504 {
00505     return rthal_set_irq_affinity(irq,affinity);
00506 }
00507 
00508 #endif /* XENO_INTR_MODULE */
00509 
00510 #ifdef XENO_HEAP_MODULE
00511 
00512 #include <linux/mm.h>
00513 
00514 static inline void xnarch_init_heapcb (xnarch_heapcb_t *hcb)
00515 
00516 {
00517     atomic_set(&hcb->numaps,0);
00518     hcb->kmflags = 0;
00519     hcb->heapbase = NULL;
00520 }
00521 
00522 static inline int xnarch_remap_page_range(struct vm_area_struct *vma,
00523                                           unsigned long uvaddr,
00524                                           unsigned long paddr,
00525                                           unsigned long size,
00526                                           pgprot_t prot)
00527 {
00528 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
00529     return remap_pfn_range(vma,uvaddr,paddr >> PAGE_SHIFT,size,prot);
00530 #else /* Linux version < 2.6.10 */
00531     return remap_page_range(vma,uvaddr,paddr,size,prot);
00532 #endif /* Linux version >= 2.6.10 */
00533 }
00534 
00535 #endif /* XENO_HEAP_MODULE */
00536 
00537 #ifdef __cplusplus
00538 }
00539 #endif
00540 
00541 /* Dashboard and graph control. */
00542 #define XNARCH_DECL_DISPLAY_CONTEXT();
00543 #define xnarch_init_display_context(obj)
00544 #define xnarch_create_display(obj,name,tag)
00545 #define xnarch_delete_display(obj)
00546 #define xnarch_post_graph(obj,state)
00547 #define xnarch_post_graph_if(obj,state,cond)
00548 
00549 #else /* !__KERNEL__ */
00550 
00551 #include <nucleus/system.h>
00552 
00553 #endif /* __KERNEL__ */
00554 
00555 #endif /* !_RTAI_ASM_GENERIC_SYSTEM_H */

Generated on Sat Sep 3 12:32:46 2005 for RTAI Fusion API by  doxygen 1.4.2