source: mainline/kernel/test/smpcall/smpcall1.c@ d70fc74

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d70fc74 was d70fc74, checked in by Adam Hraska <adam.hraska+hos@…>, 13 years ago

smp_call: Minor fixes and comments.

  • Property mode set to 100644
File size: 3.7 KB
RevLine 
[1f8c11f]1/*
2 */
3
4#include <print.h>
5#include <debug.h>
6
7#include <test.h>
8#include <smp/smp_call.h>
9#include <cpu.h>
10#include <macros.h>
11#include <config.h>
12#include <arch.h>
13
14/*
15 * Maximum total number of smp_calls in the system is:
[d70fc74]16 * 162000 == 9^2 * 1000 * 2
[1f8c11f]17 * == MAX_CPUS^2 * ITERATIONS * EACH_CPU_INC_PER_ITER
18 */
[d70fc74]19#define MAX_CPUS 9
[1f8c11f]20#define ITERATIONS 1000
21#define EACH_CPU_INC_PER_ITER 2
22
23
24static void inc(void *p)
25{
26 ASSERT(interrupts_disabled());
27
28 size_t *pcall_cnt = (size_t*)p;
29 /*
30 * No synchronization. Tests if smp_calls makes changes
31 * visible to the caller.
32 */
33 ++*pcall_cnt;
34}
35
36
37static void test_thread(void *p)
38{
39 size_t *pcall_cnt = (size_t*)p;
40 smp_call_t call_info[MAX_CPUS];
41
[d70fc74]42 unsigned int cpu_count = min(config.cpu_active, MAX_CPUS);
[1f8c11f]43
44 for (int iter = 0; iter < ITERATIONS; ++iter) {
45 /* Synchronous version. */
46 for (unsigned cpu_id = 0; cpu_id < cpu_count; ++cpu_id) {
47 /*
48 * smp_call should make changes by inc() visible on this cpu.
49 * As a result we can pass it our pcall_cnt and not worry
50 * about other synchronization.
51 */
52 smp_call(cpu_id, inc, pcall_cnt);
53 }
54
55 /*
56 * Async calls run in parallel on different cpus, so passing the
57 * same counter would clobber it without additional synchronization.
58 */
59 size_t local_cnt[MAX_CPUS] = {0};
60
61 /* Now start asynchronous calls. */
62 for (unsigned cpu_id = 0; cpu_id < cpu_count; ++cpu_id) {
63 smp_call_async(cpu_id, inc, &local_cnt[cpu_id], &call_info[cpu_id]);
64 }
65
66 /* And wait for all async calls to complete. */
67 for (unsigned cpu_id = 0; cpu_id < cpu_count; ++cpu_id) {
68 smp_call_wait(&call_info[cpu_id]);
69 *pcall_cnt += local_cnt[cpu_id];
70 }
71
72 /* Give other threads a chance to run. */
73 thread_usleep(10000);
74 }
75}
76
[d70fc74]77static size_t calc_exp_calls(size_t thread_cnt)
78{
79 return thread_cnt * ITERATIONS * EACH_CPU_INC_PER_ITER;
80}
[1f8c11f]81
82const char *test_smpcall1(void)
83{
84 /* Number of received calls that were sent by cpu[i]. */
85 size_t call_cnt[MAX_CPUS] = {0};
86 thread_t *thread[MAX_CPUS] = {0};
87
[d70fc74]88 unsigned int cpu_count = min(config.cpu_active, MAX_CPUS);
[1f8c11f]89 size_t running_thread_cnt = 0;
90
91 TPRINTF("Spawning threads on %u cpus.\n", cpu_count);
92
93 /* Create a wired thread on each cpu. */
94 for (unsigned int id = 0; id < cpu_count; ++id) {
95 thread[id] = thread_create(test_thread, &call_cnt[id], TASK,
96 THREAD_FLAG_NONE, "smp-call-test");
97
98 if (thread[id]) {
99 thread_wire(thread[id], &cpus[id]);
100 ++running_thread_cnt;
101 } else {
102 TPRINTF("Failed to create thread on cpu%u.\n", id);
103 }
104 }
105
[d70fc74]106 size_t exp_calls = calc_exp_calls(running_thread_cnt);
107 size_t exp_calls_sum = exp_calls * cpu_count;
108
109 TPRINTF("Running %zu wired threads. Expecting %zu calls. Be patient.\n",
110 running_thread_cnt, exp_calls_sum);
[1f8c11f]111
112 for (unsigned int i = 0; i < cpu_count; ++i) {
113 if (thread[i] != NULL) {
114 thread_ready(thread[i]);
115 }
116 }
117
118 /* Wait for threads to complete. */
119 for (unsigned int i = 0; i < cpu_count; ++i) {
120 if (thread[i] != NULL) {
121 thread_join(thread[i]);
[d70fc74]122 thread_detach(thread[i]);
[1f8c11f]123 }
124 }
125
126 TPRINTF("Threads finished. Checking number of smp_call()s.\n");
127
128 bool ok = true;
129 size_t calls_sum = 0;
130
131 for (size_t i = 0; i < cpu_count; ++i) {
132 if (thread[i] != NULL) {
133 if (call_cnt[i] != exp_calls) {
134 ok = false;
[d70fc74]135 TPRINTF("Error: %zu instead of %zu cpu%u's calls were"
[1f8c11f]136 " acknowledged.\n", call_cnt[i], exp_calls, i);
137 }
138 }
139
140 calls_sum += call_cnt[i];
141 }
142
143 if (calls_sum != exp_calls_sum) {
[d70fc74]144 TPRINTF("Error: total acknowledged sum: %zu instead of %zu.\n",
[1f8c11f]145 calls_sum, exp_calls_sum);
146
147 ok = false;
148 }
149
150 if (ok) {
[d70fc74]151 TPRINTF("Success: number of received smp_calls is as expected (%zu).\n",
[1f8c11f]152 exp_calls_sum);
153 return NULL;
154 } else
155 return "Failed: incorrect acknowledged smp_calls.\n";
156
157}
Note: See TracBrowser for help on using the repository browser.