tree: 9d0335fca91688fc90e42633beb0d7402db0b8ec [path history] [tgz]
  1. pincputest.c
  2. README.md
  3. rules.mk
app/pincputest/README.md

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:

  1. in any possible state of the peer thread (running, ready, blocked, sleeping),
  2. whether the newly pinned cpu is the current cpu or another cpu
  3. whether the thread from which the peer thread is pinned is a higher or lower priority than the peer thread
  4. and finally whether the involved threads are standard or real-time threads.

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.

Testing 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

Testing 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

Testing 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

Testing 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