Coverage Report

Created: 2026-03-11 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/u-boot/test/lib/uthread.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 * Copyright 2025 Linaro Limited
4
 *
5
 * Unit test for uthread
6
 */
7
8
#include <stdbool.h>
9
#include <test/lib.h>
10
#include <test/ut.h>
11
#include <uthread.h>
12
13
static int count;
14
15
/* A thread entry point */
16
static void worker(void *arg)
17
0
{
18
0
  int loops = (int)(unsigned long)arg;
19
0
  int i;
20
21
0
  for (i = 0; i < loops; i++) {
22
0
    count++;
23
0
    uthread_schedule();
24
0
  }
25
0
}
26
27
/*
28
 * uthread() - testing the uthread API
29
 *
30
 * This function creates two threads with the same entry point. The first one
31
 * receives 5 as an argument, the second one receives 10. The number indicates
32
 * the number of time the worker thread should loop on uthread_schedule()
33
 * before returning. The workers increment a global counter each time they loop.
34
 * As a result the main thread knows how many times it should call
35
 * uthread_schedule() to let the two threads proceed, and it also knows which
36
 * value the counter should have at any moment.
37
 */
38
static int uthread(struct unit_test_state *uts)
39
0
{
40
0
  int i;
41
0
  int id1, id2;
42
43
0
  count = 0;
44
0
  id1 = uthread_grp_new_id();
45
0
  ut_assert(id1 != 0);
46
0
  id2 = uthread_grp_new_id();
47
0
  ut_assert(id2 != 0);
48
0
  ut_assert(id1 != id2);
49
0
  ut_assertok(uthread_create(NULL, worker, (void *)5, 0, id1));
50
0
  ut_assertok(uthread_create(NULL, worker, (void *)10, 0, 0));
51
  /*
52
   * The first call is expected to schedule the first worker, which will
53
   * schedule the second one, which will schedule back to the main thread
54
   * (here). Therefore count should be 2.
55
   */
56
0
  ut_assert(uthread_schedule());
57
0
  ut_asserteq(2, count);
58
0
  ut_assert(!uthread_grp_done(id1));
59
  /* Four more calls should bring the count to 10 */
60
0
  for (i = 0; i < 4; i++) {
61
0
    ut_assert(!uthread_grp_done(id1));
62
0
    ut_assert(uthread_schedule());
63
0
  }
64
0
  ut_asserteq(10, count);
65
  /* This one allows the first worker to exit */
66
0
  ut_assert(uthread_schedule());
67
  /* At this point there should be no runnable thread in group 'id1' */
68
0
  ut_assert(uthread_grp_done(id1));
69
  /* Five more calls for the second worker to finish incrementing  */
70
0
  for (i = 0; i < 5; i++)
71
0
    ut_assert(uthread_schedule());
72
0
  ut_asserteq(15, count);
73
  /* Plus one call to let the second worker return from its entry point */
74
0
  ut_assert(uthread_schedule());
75
  /* Now both tasks should be done, schedule should return false */
76
0
  ut_assert(!uthread_schedule());
77
78
0
  return 0;
79
0
}
80
LIB_TEST(uthread, 0);
81
82
struct mw_args {
83
  struct unit_test_state *uts;
84
  struct uthread_mutex *m;
85
  int flag;
86
};
87
88
static int mutex_worker_ret;
89
90
static int _mutex_worker(struct mw_args *args)
91
0
{
92
0
  struct unit_test_state *uts = args->uts;
93
94
0
  ut_asserteq(-EBUSY, uthread_mutex_trylock(args->m));
95
0
  ut_assertok(uthread_mutex_lock(args->m));
96
0
  args->flag = 1;
97
0
  ut_assertok(uthread_mutex_unlock(args->m));
98
99
0
  return 0;
100
0
}
101
102
static void mutex_worker(void *arg)
103
0
{
104
0
  mutex_worker_ret = _mutex_worker((struct mw_args *)arg);
105
0
}
106
107
/*
108
 * thread_mutex() - testing uthread mutex operations
109
 *
110
 */
111
static int uthread_mutex(struct unit_test_state *uts)
112
0
{
113
0
  struct uthread_mutex m = UTHREAD_MUTEX_INITIALIZER;
114
0
  struct mw_args args = { .uts = uts, .m = &m, .flag = 0 };
115
0
  int id;
116
0
  int i;
117
118
0
  id = uthread_grp_new_id();
119
0
  ut_assert(id != 0);
120
  /* Take the mutex */
121
0
  ut_assertok(uthread_mutex_lock(&m));
122
  /* Start a thread */
123
0
  ut_assertok(uthread_create(NULL, mutex_worker, (void *)&args, 0,
124
0
           id));
125
  /* Let the thread run for a bit */
126
0
  for (i = 0; i < 100; i++)
127
0
    ut_assert(uthread_schedule());
128
  /* Thread should not have set the flag due to the mutex */
129
0
  ut_asserteq(0, args.flag);
130
  /* Release the mutex */
131
0
  ut_assertok(uthread_mutex_unlock(&m));
132
  /* Schedule the thread until it is done */
133
0
  while (uthread_schedule())
134
0
    ;
135
  /* Now the flag should be set */
136
0
  ut_asserteq(1, args.flag);
137
  /* And the mutex should be available */
138
0
  ut_assertok(uthread_mutex_trylock(&m));
139
0
  ut_assertok(uthread_mutex_unlock(&m));
140
141
  /* Of course no error are expected from the thread routine */
142
0
  ut_assertok(mutex_worker_ret);
143
144
0
  return 0;
145
0
}
146
LIB_TEST(uthread_mutex, 0);