1 // Prime SMP Test Program (v1.2, September 7 2010)
2 // Written by Ian Seyler
4 // This program checks all odd numbers between 3 and 'maxn' and determines if they are prime.
5 // On exit the program will display the execution time and how many prime numbers were found.
6 // Useful for testing runtime performance between Linux and BareMetal OS.
8 // BareMetal compile using GCC (Tested with 4.5.0)
9 // gcc -c -m64 -nostdlib -nostartfiles -nodefaultlibs -mno-red-zone -o primesmp.o primesmp.c -DBAREMETAL
10 // gcc -c -m64 -nostdlib -nostartfiles -nodefaultlibs -mno-red-zone -o libBareMetal.o libBareMetal.c
11 // objcopy --remove-section .eh_frame --remove-section .rel.eh_frame --remove-section .rela.eh_frame primesmp.o
12 // objcopy --remove-section .eh_frame --remove-section .rel.eh_frame --remove-section .rela.eh_frame libBareMetal.o
13 // ld -T app.ld -o primesmp.app primesmp.o libBareMetal.o
15 // Linux compile using GCC (Tested with 4.5.0)
16 // gcc -m64 -lpthread -o primesmp primesmp.c -DLINUX
19 // maxn = 500000 primes = 41538
20 // maxn = 1000000 primes = 78498
21 // maxn = 5000000 primes = 348513
22 // maxn = 10000000 primes = 664579
26 #include "libBareMetal.h"
38 // primes is set to 1 since we don't calculate for '2' as it is a known prime number
39 unsigned long maxn
=1000000, primes
=1, local
=0, lock
=0, process_stage
=0, processes
=8;
40 unsigned char tstring
[25];
42 pthread_mutex_t mutex1
= PTHREAD_MUTEX_INITIALIZER
;
50 process_stage
= processes
;
53 unsigned long start
, finish
;
54 start
= b_get_timercounter(); // Grab the starting time
59 time(&start
); // Grab the starting time
60 pthread_t worker
[processes
];
63 // Spawn the worker processes
64 for (k
=0; k
<processes
; k
++)
67 b_smp_enqueue(&prime_process
);
71 pthread_create(&worker
[k
], NULL
, prime_process
, NULL
);
76 // Attempt to run a process on this CPU Core
77 while (b_smp_queuelen() != 0) // Check the length of the queue. If greater than 0 then try to run a queued job.
79 local
= b_smp_dequeue(); // Grab a job from the queue. b_smp_dequeue returns the memory address of the code
80 if (local
!= 0) // If it was set to 0 then the queue was empty
81 b_smp_run(local
); // Run the code
84 // No more jobs in the queue
85 b_smp_wait(); // Wait for all CPU cores to finish
89 for (k
=0; k
<processes
; k
++)
91 pthread_join(worker
[k
], NULL
);
97 finish
= b_get_timercounter();
98 b_int_to_string(primes
, tstring
);
99 b_print_string(tstring
);
100 b_print_string(" in ");
101 finish
= (finish
- start
) / 8;
102 b_int_to_string(finish
, tstring
);
103 b_print_string(tstring
);
104 b_print_string(" seconds\n");
109 printf("%u in %.0lf seconds\n", primes
, difftime(finish
, start
));
116 // prime_process() only works on odd numbers.
117 // The only even prime number is 2. All other even numbers can be divided by 2.
118 // 1 process 1: 3 5 7 ...
119 // 2 processes 1: 3 7 11 ... 2: 5 9 13 ...
120 // 3 processes 1: 3 9 15 ... 2: 5 11 17 ... 3: 7 13 19 ...
121 // 4 processes 1: 3 11 19 ... 2: 5 13 21 ... 3: 7 15 23 ... 4: 9 17 25...
126 register unsigned long h
, i
, j
, tprimes
=0;
128 // Lock process_stage, copy it to local var, subtract 1 from process_stage, unlock it.
133 pthread_mutex_lock( &mutex1
);
136 i
= (process_stage
* 2) + 1;
143 pthread_mutex_unlock( &mutex1
);
151 for(j
=2; j
<=i
-1; j
++)
153 if(i
%j
==0) break; // Number is divisible by some other number. So break out
157 tprimes
= tprimes
+ 1;
159 } // Continue loop up to max number
161 // Add tprimes to primes.
166 pthread_mutex_lock( &mutex1
);
168 primes
= primes
+ tprimes
;
174 pthread_mutex_unlock( &mutex1
);