Project Home
Project Home
Documents
Documents
Wiki
Wiki
Discussion Forums
Discussions
Project Information
Project Info
Forum Topic - ISR on SMP: (8 Items)
   
ISR on SMP  
Hi, 
I have a question: 
When running on a SMP configuration, could I have concurrent ISRs running on each processor? 

This is my scenario: I receive a pulse to do time correction so when I am reading/writing the qtime (nsec) I would like 
to make sure I am not in the middle of an update of the system clock.

Thank you,
Javier
Re: ISR on SMP  
After running test. 
Conclusion: Concurrent ISR.

Question: Is there any way top avoid the clock ISR to be running concurrently? 

Any help is appreciated :)
Javier
Re: ISR on SMP  
Is there any QNX system guy on this forum?

Thank you...
Re: ISR on SMP  
Hi Javier,

I am not a QNX employee, but my intial recommendation would be to suggest using InterruptAttachEvent() and a very very 
high priority user-mode thread that just calls clock_gettime(), which  just uses the kernel's internal code to ensure 
interlocking with the tick interrupt.   It you've got the ability to measure the latency, it might be worth benchmarking
 the latency of using that approach instead of an InterruptAttach() interrupt handler - there are a lot fewer 
restrictions on what you can do in your handler, and it makes debugging much easier.

Assuming that InterruptAttachEvent() adds measurable delay that your application cannot tolerate, the next 
recommendation would be to do as the kernel does internally, and just inspect the time in a loop to make sure it hasn't 
changed (and therefore you have an atomic read!):

Here is some example code (untested from memory, so you might have to fix it up):

void get_current_time(uint64_t* time_out, int include_time_of_day) {
  volatile uint64_t* nsec_vol = &(SYSPAGE_ENTRY(qtime)->nsec);
  int64_t adjust;
  do {
    *time_out = *nsec_vol;
    adjust = SYSPAGE_ENTRY(qtime)->nsec_tod_adjust;
  } while (*time_out != *nsec_vol);
  if (include_time_of_day) *time_out += adjust;
}

Hope this helps some,

-Will
Re: ISR on SMP  
> This is my scenario: I receive a pulse to do time correction so when I am 
> reading/writing the qtime (nsec) I would like to make sure I am not in the 
> middle of an update of the system clock.

Just read time in loop util you get two matching values in a row.
Re: ISR on SMP  
Hi guys, 
Thank you for the update.

Here is what I am doing right now.


volatile qtime_entry* qtime_ptr_;

//-Map the qtime kernel struct to local memory
void init_memory(){
    struct qtime_entry* kernel_qtime = SYSPAGE_ENTRY ( qtime );
    off64_t offset = 0;
    if( -1 == mem_offset64(kernel_qtime, NOFD, sizeof(qtime_entry), &offset, 0)){
        fprintf(stderr, "Failed to get phyaddr %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
    printf("Qtime physical addr 0x%x\n", offset);
    qtime_ptr_ = (struct qtime_entry*) mmap_device_memory(0, sizeof(qtime_entry), PROT_READ | PROT_WRITE | PROT_NOCACHE,
 0, offset);
    if (qtime_ptr_ == MAP_FAILED){
        fprintf(stderr, "Failed to map qtime %s\n", strerror(errno));
        exit(EXIT_FAILURE);
    }
}

//-ISR
const struct sigevent * isr(void* p, int id) {
            //If not interrupt pending on my HW return NULL
            .....
            //-Disable timing interrupt
            InterruptMask(qtime_ptr_->intr, -1);
            //-Read until there is no change (this will ensure the clock is not in the middle of an update)
            uint64_t current_nsec;
            do{
                current_nsec = qtime_ptr_->nsec;
            } while (qtime_ptr_->nsec != current_nsec);

            //-Adjust clock (set it to next_time_sec & next_time_nsec)
            qtime_ptr_->nsec_tod_adjust =  (next_time_sec * 1000000000) + next_time_nsec -
 current_nsec;
            InterruptUnmask(qtime_ptr_->intr, -1);

            //-Fire event
            return (&intr_event_);
  
}

If the 2 ISRs can run concurrently the only way to do a proper synchronization would be to share a spinlock (which I do 
believe QNX has it but is only internal to the Kernel). So far this is the best I ca do. If you have any ideas or 
critics go ahead…

Javier
RE: ISR on SMP  

> -----Message d'origine-----
> De : Javier A. [mailto:community-noreply@qnx.com]
> Envoyé : 10 septembre 2012 13:28
> À : ostech-core_os
> Objet : Re: ISR on SMP
> 
> Hi guys,
> Thank you for the update.
> 
> Here is what I am doing right now.
> 
> 
> volatile qtime_entry* qtime_ptr_;
> 

There is no need to use mmap, qtime is already mmaped for you

> //-Map the qtime kernel struct to local memory void init_memory(){
>     struct qtime_entry* kernel_qtime = SYSPAGE_ENTRY ( qtime );
>     off64_t offset = 0;
>     if( -1 == mem_offset64(kernel_qtime, NOFD, sizeof(qtime_entry), &offset,
> 0)){
>         fprintf(stderr, "Failed to get phyaddr %s\n", strerror(errno));
>         exit(EXIT_FAILURE);
>     }
>     printf("Qtime physical addr 0x%x\n", offset);
>     qtime_ptr_ = (struct qtime_entry*) mmap_device_memory(0,
> sizeof(qtime_entry), PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, offset);
>     if (qtime_ptr_ == MAP_FAILED){
>         fprintf(stderr, "Failed to map qtime %s\n", strerror(errno));
>         exit(EXIT_FAILURE);
>     }
> }
> 
> //-ISR
> const struct sigevent * isr(void* p, int id) {
>             //If not interrupt pending on my HW return NULL
>             .....

I don't see the point of disabling the interrupt 

>             //-Disable timing interrupt
>             InterruptMask(qtime_ptr_->intr, -1);
>             //-Read until there is no change (this will ensure the clock is not in the
> middle of an update)
>             uint64_t current_nsec;
>             do{
>                 current_nsec = qtime_ptr_->nsec;
>             } while (qtime_ptr_->nsec != current_nsec);
> 

I have no idea if this is allowed or supported

>             //-Adjust clock (set it to next_time_sec & next_time_nsec)
>             qtime_ptr_->nsec_tod_adjust =  (next_time_sec * 
1000000000) +
> next_time_nsec - current_nsec;
>             InterruptUnmask(qtime_ptr_->intr, -1);
> 
>             //-Fire event
>             return (&intr_event_);
> 
> }
> 
> If the 2 ISRs can run concurrently the only way to do a proper synchronization
> would be to share a spinlock (which I do believe QNX has it but is only
> internal to the Kernel). So far this is the best I ca do. If you have any ideas or
> critics go ahead…
> 
> Javier
> 
> 
> 
> _______________________________________________
> 
> OSTech
> http://community.qnx.com/sf/go/post95486
> To cancel your subscription to this discussion, please e-mail ostech-core_os-
> unsubscribe@community.qnx.com
Re: RE: ISR on SMP  
Hi,
The 2 ISRs do run concurrently.
Now the problem is this: am I allowed to change QTIME from the ISR? (Is this supported?)


Thanks,
Javier