Skip to content

Commit 3e0eb8a

Browse files
aescolarkartben
authored andcommitted
native_simulator: Get latest from upstream
Align with native_simulator's upstream main 19293fafc9959b03ece651e5e2afb768cfa891cf Which includes: 19293fa misc trivial changes to please static analyzers 2a41263 nsi_tracing: Annotate functions as noreturn f0307c1 nct: Simplify and improve switching performance 9f0c825 nce: Optimize/improve performance 63ce7e2 nsi_utils: Add macro to define static inline functions 6035bd8 nsi_errno: Minor optimization with no functional impact Signed-off-by: Alberto Escolar Piedras <[email protected]>
1 parent 22cac4f commit 3e0eb8a

File tree

12 files changed

+224
-362
lines changed

12 files changed

+224
-362
lines changed

scripts/native_simulator/common/src/include/nsi_tracing.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define NSI_COMMON_SRC_INCL_NSI_TRACING_H
99

1010
#include <stdarg.h>
11+
#include "nsi_utils.h"
1112

1213
#ifdef __cplusplus
1314
extern "C" {
@@ -21,10 +22,10 @@ extern "C" {
2122
* All print()/vprint() APIs take the same arguments as printf()/vprintf().
2223
*/
2324

24-
void nsi_print_error_and_exit(const char *format, ...);
25+
NSI_FUNC_NORETURN void nsi_print_error_and_exit(const char *format, ...);
2526
void nsi_print_warning(const char *format, ...);
2627
void nsi_print_trace(const char *format, ...);
27-
void nsi_vprint_error_and_exit(const char *format, va_list vargs);
28+
NSI_FUNC_NORETURN void nsi_vprint_error_and_exit(const char *format, va_list vargs);
2829
void nsi_vprint_warning(const char *format, va_list vargs);
2930
void nsi_vprint_trace(const char *format, va_list vargs);
3031

scripts/native_simulator/common/src/include/nsi_utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#define NSI_FUNC_NORETURN __attribute__((__noreturn__))
3333
#define NSI_WEAK __attribute__((__weak__))
34+
#define NSI_INLINE static __attribute__((__always_inline__)) inline
3435

3536
#if defined(__clang__)
3637
/* The address sanitizer in llvm adds padding (redzones) after data

scripts/native_simulator/common/src/main.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ int main(int argc, char *argv[])
121121
nsi_hws_one_event();
122122
}
123123

124-
/* This line should be unreachable */
125-
return 1; /* LCOV_EXCL_LINE */
124+
NSI_CODE_UNREACHABLE; /* LCOV_EXCL_LINE */
126125
}
127126

128127
#endif /* NSI_NO_MAIN */

scripts/native_simulator/common/src/nce.c

Lines changed: 36 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@
1616
* a time. Check the docs for more info.
1717
*/
1818

19-
#include <pthread.h>
2019
#include <stdbool.h>
21-
#include <unistd.h>
2220
#include <stdlib.h>
21+
#include <unistd.h>
22+
#include <pthread.h>
23+
#include <semaphore.h>
24+
#include <errno.h>
25+
#include "nsi_utils.h"
2326
#include "nce_if.h"
2427
#include "nsi_safe_call.h"
2528

2629
struct nce_status_t {
27-
/* Conditional variable to know if the CPU is running or halted/idling */
28-
pthread_cond_t cond_cpu;
29-
/* Mutex for the conditional variable cond_cpu */
30-
pthread_mutex_t mtx_cpu;
31-
/* Variable which tells if the CPU is halted (1) or not (0) */
30+
sem_t sem_sw; /* Semaphore to hold the CPU/SW thread(s) */
31+
sem_t sem_hw; /* Semaphore to hold the HW thread */
3232
bool cpu_halted;
3333
bool terminate; /* Are we terminating the program == cleaning up */
3434
void (*start_routine)(void);
@@ -48,6 +48,16 @@ struct nce_status_t {
4848

4949
extern void nsi_exit(int exit_code);
5050

51+
NSI_INLINE int nce_sem_rewait(sem_t *semaphore)
52+
{
53+
int ret;
54+
55+
while ((ret = sem_wait(semaphore)) == EINTR) {
56+
/* Restart wait if we were interrupted */
57+
}
58+
return ret;
59+
}
60+
5161
/*
5262
* Initialize an instance of the native simulator CPU emulator
5363
* and return a pointer to it.
@@ -65,8 +75,8 @@ void *nce_init(void)
6575
this->cpu_halted = true;
6676
this->terminate = false;
6777

68-
NSI_SAFE_CALL(pthread_cond_init(&this->cond_cpu, NULL));
69-
NSI_SAFE_CALL(pthread_mutex_init(&this->mtx_cpu, NULL));
78+
NSI_SAFE_CALL(sem_init(&this->sem_sw, 0, 0));
79+
NSI_SAFE_CALL(sem_init(&this->sem_hw, 0, 0));
7080

7181
return (void *)this;
7282
}
@@ -104,13 +114,9 @@ void nce_terminate(void *this_arg)
104114
} else if (this->terminate == false) {
105115

106116
this->terminate = true;
107-
108-
NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_cpu));
109-
110117
this->cpu_halted = true;
111118

112-
NSI_SAFE_CALL(pthread_cond_broadcast(&this->cond_cpu));
113-
NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_cpu));
119+
NSI_SAFE_CALL(sem_post(&this->sem_hw));
114120

115121
while (1) {
116122
sleep(1);
@@ -123,56 +129,15 @@ void nce_terminate(void *this_arg)
123129
/* LCOV_EXCL_STOP */
124130
}
125131

126-
/**
127-
* Helper function which changes the status of the CPU (halted or running)
128-
* and waits until somebody else changes it to the opposite
129-
*
130-
* Both HW and SW threads will use this function to transfer control to the
131-
* other side.
132-
*
133-
* This is how the idle thread halts the CPU and gets halted until the HW models
134-
* raise a new interrupt; and how the HW models awake the CPU, and wait for it
135-
* to complete and go to idle.
136-
*/
137-
static void change_cpu_state_and_wait(struct nce_status_t *this, bool halted)
138-
{
139-
NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_cpu));
140-
141-
NCE_DEBUG("Going to halted = %d\n", halted);
142-
143-
this->cpu_halted = halted;
144-
145-
/* We let the other side know the CPU has changed state */
146-
NSI_SAFE_CALL(pthread_cond_broadcast(&this->cond_cpu));
147-
148-
/* We wait until the CPU state has been changed. Either:
149-
* we just awoke it, and therefore wait until the CPU has run until
150-
* completion before continuing (before letting the HW models do
151-
* anything else)
152-
* or
153-
* we are just hanging it, and therefore wait until the HW models awake
154-
* it again
155-
*/
156-
while (this->cpu_halted == halted) {
157-
/* Here we unlock the mutex while waiting */
158-
pthread_cond_wait(&this->cond_cpu, &this->mtx_cpu);
159-
}
160-
161-
NCE_DEBUG("Awaken after halted = %d\n", halted);
162-
163-
NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_cpu));
164-
}
165-
166132
/*
167133
* Helper function that wraps the SW start_routine
168134
*/
169135
static void *sw_wrapper(void *this_arg)
170136
{
171137
struct nce_status_t *this = (struct nce_status_t *)this_arg;
172138

173-
/* Ensure nce_boot_cpu has reached the cond loop */
174-
NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_cpu));
175-
NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_cpu));
139+
/* Ensure nce_boot_cpu is blocked in nce_wake_cpu() */
140+
NSI_SAFE_CALL(nce_sem_rewait(&this->sem_sw));
176141

177142
#if (NCE_DEBUG_PRINTS)
178143
pthread_t sw_thread = pthread_self();
@@ -198,25 +163,14 @@ void nce_boot_cpu(void *this_arg, void (*start_routine)(void))
198163
{
199164
struct nce_status_t *this = (struct nce_status_t *)this_arg;
200165

201-
NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_cpu));
202-
203-
this->cpu_halted = false;
204166
this->start_routine = start_routine;
205167

206168
/* Create a thread for the embedded SW init: */
207169
pthread_t sw_thread;
208170

209171
NSI_SAFE_CALL(pthread_create(&sw_thread, NULL, sw_wrapper, this_arg));
210172

211-
/* And we wait until the embedded OS has send the CPU to sleep for the first time */
212-
while (this->cpu_halted == false) {
213-
pthread_cond_wait(&this->cond_cpu, &this->mtx_cpu);
214-
}
215-
NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_cpu));
216-
217-
if (this->terminate) {
218-
nsi_exit(0);
219-
}
173+
nce_wake_cpu(this_arg);
220174
}
221175

222176
/*
@@ -236,7 +190,12 @@ void nce_halt_cpu(void *this_arg)
236190
nsi_print_error_and_exit("Programming error on: %s ",
237191
"This CPU was already halted\n");
238192
}
239-
change_cpu_state_and_wait(this, true);
193+
this->cpu_halted = true;
194+
195+
NSI_SAFE_CALL(sem_post(&this->sem_hw));
196+
NSI_SAFE_CALL(nce_sem_rewait(&this->sem_sw));
197+
198+
NCE_DEBUG("CPU awaken, HW thread held\n");
240199
}
241200

242201
/*
@@ -255,7 +214,13 @@ void nce_wake_cpu(void *this_arg)
255214
nsi_print_error_and_exit("Programming error on: %s ",
256215
"This CPU was already awake\n");
257216
}
258-
change_cpu_state_and_wait(this, false);
217+
218+
this->cpu_halted = false;
219+
220+
NSI_SAFE_CALL(sem_post(&this->sem_sw));
221+
NSI_SAFE_CALL(nce_sem_rewait(&this->sem_hw));
222+
223+
NCE_DEBUG("CPU went to sleep, HW continues\n");
259224

260225
/*
261226
* If while the SW was running it was decided to terminate the execution

0 commit comments

Comments
 (0)