* mikeOS 16 bit and amd64 baremetal
[mascara-docs.git] / amd64 / bareMetalOS-0.5.2 / baremetal0.5.2 / programs / primesmp.c
blob7b12b4f2158c872f752f7d5856503646ed188fdd
1 // Prime SMP Test Program (v1.2, September 7 2010)
2 // Written by Ian Seyler
3 //
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.
7 //
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
17 // strip primesmp
19 // maxn = 500000 primes = 41538
20 // maxn = 1000000 primes = 78498
21 // maxn = 5000000 primes = 348513
22 // maxn = 10000000 primes = 664579
25 #ifdef BAREMETAL
26 #include "libBareMetal.h"
27 #endif
29 #ifdef LINUX
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <pthread.h>
33 #include <time.h>
34 #endif
36 void prime_process();
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];
41 #ifdef LINUX
42 pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
43 #endif
46 int main()
48 unsigned long k;
50 process_stage = processes;
52 #ifdef BAREMETAL
53 unsigned long start, finish;
54 start = b_get_timercounter(); // Grab the starting time
55 #endif
57 #ifdef LINUX
58 time_t start, finish;
59 time(&start); // Grab the starting time
60 pthread_t worker[processes];
61 #endif
63 // Spawn the worker processes
64 for (k=0; k<processes; k++)
66 #ifdef BAREMETAL
67 b_smp_enqueue(&prime_process);
68 #endif
70 #ifdef LINUX
71 pthread_create(&worker[k], NULL, prime_process, NULL);
72 #endif
75 #ifdef BAREMETAL
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
86 #endif
88 #ifdef LINUX
89 for (k=0; k<processes; k++)
91 pthread_join(worker[k], NULL);
93 #endif
95 // Print the results
96 #ifdef BAREMETAL
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");
105 #endif
107 #ifdef LINUX
108 time(&finish);
109 printf("%u in %.0lf seconds\n", primes, difftime(finish, start));
110 #endif
112 return 0;
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...
122 // And so on.
124 void prime_process()
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.
129 #ifdef BAREMETAL
130 b_smp_lock(lock);
131 #endif
132 #ifdef LINUX
133 pthread_mutex_lock( &mutex1 );
134 #endif
136 i = (process_stage * 2) + 1;
137 process_stage--;
139 #ifdef BAREMETAL
140 b_smp_unlock(lock);
141 #endif
142 #ifdef LINUX
143 pthread_mutex_unlock( &mutex1 );
144 #endif
146 h = processes * 2;
148 // Process
149 for(; i<=maxn; i+=h)
151 for(j=2; j<=i-1; j++)
153 if(i%j==0) break; // Number is divisible by some other number. So break out
155 if(i==j)
157 tprimes = tprimes + 1;
159 } // Continue loop up to max number
161 // Add tprimes to primes.
162 #ifdef BAREMETAL
163 b_smp_lock(lock);
164 #endif
165 #ifdef LINUX
166 pthread_mutex_lock( &mutex1 );
167 #endif
168 primes = primes + tprimes;
170 #ifdef BAREMETAL
171 b_smp_unlock(lock);
172 #endif
173 #ifdef LINUX
174 pthread_mutex_unlock( &mutex1 );
175 #endif
178 // EOF