Skip to content

Commit e9ca7dc

Browse files
committed
Fix: Remove all printf from active tasks (printf not thread-safe)
Root cause: Printf is not thread-safe in preemptive multitasking environment. Evidence: Tasks hang consistently when calling printf concurrently: - Run #19502124408: 'Task A: [' hangs on first printf in task Solution: Remove all printf calls from task_a and task_b execution loops. Monitor task only prints final results after waiting for tasks to idle. Rationale: - Printf uses shared UART buffer/state without synchronization - Preemptive task switching during printf causes corruption/deadlock - Monitor waits for task completion + 50 yields before printing - This ensures tasks are idle/yielding when printf executes Impact: - No runtime diagnostics during test (but tests should complete quickly) - Final PASS/FAIL output will print if test succeeds - Preserves functional correctness testing without printf conflicts
1 parent d48c37c commit e9ca7dc

File tree

1 file changed

+8
-34
lines changed

1 file changed

+8
-34
lines changed

app/mutex.c

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,17 @@ static int currently_in_critical_section = 0;
1818
/* Enhanced Task A */
1919
void task_a(void)
2020
{
21-
printf("Task A (ID %d) starting...\n", mo_task_id());
21+
/* WORKAROUND: Printf not thread-safe in preemptive mode - minimize usage */
2222

2323
for (int i = 0; i < MAX_ITERATIONS; i++) {
24-
printf("Task A: Requesting mutex (iteration %d)\n", i + 1);
2524
mo_sem_wait(binary_mutex);
2625

2726
/* === CRITICAL SECTION START === */
2827
if (currently_in_critical_section != 0) {
29-
printf("Task A: VIOLATION - Multiple tasks in critical section!\n");
3028
critical_section_violations++;
3129
}
3230
currently_in_critical_section = mo_task_id();
3331

34-
printf("Task A: Entering critical section\n");
3532
int old_counter = shared_counter;
3633

3734
/* Simulate work with yields instead of delays */
@@ -40,26 +37,20 @@ void task_a(void)
4037

4138
shared_counter = old_counter + 1;
4239
task_a_count++;
43-
printf("Task A: Updated counter: %d -> %d\n", old_counter,
44-
shared_counter);
4540

4641
if (currently_in_critical_section != mo_task_id()) {
47-
printf("Task A: VIOLATION - Critical section corrupted!\n");
4842
critical_section_violations++;
4943
}
5044
currently_in_critical_section = 0;
5145
/* === CRITICAL SECTION END === */
5246

5347
mo_sem_signal(binary_mutex);
54-
printf("Task A: Released mutex\n");
5548

5649
/* Cooperative scheduling */
5750
for (int j = 0; j < COOPERATION_YIELDS; j++)
5851
mo_task_yield();
5952
}
6053

61-
printf("Task A completed %d iterations\n", task_a_count);
62-
6354
/* Keep running to prevent panic */
6455
while (1) {
6556
for (int i = 0; i < 10; i++)
@@ -70,28 +61,21 @@ void task_a(void)
7061
/* Enhanced Task B */
7162
void task_b(void)
7263
{
73-
printf("Task B (ID %d) starting...\n", mo_task_id());
64+
/* WORKAROUND: Printf not thread-safe in preemptive mode - minimize usage */
7465

7566
for (int i = 0; i < MAX_ITERATIONS; i++) {
76-
printf("Task B: Trying trylock (iteration %d)\n", i + 1);
77-
7867
/* Try non-blocking first */
7968
int32_t trylock_result = mo_sem_trywait(binary_mutex);
8069
if (trylock_result != ERR_OK) {
81-
printf("Task B: Mutex busy, using blocking wait\n");
8270
mo_sem_wait(binary_mutex);
83-
} else {
84-
printf("Task B: Trylock succeeded\n");
8571
}
8672

8773
/* === CRITICAL SECTION START === */
8874
if (currently_in_critical_section != 0) {
89-
printf("Task B: VIOLATION - Multiple tasks in critical section!\n");
9075
critical_section_violations++;
9176
}
9277
currently_in_critical_section = mo_task_id();
9378

94-
printf("Task B: Entering critical section\n");
9579
int old_counter = shared_counter;
9680

9781
/* Simulate work */
@@ -100,26 +84,20 @@ void task_b(void)
10084

10185
shared_counter = old_counter + 10;
10286
task_b_count++;
103-
printf("Task B: Updated counter: %d -> %d\n", old_counter,
104-
shared_counter);
10587

10688
if (currently_in_critical_section != mo_task_id()) {
107-
printf("Task B: VIOLATION - Critical section corrupted!\n");
10889
critical_section_violations++;
10990
}
11091
currently_in_critical_section = 0;
11192
/* === CRITICAL SECTION END === */
11293

11394
mo_sem_signal(binary_mutex);
114-
printf("Task B: Released mutex\n");
11595

11696
/* Cooperative scheduling */
11797
for (int j = 0; j < COOPERATION_YIELDS; j++)
11898
mo_task_yield();
11999
}
120100

121-
printf("Task B completed %d iterations\n", task_b_count);
122-
123101
/* Keep running to prevent panic */
124102
while (1) {
125103
for (int i = 0; i < 10; i++)
@@ -130,23 +108,15 @@ void task_b(void)
130108
/* Simple monitor task */
131109
void monitor_task(void)
132110
{
133-
printf("Monitor starting...\n");
111+
/* WORKAROUND: Printf not thread-safe - only print at end when tasks idle */
134112

135113
int cycles = 0;
136114

137115
while (cycles < 50) { /* Monitor for reasonable time */
138116
cycles++;
139117

140-
/* Check progress every few cycles */
141-
if (cycles % 10 == 0) {
142-
printf("Monitor: A=%d, B=%d, Counter=%d, Violations=%d\n",
143-
task_a_count, task_b_count, shared_counter,
144-
critical_section_violations);
145-
}
146-
147118
/* Check if both tasks completed */
148119
if (task_a_count >= MAX_ITERATIONS && task_b_count >= MAX_ITERATIONS) {
149-
printf("Monitor: Both tasks completed successfully\n");
150120
break;
151121
}
152122

@@ -155,7 +125,11 @@ void monitor_task(void)
155125
mo_task_yield();
156126
}
157127

158-
/* Final report */
128+
/* Wait a bit for tasks to fully idle */
129+
for (int i = 0; i < 50; i++)
130+
mo_task_yield();
131+
132+
/* Final report - safe to print when other tasks are idle */
159133
printf("\n=== FINAL RESULTS ===\n");
160134
printf("Task A iterations: %d\n", task_a_count);
161135
printf("Task B iterations: %d\n", task_b_count);

0 commit comments

Comments
 (0)