pincputest
shall verify that a peer thread being pinned to a new cpu is rescheduled properly; particular attention shall be given to situations where the thread can be rescheduled right away.
In order to cover all cases, the test shall ensure that the peer thread rescheduling happens:
Note: the real-time threads are not collaboratively time-sliced with other threads on their current cpu. This implies that a real-time thread will have to become BLOCKED or SLEEPING before it can be interrupted.
In order to be able to set the peer thread in a given state, we need to use a control thread with same or higher priority than the peer thread. This control thread will be the unittest thread
. The thread responsible for pinning the peer
thread is called the main
thread.
Below sections illustrates the interactions between the unittest
thread, the main
thread and the peer
thread to reach the expected peer
thread state in the various cases described above.
thread_set_pinned_cpu
on a [RUNNING]
peer
sequenceDiagram participant U as unitest thread (priority peer+1) participant M as main thread (priority peer+/-1) participant P as peer thread (priority peer) Note over U, P: Testing thread_set_pinned_cpu on a [RUNNING] peer Note over M: main [BLOCKED] Note over P: peer [BLOCKED] U->>U:thread_set_pinned_cpu(get_current_thread(), p) U->>P:thread_set_pinned_cpu(peer.thread, p) U->>M:thread_set_pinned_cpu(peer.thread, p+1 or p+2) Note over M: main is pinned to another or same cpu than peer will be<br/> allowing to test cases where<br/> 1) either current cpu needs to be rescheduled<br/> or 2) another cpu than current U->>U: spin_lock(&peer.lock) U->>+P: event_signal(&peer.ev_req) P->>P: spin_lock(&peer.lock) Note over P: peer [READY] until unittest in [BLOCKED] U->>+M: event_signal(&main.ev_req) U->>+U: event_wait(&main.ev_resp) Note over U: unittest [BLOCKED] U-->>P: peer thread scheduled on cpu p Note over P: peer [RUNNING] M->>M: loop until peer is [RUNNING] M->>P: thread_set_pinned_cpu(p+1 or p+2) M-->>P: peer thread scheduled on p+1 or p+2 Note over P: peer in [RUNNING] on the spin_lock M->>U: event_signal(&main.ev_resp) M-->>U: unitest unblocked by main Note over U: unittest [RUNNING] U->>U: spin_unlock(&peer.lock) U-->>P: peer is unlocked by unittest Note over P: peer is [RUNNING] unlocked from spin U->>U: wait(&peer.ev_resp) Note over U: unittest [BLOCKED] P->>P: set actual_cpu P->>U: event_signal(&peer.ev_resp) P->>P: ev_wait(peer.ev_req) P-->>U: unittest unblocked by peer Note over P: peer [BLOCKED] M->>M: ev_wait(peer.ev_req) Note over M: main [BLOCKED] U->>U: check actual_cpu == p+1 or p+2
thread_set_pinned_cpu
on a [READY]
peer
sequenceDiagram participant U as unitest thread (priority peer+1) participant M as main thread (priority peer+/-1) participant P as peer thread (priority peer) Note over U, P: Testing thread_set_pinned_cpu on a [READY] peer Note over M: main [BLOCKED] Note over P: peer [BLOCKED] U->>U:thread_set_pinned_cpu(get_current_thread(), p) U->>P:thread_set_pinned_cpu(peer.thread, p) U->>M:thread_set_pinned_cpu(peer.thread, p+1 or p+2) Note over M: main is pinned to another or same cpu than peer will be<br/> allowing to test cases where<br/> 1) either current cpu needs to be rescheduled<br/> or 2) another cpu than current U->>U: spin_lock(&peer.lock) U->>+P: event_signal(&peer.ev_req) P->>P: spin_lock(&peer.lock) Note over P: peer [READY] until unittest in [BLOCKED] U->>+M: event_signal(&main.ev_req) U->>+U: event_wait(&main.ev_resp) Note over U: unittest [BLOCKED] U-->>P: peer thread scheduled on cpu p Note over P: peer [RUNNING] M->>M: spin_lock(&main.lock) M->>-U: event_signal(&main.ev_resp) M->>M: loop until peer is [READY] Note over U: unittest [RUNNING] U-->>P: peer thread scheduled out of cpu p Note over P: peer [READY] U->>U: spin_lock(&main.lock) Note over U: unittest [RUNNING] in busy loop due to locked lock M->>P: thread_set_pinned_cpu(p+1) Note over P: peer thread still spin locked in [READY] M->>M: spin_unlock(&main.lock) M-->>U: unittest unlocked U->>P: spin_unlock(&peer.lock) Note over P: peer thread [RUNNING] but still locked on spin_lock U->>U: event_wait(&peer_ev_resp) U-->>P: peer thread unlocked Note over P: peer thread [RUNNING] M-->>P: peer thread scheduled on p+1 P->>P: set actual_cpu P->>U: event_signal(&peer.ev_resp) P->>P: ev_wait(peer.ev_req) Note over P: peer [BLOCKED] M->>M: ev_wait(peer.ev_req) Note over M: main [BLOCKED] U->>U: check actual_cpu == p+1
thread_set_pinned_cpu
on a [BLOCKED]
peer
sequenceDiagram participant U as unitest thread (priority peer+1) participant M as main thread (priority peer+/-1) participant P as peer thread (priority peer) Note over U, P: Testing thread_set_pinned_cpu on a [BLOCKED] peer Note over M: main [BLOCKED] Note over P: peer [BLOCKED] U->>U:thread_set_pinned_cpu(get_current_thread(), p) U->>P:thread_set_pinned_cpu(peer.thread, p) U->>M:thread_set_pinned_cpu(peer.thread, p+1 or p+2) Note over M: main is pinned to another or same cpu than peer will be<br/> allowing to test cases where<br/> 1) either current cpu needs to be rescheduled<br/> or 2) another cpu than current U->>+P: event_signal(&peer.ev_req) P->>P: event_wait(&peer.blocked_ev) Note over P: peer [BLOCKED] U->>+M: event_signal(&main.ev_req) U->>+U: event_wait(&main.ev_resp) Note over U: unittest [BLOCKED] M->>M: loop until peer is [BLOCKED] M->>P: thread_set_pinned_cpu(p+1 or p+2) M->>U: event_signal(&main.ev_resp) M-->>U: unittest unblocked by main Note over U: unittest [RUNNING] U->>P: event_signal(&peer.blocked_ev) U-->>P: peer unblocked by unittest M-->>P: peer thread scheduled on p+1 or p+2 Note over P: peer [RUNNING] P->>P: set actual_cpu P->>U: event_signal(&peer.ev_resp) P->>P: ev_wait(peer.ev_req) Note over P: peer [BLOCKED] M->>M: ev_wait(peer.ev_req) Note over M: main [BLOCKED] U->>U: wait(&peer.ev_resp) U->>U: check actual_cpu == p+1 or p+2
thread_set_pinned_cpu
on a [SLEEPING]
peer
sequenceDiagram participant U as unitest thread (priority peer+1) participant M as main thread (priority peer+/-1) participant P as peer thread (priority peer) Note over U, P: Testing thread_set_pinned_cpu on a [SLEEPING] peer Note over M: main [BLOCKED] Note over P: peer [BLOCKED] U->>U:thread_set_pinned_cpu(get_current_thread(), p) U->>P:thread_set_pinned_cpu(peer.thread, p) U->>M:thread_set_pinned_cpu(peer.thread, p+1 or p+2) Note over M: main is pinned to another or same cpu than peer will be<br/> allowing to test cases where<br/> 1) either current cpu needs to be rescheduled<br/> or 2) another cpu than current U->>+P: event_signal(&peer.ev_req) P->>P: thread_sleep_ns(100ms) Note over P: peer [SLEEPING] U->>+M: event_signal(&main.ev_req) U->>+U: event_wait(&main.ev_resp) Note over U: unittest [BLOCKED] M->>M: loop until peer is [SLEEPING] M->>P: thread_set_pinned_cpu(p+1 or p+2) M->>U: event_signal(&main.ev_resp) M-->>U: unittest unblocked by main Note over U: unittest [RUNNING] M->>M: ev_wait(peer.ev_req) Note over M: main [BLOCKED] U->>U: wait(&peer.ev_resp) Note over U: unittest [BLOCKING] P-->>P: timer interrupt: waking-up peer M-->>P: peer thread scheduled on p+1 or p+2 Note over P: peer [RUNNING] P->>P: set actual_cpu P->>U: event_signal(&peer.ev_resp) P->>P: ev_wait(peer.ev_req) Note over P: peer [BLOCKED] P-->>U: unittest unblocked by peer U->>U: check actual_cpu == p+1 or p+2