-
Notifications
You must be signed in to change notification settings - Fork 0
/
Multithreading.html
830 lines (665 loc) · 62.4 KB
/
Multithreading.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
<!--- basic page needs
================================================== -->
<meta charset="utf-8">
<title>Becketron Engine</title>
<meta name="description" content="A simplistic game-engine, currently supporting OpenGL, PhysX, ImGui etc.">
<meta name="author" content="Hamza Khan">
<!-- mobile specific metas
================================================== -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSS
================================================== -->
<link rel="stylesheet" href="css/vendor.css">
<link rel="stylesheet" href="css/styles.css">
<!-- script
================================================== -->
<script src="js/modernizr.js"></script>
<script defer src="js/fontawesome/all.min.js"></script>
<!-- favicons
================================================== -->
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="foxling-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="foxling-16x16.png">
<link rel="manifest" href="site.webmanifest">
</head>
<body id="top">
<!-- preloader
================================================== -->
<div id="preloader">
<div id="loader"></div>
</div>
<!-- header
================================================== -->
<header class="s-header s-header--opaque">
<div class="s-header__logo">
<a class="logo" href="index.html">
<img src="images/logo.svg" alt="Homepage">
</a>
</div>
<div class="row s-header__navigation">
<nav class="s-header__nav-wrap">
<h3 class="s-header__nav-heading h6">Navigate to</h3>
<ul class="s-header__nav">
<li><a href="index.html" title="">Home</a></li>
<li class="has-children">
<a href="#0" title="">Projects</a>
<ul class="sub-menu">
<li><a href="Becketron-1.html">Game Engine</a></li>
<li><a href="React-Nodejs-Proj.html">Social-Media Webapp</a></li>
<li><a href="Robo-tx.html">Robo-tx</a></li>
<li><a href="SMD-Counter.html">SMD Comp-Counter</a></li>
<li><a href="SCPI.html">Oscilloscope CMD Sim</a></li>
<li><a href="Multithreading.html">R-pi Multithreading</a></li>
<li><a href="EVE3.html">EVE3 automation</a></li>
<li><a href="#0">PDDL Game</a></li>
</ul>
</li>
<li class="has-children">
<a href="#0" title="">Blog</a>
<ul class="sub-menu">
<li><a href="Articles/OS_Discussion.html">Discusion on OS</a></li>
</ul>
</li>
<li><a href="#0" title="">Art</a></li>
<li><a href="about.html" title="">About</a></li>
<li><a href="contact.html" title="">Contact</a></li>
</ul> <!-- end s-header__nav -->
<a href="#0" title="Close Menu" class="s-header__overlay-close close-mobile-menu">Close</a>
</nav> <!-- end s-header__nav-wrap -->
</div> <!-- end s-header__navigation -->
<a class="s-header__toggle-menu" href="#0" title="Menu"><span>Menu</span></a>
<div class="s-header__search">
<div class="s-header__search-inner">
<div class="row wide">
<form role="search" method="get" class="s-header__search-form" action="#">
<label>
<span class="h-screen-reader-text">Search for:</span>
<input type="search" class="s-header__search-field" placeholder="Search for..." value=""
name="s" title="Search for:" autocomplete="off">
</label>
<input type="submit" class="s-header__search-submit" value="Search">
</form>
<a href="#0" title="Close Search" class="s-header__overlay-close">Close</a>
</div> <!-- end row -->
</div> <!-- s-header__search-inner -->
</div> <!-- end s-header__search wrap -->
<a class="s-header__search-trigger" href="#">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 17.982 17.983">
<path fill="#010101"
d="M12.622 13.611l-.209.163A7.607 7.607 0 017.7 15.399C3.454 15.399 0 11.945 0 7.7 0 3.454 3.454 0 7.7 0c4.245 0 7.699 3.454 7.699 7.7a7.613 7.613 0 01-1.626 4.714l-.163.209 4.372 4.371-.989.989-4.371-4.372zM7.7 1.399a6.307 6.307 0 00-6.3 6.3A6.307 6.307 0 007.7 14c3.473 0 6.3-2.827 6.3-6.3a6.308 6.308 0 00-6.3-6.301z" />
</svg>
</a>
</header> <!-- end s-header -->
<!-- content
================================================== -->
<section class="s-content">
<div class="row">
<div class="column large-12">
<article class="s-content__entry format-standard">
<div class="s-content__media">
<div class="s-content__post-thumb">
<img src="images/thumbs/Projects/Rpi-Multithreading/Banner.jpg" srcset="images/thumbs/Projects/Rpi-Multithreading/Banner.jpg 2000w,
images/thumbs/Projects/Rpi-Multithreading/Banner_1150w.jpg 1150w,
images/thumbs/Projects/Rpi-Multithreading/Banner_525w.jpg 525w"
sizes="(max-width: 1920px) 100vw, 1920px" alt="">
</div>
</div> <!-- end s-content__media -->
<div class="s-content__entry-header">
<h1 class="s-content__title s-content__title--post">Writing and analysing multi-threaded code on
a Raspberry-pi</h1>
</div> <!-- end s-content__entry-header -->
<div class="s-content__primary">
<div class="s-content__entry-content">
<p>
A C program is created that creates three threads, running for different lengths of
time, and executes two shell scripts (One before and one after the multiple-thread
creation).
<!-- Code block-->
<div class="s-content__page-content">
<!-- HTML generated using hilite.me -->
<div
style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;">
<pre style="margin: 0; line-height: 125%">
<span style="color: #557799">#include <stdio.h></span>
<span style="color: #557799">#include <stdlib.h></span>
<span style="color: #557799">#include <pthread.h></span>
<span style="color: #557799">#include <unistd.h></span>
<span style="color: #557799">#include <sys/types.h></span>
<span style="color: #557799">#include <sys/wait.h></span>
<span style="color: #557799">#include <sys/time.h></span>
<span style="color: #557799">#include <time.h></span>
<span style="color: #888888">// **NOTE** fprintf is used to print the messages to terminal and 'standard error</span>
<span style="color: #888888">// stream' is used instead 'standard output', this methods prints the messages </span>
<span style="color: #888888">// in the right sequence instead of buffering them to the end</span>
<span style="color: #333399; font-weight: bold">void</span><span style="color: #333333">*</span> <span style="color: #0066BB; font-weight: bold">Thread_1</span>(<span style="color: #333399; font-weight: bold">void</span><span style="color: #333333">*</span> arg) <span style="color: #888888">// Function for thread 1 </span>
{
<span style="color: #008800; font-weight: bold">struct</span> timeval t0, t1, time_diff; <span style="color: #888888">// Used for testing the </span>
gettimeofday(<span style="color: #333333">&</span>t0,<span style="color: #007020">NULL</span>); <span style="color: #888888">// actual time taken by the thread </span>
fprintf(stderr,<span style="background-color: #fff0f0">"Entered the first thread</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">"</span>);
sleep(<span style="color: #0000DD; font-weight: bold">1</span>); <span style="color: #888888">// sleep for 1 second</span>
gettimeofday(<span style="color: #333333">&</span>t1,<span style="color: #007020">NULL</span>); <span style="color: #888888">// time after </span>
timersub(<span style="color: #333333">&</span>t1,<span style="color: #333333">&</span>t0,<span style="color: #333333">&</span>time_diff); <span style="color: #888888">// store the difference in before and after time</span>
fprintf(stderr,<span style="background-color: #fff0f0">"</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">Left the first thread</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">"</span>);
fprintf(stderr,<span style="background-color: #fff0f0">"doSomething (thread %ld) took %d.%06d sec</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">"</span>,(<span style="color: #333399; font-weight: bold">long</span>)pthread_self()
,time_diff.tv_sec,time_diff.tv_usec); <span style="color: #888888">// print time taken with the accuracy</span>
<span style="color: #888888">// of microseconds </span>
pthread_exit(<span style="color: #0000DD; font-weight: bold">0</span>); <span style="color: #888888">// exit the thread</span>
}
<span style="color: #333399; font-weight: bold">void</span><span style="color: #333333">*</span> <span style="color: #0066BB; font-weight: bold">Thread_2</span>(<span style="color: #333399; font-weight: bold">void</span><span style="color: #333333">*</span> arg) <span style="color: #888888">// Function for thread 2 </span>
{
fprintf(stderr,<span style="background-color: #fff0f0">"Entered the second thread</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">"</span>);
sleep(<span style="color: #0000DD; font-weight: bold">7</span>); <span style="color: #888888">// sleep for seven seconds</span>
fprintf(stderr,<span style="background-color: #fff0f0">"</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">Left the second thread</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">"</span>);
pthread_exit(<span style="color: #0000DD; font-weight: bold">0</span>); <span style="color: #888888">// exit the thread</span>
}
<span style="color: #333399; font-weight: bold">void</span><span style="color: #333333">*</span> <span style="color: #0066BB; font-weight: bold">Thread_3</span>(<span style="color: #333399; font-weight: bold">void</span><span style="color: #333333">*</span> arg) <span style="color: #888888">// Function for thread 3</span>
{
fprintf(stderr,<span style="background-color: #fff0f0">"Entered the third thread</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">"</span>);
sleep(<span style="color: #0000DD; font-weight: bold">5</span>); <span style="color: #888888">// sleep for five seconds</span>
fprintf(stderr,<span style="background-color: #fff0f0">"</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">Left the third thread</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">"</span>);
pthread_exit(<span style="color: #0000DD; font-weight: bold">0</span>);<span style="color: #888888">// exit thread</span>
}
<span style="color: #333399; font-weight: bold">int</span> <span style="color: #0066BB; font-weight: bold">main</span>()
{
<span style="color: #333399; font-weight: bold">pid_t</span> pid; <span style="color: #888888">// declare a variable 'pid' of type pid_t</span>
pid <span style="color: #333333">=</span>fork();<span style="color: #888888">// fork a child and parent process and assign the return value to 'pid' </span>
<span style="color: #008800; font-weight: bold">if</span>(pid<span style="color: #333333">==</span><span style="color: #0000DD; font-weight: bold">0</span>) <span style="color: #888888">// if inside child process (fork's return value zero means in child process)</span>
{
<span style="color: #333399; font-weight: bold">char</span> <span style="color: #333333">*</span> path1<span style="color: #333333">=</span><span style="background-color: #fff0f0">"./first.sh"</span>; <span style="color: #888888">// path for the first shell script</span>
<span style="color: #333399; font-weight: bold">char</span> <span style="color: #333333">*</span> arg1[]<span style="color: #333333">=</span>{<span style="background-color: #fff0f0">"./first"</span>,<span style="color: #007020">NULL</span>}; <span style="color: #888888">// default argument needed by 'execvp' function</span>
execvp(path1,arg1); <span style="color: #888888">// executes the 'first.sh' shell script</span>
}
<span style="color: #008800; font-weight: bold">else</span> <span style="color: #008800; font-weight: bold">if</span>(pid <span style="color: #333333">></span> <span style="color: #0000DD; font-weight: bold">0</span>) <span style="color: #888888">// If Inside the parent process</span>
{
<span style="color: #888888">//Thread ID</span>
<span style="color: #333399; font-weight: bold">pthread_t</span> tid1; <span style="color: #888888">// declare a variable 'tid1' of type pthread_t</span>
<span style="color: #333399; font-weight: bold">pthread_t</span> tid2; <span style="color: #888888">// declare a variable 'tid2' of type pthread_t</span>
<span style="color: #333399; font-weight: bold">pthread_t</span> tid3; <span style="color: #888888">// declare a variable 'tid3' of type pthread_t</span>
<span style="color: #888888">//Create the threads</span>
pthread_create(<span style="color: #333333">&</span>tid1,<span style="color: #007020">NULL</span>,<span style="color: #333333">&</span>Thread_1,<span style="color: #007020">NULL</span>);<span style="color: #888888">//initalize tid1 and run Thread_1 function </span>
pthread_create(<span style="color: #333333">&</span>tid2,<span style="color: #007020">NULL</span>,<span style="color: #333333">&</span>Thread_2,<span style="color: #007020">NULL</span>);<span style="color: #888888">//initalize tid1 and run Thread_1 function </span>
pthread_create(<span style="color: #333333">&</span>tid3,<span style="color: #007020">NULL</span>,<span style="color: #333333">&</span>Thread_3,<span style="color: #007020">NULL</span>);<span style="color: #888888">//initalize tid1 and run Thread_1 function </span>
<span style="color: #888888">//wait until the thread has done its work</span>
pthread_join(tid1,<span style="color: #007020">NULL</span>); <span style="color: #888888">// wait for thread with thread ID tid1, no return value needed</span>
pthread_join(tid2,<span style="color: #007020">NULL</span>); <span style="color: #888888">// wait for thread with thread ID tid1, no return value needed</span>
pthread_join(tid3,<span style="color: #007020">NULL</span>); <span style="color: #888888">// wait for thread with thread ID tid1, no return value needed</span>
<span style="color: #888888">//sleep(10);</span>
wait(<span style="color: #007020">NULL</span>); <span style="color: #888888">// Wait for the child process to finish (If it hasn't)</span>
}
<span style="color: #008800; font-weight: bold">else</span> <span style="color: #008800; font-weight: bold">if</span>(pid <span style="color: #333333"><</span> <span style="color: #0000DD; font-weight: bold">0</span>) <span style="color: #888888">// If there was an error in forking</span>
{
perror(<span style="background-color: #fff0f0">"Fork failed"</span>); <span style="color: #888888">//Print an error messsage</span>
exit(<span style="color: #0000DD; font-weight: bold">1</span>); <span style="color: #888888">// exit with return value 1 </span>
}
pid<span style="color: #333333">=</span>fork(); <span style="color: #888888">// Create another child process and parent process </span>
<span style="color: #008800; font-weight: bold">if</span>(pid <span style="color: #333333">==</span> <span style="color: #0000DD; font-weight: bold">0</span>) <span style="color: #888888">// If in child process </span>
{
<span style="color: #333399; font-weight: bold">char</span> <span style="color: #333333">*</span>path2<span style="color: #333333">=</span><span style="background-color: #fff0f0">"./second.sh"</span>; <span style="color: #888888">// path to second shell script</span>
<span style="color: #333399; font-weight: bold">char</span> <span style="color: #333333">*</span>arg2[]<span style="color: #333333">=</span>{<span style="background-color: #fff0f0">"./second"</span>,<span style="color: #007020">NULL</span>}; <span style="color: #888888">// default argument needed for execvp</span>
execvp(path2,arg2);<span style="color: #888888">// execute the 'second.sh' shell script </span>
}
<span style="color: #008800; font-weight: bold">else</span> <span style="color: #008800; font-weight: bold">if</span>(pid<span style="color: #333333">></span><span style="color: #0000DD; font-weight: bold">0</span>)
{
wait(<span style="color: #007020">NULL</span>); <span style="color: #888888">// wait for the child process to finish</span>
printf(<span style="background-color: #fff0f0">"</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">Exiting the main loop</span><span style="color: #666666; font-weight: bold; background-color: #fff0f0">\n</span><span style="background-color: #fff0f0">"</span>);
}
}
<span style="color: #888888">//to compile we use = gcc sum_on_t.c -pthread -o some_name </span>
<span style="color: #888888">// we use the c99 format because we declared the variable in the for loop which can't be done in the linux C version</span>
</pre>
</div>
</div>
<!--Codeblock end-->
</p>
<p>
<i>It is to be noted that ‘fprintf’ function is used to identify the printing
stream to be ‘stderr (standard-error)’ instead of ‘printf’ which uses ‘stdout
(standard-out) as default because in the multithreaded code, the printf function
seems to be stacking up the message to be printed at the end program instead of
the right sequence.</i><br><br>
The three functions Thread_1, Thread_2, Thread_3 essentially do the same thing,
sleeping for 1-sec, 7-sec and 5-sec respectively.The return type of the functions
is a void-pointer as the thread creation function accepts a pointer-to-NULL as the
argument for Function-call. ‘gettimeofday’ function is used in the first thread to
see the time spent in the thread with more accuracy (i.e. micro-secs).
<br><br>
‘Fork’ function is used to spawn the child processes that execute the two shell-scripts.
The threads are created in the parent process.
‘pid’ variable of type pid_t is used to store the return type of ‘Fork()’ to check if
the program-counter is inside the child process or
parent process (the process-id of child process is returned when inside parent).<i>
Using Fork() is important when using exec() function to start another
process, because exec() exits the calling process before executing the specified
file. Therefore the child process’s will become the respective shell
scripts when the exec() function is reached.</i>
If Fork()’s return value is less than zero, means the child process wasn’t created and
an error message is printed, exiting with the a return-value 1.
<br><br>
Variables of type ‘pthread_t’ are declared to reserve the memory space for thread-IDs
which can be pointed to in the thread-creation function. ‘pthread_create()’ function
creates the respective threads taking the thread-ID and the Thread-function as the first
and third arguments respectively.
‘pthread_join()’ function waits for the specified thread to finish executing before
exiting the parent process.
The program is compiled using the ‘GCC’ compiler.
<br><br>
<h3>Top Command</h3>
Two shell scripts are used to run the ‘top’ command at different times to look at
the system information when multithreaded code is run. The figure below shows the Top
command running with ‘H’ attribute (Showing Threads) when the multithreaded
compiled-C-program is running. The multiple-CPU (multi-core) breakdown can be viewed
by pressing 1. This shows that the Kernel makes use of multiple cores when the
Kernel-level-threads created by pthread_create are running.
This configuration of top can be saved by pressing ‘shift+w’.
<img src="C:\Devz\portfolio\Doctor-Foxling.github.io\images\thumbs\Projects\Rpi-Multithreading\top_multi_core.jpg"
style="display: block;width:80%;margin-left: auto; margin-right: auto">
<figcaption>Top command running in a Rasbian (Linux) Terminal</figcaption>
<h3>Shell Scripts</h3>
<div class="s-content__page-content">
<!-- HTML generated using hilite.me -->
<div
style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;">
<pre style="margin: 0; line-height: 125%"><span style="color: #007020">echo</span> <span style="background-color: #fff0f0">"\nEntered the first shell script\n"</span> <span style="color: #888888">#Announce that shell script is executed</span>
top -H -b -n 1 |grep Threads > Threads.txt <span style="color: #888888">#run the top command in |thread mode '-H'|</span>
<span style="color: #888888"># with |batch-mode text '-b'| and |run it once '-n 1'|</span>
<span style="color: #888888"># Grab the line with 'Thread' word in the string </span>
<span style="color: #888888">#the Output is piped to Threads.txt file </span>
top -H -b -n 1 -w 14 |grep top >>Threads.txt <span style="color: #888888">#run the top command in |thread mode '-H'|</span>
<span style="color: #888888"># with |batch-mode text '-b'| and |run it once '-n 1'| with a width of 14 '-w 14'</span>
<span style="color: #888888">#Grab the line with 'top' word in the line of string </span>
<span style="color: #888888">#the Output is piped to Threads.txt file </span>
<span style="color: #007020">echo</span> <span style="background-color: #fff0f0">"This is the data put into the first text file\n"</span>
cat Threads.txt <span style="color: #888888"># Output the contents of the text file</span>
<span style="color: #007020">echo</span> <span style="background-color: #fff0f0">"\n"</span>
<span style="color: #996633">C_prog_pid</span><span style="color: #333333">=</span><span style="background-color: #fff0f0">"$(pidof Thread_runner)"</span> <span style="color: #888888"># Get the process Id of the executable Thread_runner</span>
<span style="color: #007020">echo</span> <span style="background-color: #fff0f0">"$C_prog_pid is the process ID of the running executable\n"</span>
</pre>
</div><br>
<figcaption>First Shell Script</figcaption>
</div>
<!--End of the first shell script-->
The codeblock above shows the shell script executed by the C program when the multiple
threads are running.
It runs one iteration of ‘top’ command twice to grab and store the ‘Thread-row’ and
the ‘top-row’ in a text file called ‘Threads.txt’
The contents of the text-file are then printed on the terminal.
The script also gets the process-ID of the C-program-executable using ‘pidof’ command
and prints it on the terminal.<br><br>
<!-- HTML generated using hilite.me -->
<div class="s-content__page-content">
<div
style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;">
<pre style="margin: 0; line-height: 125%"><span style="color: #007020">echo</span> <span style="background-color: #fff0f0">"\nEntered the second shell script\n"</span>
<span style="color: #007020">echo</span> <span style="background-color: #fff0f0">"This is the data put into the second text file\n"</span>
top -H -b -n 1 |grep Threads > Threads_after.txt <span style="color: #888888">#run the top command in |thread mode '-H'|</span>
<span style="color: #888888"># with |batch-mode text '-b'| and |run it once '-n 1'|</span>
<span style="color: #888888"># Grab the line with 'Thread' word in the string </span>
<span style="color: #888888">#the Output is piped to 'Threads_after.txt' file </span>
top -H -b -n 1 -w 14 |grep top >> Threads_after.txt <span style="color: #888888">#run the top command in |thread mode '-H'|</span>
<span style="color: #888888"># with |batch-mode text '-b'| and |run it once '-n 1'| with a width of 14 '-w 14'</span>
<span style="color: #888888">#Grab the line with 'top' word in the line of string </span>
<span style="color: #888888">#the Output is piped to Threads.txt file </span>
cat Threads_after.txt <span style="color: #888888"># Output the contents of the text file</span>
perl search_th.pl <span style="color: #888888"># Run the perl script to Output the data in a summarized fashion</span>
</pre>
</div><br>
<figcaption>Second Shell Script</figcaption>
</div>
<!--End of the second shell script-->
The second shell script does essentially the same thing as the first shell script
(after the threads have finished executing) but it also executes the ‘Perl-script’
that Outputs the data stored in the text files in a more readable, user-friendly
fashion.
</p>
<h3>Perl Script</h3>
<p>This section looks at the Perl-script used to read the data stored in the text
files and print the data in the terminal, explaining to the non-technical user
the analysis of the multi-threaded code</p>
<div class="s-content__page-content">
<!-- HTML generated using hilite.me -->
<div
style="background: #ffffff; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .8em;padding:.2em .6em;">
<pre style="margin: 0; line-height: 125%"><span style="color: #888888">#!/usr/bin/perl</span>
<span style="color: #008800; font-weight: bold">use</span> strict;
<span style="color: #008800; font-weight: bold">use</span> warnings;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"\n\n THE PERL SCRIPT BEGINS \n\n"</span>; <span style="color: #888888">#Annouce the entry into the perl script</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$Threads_total_before</span>; <span style="color: #888888"># scalar variable for total threads in first text file</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$Threads_total_after</span>; <span style="color: #888888"># scalar variable for total threads in the second text file</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$Threads_running</span>; <span style="color: #888888"># scalar variable for running threads</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$Threads_sleeping</span>; <span style="color: #888888"># scalar variable for running threads</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$start_minute</span>; <span style="color: #888888"># scalar variable for start time's minute part</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$start_second</span>; <span style="color: #888888"># scalar variable for start time's second part</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$end_minute</span>; <span style="color: #888888"># scalar variable for end time's minute part</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$end_second</span>; <span style="color: #888888"># scalar variable for end time's second part </span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">@my_array</span>; <span style="color: #888888">#array variable for storing the words in a row of a file</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">@start_time</span>; <span style="color: #888888">#array variable for storig the hours,minutes and secs of start time</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">@end_time</span>; <span style="color: #888888">#array variable for storing the hours,minutes and secs of end time </span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$row</span>; <span style="color: #888888">#scalar variable for storing the row of a file</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$filename</span> <span style="color: #333333">=</span> <span style="background-color: #fff0f0">'Threads.txt'</span>; <span style="color: #888888"># name of the text file to be read</span>
<span style="color: #007020">open</span>(<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$fh</span>,<span style="background-color: #fff0f0">'<:encoding(UTF-8)'</span>,<span style="color: #996633">$filename</span>) <span style="color: #888888">#Open 'Threads.txt' as a big string '$fh'</span>
<span style="color: #000000; font-weight: bold">or</span> <span style="color: #007020">die</span> <span style="background-color: #fff0f0">"Could not open file '$filename' $!"</span>; <span style="color: #888888"># exit with a message if file can't open</span>
<span style="color: #008800; font-weight: bold">while</span>( <span style="color: #996633">$row</span> <span style="color: #333333">=</span> <span style="color: #000000; background-color: #fff0ff"><$fh></span>) <span style="color: #888888">#run a while loop with range equal to the number of rows in $fh string </span>
{
<span style="color: #007020">chomp</span> <span style="color: #996633">$row</span>; <span style="color: #888888"># Get rid of any empty newlines</span>
<span style="color: #996633">@my_array</span><span style="color: #333333">=</span><span style="color: #007020">split</span>(<span style="background-color: #fff0f0">' '</span>,<span style="color: #996633">$row</span>); <span style="color: #888888">#split the words in the row based on 'spaces' and store them in @my_array </span>
<span style="color: #008800; font-weight: bold">if</span>(<span style="color: #996633">$row</span> <span style="color: #333333">=~</span><span style="color: #000000; background-color: #fff0ff"> /Threads/</span>) <span style="color: #888888"># using regex '=~ //' determine if the word 'Thread' appears in the row</span>
{
<span style="color: #996633">$Threads_total_before</span><span style="color: #333333">=</span><span style="color: #996633">$my_array</span>[<span style="color: #0000DD; font-weight: bold">1</span>]; <span style="color: #888888">#get the second element of @my_array which is total threads</span>
<span style="color: #996633">$Threads_running</span><span style="color: #333333">=</span><span style="color: #996633">$my_array</span>[<span style="color: #0000DD; font-weight: bold">3</span>]; <span style="color: #888888">#get the fourth element of @my_array which is running threads</span>
<span style="color: #996633">$Threads_sleeping</span><span style="color: #333333">=</span><span style="color: #996633">$my_array</span>[<span style="color: #0000DD; font-weight: bold">5</span>];<span style="color: #888888"># get the sixth element of @my_array which is sleeping threads</span>
}
<span style="color: #008800; font-weight: bold">elsif</span>(<span style="color: #996633">$row</span> <span style="color: #333333">=~</span><span style="color: #000000; background-color: #fff0ff"> /top/</span>) <span style="color: #888888"># using regex '=~ //' check if the word 'top' appears in the row</span>
{
<span style="color: #996633">@start_time</span><span style="color: #333333">=</span><span style="color: #007020">split</span>(<span style="background-color: #fff0f0">':'</span>,<span style="color: #996633">$my_array</span>[<span style="color: #0000DD; font-weight: bold">2</span>]); <span style="color: #888888">#split digits in the array based on ':' & store in @start_time </span>
<span style="color: #996633">$start_minute</span><span style="color: #333333">=</span><span style="color: #996633">$start_time</span>[<span style="color: #0000DD; font-weight: bold">1</span>]; <span style="color: #888888"># store the 2nd element of @start_time, which is minutes</span>
<span style="color: #996633">$start_second</span><span style="color: #333333">=</span><span style="color: #996633">$start_time</span>[<span style="color: #0000DD; font-weight: bold">2</span>]; <span style="color: #888888"># store the 2nd element of @start_time, which is minutes</span>
}
}
<span style="color: #888888"># PRINT THE READINGS IN UNDERSTABDABLE TEXT</span>
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"Total number of threads are $Threads_total_before\n"</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"$Threads_running of the $Threads_total_before are running\n"</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"$Threads_sleeping threads are taking a nap\n"</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"Start minute : $start_minute\n"</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"Start second : $start_second\n"</span>;
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$filename2</span> <span style="color: #333333">=</span> <span style="background-color: #fff0f0">'Threads_after.txt'</span>; <span style="color: #888888"># name of the second file to be read</span>
<span style="color: #007020">open</span>(<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$fh2</span>,<span style="background-color: #fff0f0">'<:encoding(UTF-8)'</span>,<span style="color: #996633">$filename2</span>) <span style="color: #888888">#Open 'Threads_after.txt' as a big string '$fh2' </span>
<span style="color: #000000; font-weight: bold">or</span> <span style="color: #007020">die</span> <span style="background-color: #fff0f0">"Could not open file '$filename' $!"</span>; <span style="color: #888888"># exit with a message if file can't open</span>
<span style="color: #008800; font-weight: bold">while</span>( <span style="color: #996633">$row</span> <span style="color: #333333">=</span> <span style="color: #000000; background-color: #fff0ff"><$fh2></span>) <span style="color: #888888"># run a while loop with range equal to the number of rows in $fh2 string</span>
{
<span style="color: #007020">chomp</span> <span style="color: #996633">$row</span>; <span style="color: #888888"># Get rid of empty newlines</span>
<span style="color: #996633">@my_array</span><span style="color: #333333">=</span><span style="color: #007020">split</span>(<span style="background-color: #fff0f0">' '</span>,<span style="color: #996633">$row</span>); <span style="color: #888888">#split the words in the row based on 'spaces' and store them in @my_array</span>
<span style="color: #008800; font-weight: bold">if</span>(<span style="color: #996633">$row</span> <span style="color: #333333">=~</span><span style="color: #000000; background-color: #fff0ff"> /Threads/</span>) <span style="color: #888888"># using regex '=~ //' check if the word 'Thread' appears in the row</span>
{
<span style="color: #996633">$Threads_total_after</span><span style="color: #333333">=</span><span style="color: #996633">$my_array</span>[<span style="color: #0000DD; font-weight: bold">1</span>];<span style="color: #888888">#get the second element of @my_array which is total threads </span>
<span style="color: #996633">$Threads_running</span><span style="color: #333333">=</span><span style="color: #996633">$my_array</span>[<span style="color: #0000DD; font-weight: bold">3</span>];<span style="color: #888888">#get the fourth element of @my_array which is runnning threads</span>
<span style="color: #996633">$Threads_sleeping</span><span style="color: #333333">=</span><span style="color: #996633">$my_array</span>[<span style="color: #0000DD; font-weight: bold">5</span>];<span style="color: #888888">#get the sixth element of @my_array which is sleeping threads</span>
}
<span style="color: #008800; font-weight: bold">elsif</span>(<span style="color: #996633">$row</span> <span style="color: #333333">=~</span><span style="color: #000000; background-color: #fff0ff"> /top/</span>) <span style="color: #888888"># using regex '=~ //' check if the word 'Top' appears in the row</span>
{
<span style="color: #996633">@end_time</span><span style="color: #333333">=</span><span style="color: #007020">split</span>(<span style="background-color: #fff0f0">':'</span>,<span style="color: #996633">$my_array</span>[<span style="color: #0000DD; font-weight: bold">2</span>]); <span style="color: #888888">#split the words in the @my_array[2] based on ':' </span>
<span style="color: #996633">$end_minute</span><span style="color: #333333">=</span><span style="color: #996633">$end_time</span>[<span style="color: #0000DD; font-weight: bold">1</span>]; <span style="color: #888888"># get the second element of end-time, which is minutes</span>
<span style="color: #996633">$end_second</span><span style="color: #333333">=</span><span style="color: #996633">$end_time</span>[<span style="color: #0000DD; font-weight: bold">2</span>]; <span style="color: #888888"># get the third element of end-time, which is seconds</span>
}
}
<span style="color: #888888"># PRINT THE DATA IN UNDERSTANDABLE TEXT</span>
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"\nTotal number of threads are $Threads_total_after\n"</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"$Threads_running of the $Threads_total_after are running\n"</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"$Threads_sleeping threads are taking a nap\n"</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"End minute : $end_minute\n"</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"End second : $end_second\n"</span>;
<span style="color: #888888"># Get the number of threads spawned by comparing the total threads from both the text file</span>
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$number_of_threads</span> <span style="color: #333333">=</span> <span style="color: #996633">$Threads_total_before</span> <span style="color: #333333">-</span> <span style="color: #996633">$Threads_total_after</span>;
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"\n$number_of_threads threads were created by the executable\n"</span>;
<span style="color: #888888">#Get the time taken for all threads to finish executing by comparing time from both text files</span>
<span style="color: #008800; font-weight: bold">if</span>(<span style="color: #996633">$end_minute</span> <span style="color: #333333">==</span> <span style="color: #996633">$start_minute</span>) <span style="color: #888888"># If less than a minute was spent</span>
{
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$diff</span> <span style="color: #333333">=</span> <span style="color: #996633">$end_second</span> <span style="color: #333333">-</span> <span style="color: #996633">$start_second</span>; <span style="color: #888888"># get the time difference</span>
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"\n$diff seconds were taken to complete all "</span>,
<span style="background-color: #fff0f0">"the threads spawned by the executable\n"</span>;
}
<span style="color: #008800; font-weight: bold">else</span> <span style="color: #888888"># if more than a minute was taken</span>
{
<span style="color: #008800; font-weight: bold">my</span> <span style="color: #996633">$diff</span> <span style="color: #333333">=</span> ((<span style="color: #996633">$end_minute</span> <span style="color: #333333">-</span> <span style="color: #996633">$start_minute</span>) <span style="color: #333333">*</span> <span style="color: #0000DD; font-weight: bold">60</span> ) <span style="color: #333333">+</span>
(<span style="color: #996633">$end_second</span> <span style="color: #333333">-</span> <span style="color: #996633">$start_second</span>); <span style="color: #888888"># Get the time difference</span>
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">"\n$diff seconds were taken to complete all "</span>,
<span style="background-color: #fff0f0">"the threads spawned by the executable\n"</span>;
}
<span style="color: #008800; font-weight: bold">print</span> <span style="background-color: #fff0f0">" \n\n PERL SCRIPT ENDS \n\n"</span> <span style="color: #888888"># Announce the exit from perl script</span>
</pre>
</div><br>
<figcaption> Perl Script for parsing the stored data</figcaption>
</div>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~ Perl Script End ~~~~~~~~~~~~~~~~~~~~-->
The line <code> #!/usr/bin/perl</code> tells the system where the compiler resides, when the
script is run using ‘Perl’ command. The ‘strict’ pragma sets certain rules for the
programmer that helps writing the correct format of code. For example, unlike most
programming languages, Perl doesn’t have a main-loop. The ‘strict’ pragma therefore forces
the programmer to declare all variable in a lexical scope. So, a variable declared in a
block-of-code (e.g. While-loop) cannot be used outside that block-of-code. The ‘warning’
pragma helps that compiler in the detection of errors and potential problems.
<br>
The variables declared at the top of file are declared outside any block of code so they
could be used as global-variables in any block of code.
<br><br>
The <code>open</code> function opens ‘Threads.txt’ file with UTF-8 encoding (UTF-8’s wide
range of language support makes it ideal).
Getting rid of any empty newline, using <code>chomp()</code> function in the while loop, the
loop reads through the 2 rows in ‘Threads.txt’. The words in each row are split based on
‘space’ and stored in an array-variable.
In the first row, the second, fourth and sixth element are used to store the total, running
and sleeping threads respectively. In the second row, second element of the array, which is
the start time is split based on the symbol ‘:’ and stored in another array. The second
third element of the ‘start_time’ array are used to store the minute part and second part of
the start time.
<br><br>
Next, similar steps are followed for opening and reading the second text file. The second
text file holds identical information with different values for that variables of interest.
The reading and data separation process for the second text file is therefore same as the
first text file.
<pre>
<code class="language-perl"> #Get the time taken for all threads to finish executing by comparing time from both text files
if($end_minute == $start_minute) # If less than a minute was spent
{
my $diff = $end_second - $start_second; # get the time difference
print "\n$diff seconds were taken to complete all ",
"the threads spawned by the executable\n";
}
</code></pre>
<figcaption>If less than a minute was spent</figcaption>
<pre>
<code class="language-perl">
else # if more than a minute was taken
{
my $diff = (($end_minute - $start_minute) * 60 ) +
($end_second - $start_second); # Get the time difference
print "\n$diff seconds were taken to complete all ",
"the threads spawned by the executable\n";
}
</code></pre>
<figcaption>If more than a minute was spent</figcaption>
The sections above compares the data from the two text files.
It checks the Total number of threads while the Multithreaded program is running and
after it has finished Executing.
It also looks at the difference between the Multithreaded-Program start time and end
time. To see the total time taken by the whole process
<h3>Running the executable</h3>
<p>
Finally to run the multithreaded-code and get back the background analysis,
the compiled executable of ‘Thread_runner.c’ which is ‘Thread_runner’ is executed
in the Terminal by typing: “ ./Thread_runner “
This will give the following output:
<img
src="C:\Devz\portfolio\Doctor-Foxling.github.io\images\thumbs\Projects\Rpi-Multithreading\Final_Output.png">
It can be seen that the total time taken to run the multi-threaded program is 7 seconds.
The three threads in the program run for 1 second, 7 second and 5 second respectively,
which totals to 13 seconds. In a single-threaded program, the program would take 13
seconds to run the three functions sequentially, however in this case, the program
makes use of the four cores in the Raspberry-pi processor to run each thread on
separate cores. Hence only 7 seconds, which is total time taken by the second thread
(i.e. The longest running thread), are used to reach the end of the executable.
</p>
<blockquote>
<p>
"I consider that the golden rule requires that if I like a program I must share it
with other people who like it."
</p>
<cite>Richard Stallman</cite>
</blockquote>
<h3>Importance of Multithreading</h3>
<p>
We have now reached the stage when CPU clock speeds are no longer increasing, or,
have slowed down drastically compared to the exponential rise in the last five
decades. <br><br>
More’s Law, that states that the number of transistors in a dense integrated circuit,
doubles every year, is no longer applicable to the current trend. This is due to
various factors including the reached limit of ‘Dennard scaling’ (that states that
the power needing to run transistors in a unit volume stays constant.) meaning that
with increasing transistors more power would be needed. The shrinking size of the
transistors also makes their accuracy more susceptible to thermal losses which
would also be increasing with increasing power supply. <br><br>
Even with more efficient cooling methods available in the future, the reduction in
transistor size has also nearly reached its limit. The current size of 10-20
nano-meters can be further reduced to 5-7 nano-meters but beyond that quantum
effects would prevent the transistor from working properly.
It is clear that increase in CPU clock speed is not the way forward but rather
it is the increase in the number of CPU that would compensate for the need of
more computing power needed for the more sophisticated future applications. <br><br>
Already, processor companies have designed and manufactured CPU’s with over hundred
cores but it is the software industry that is now lagging behind. To utilize
multiple cores in a system, the software must be written in a multi-threaded
fashion that makes use of the available cores. Writing multithreaded code,
however, has proven very difficult with the need to keep track of multiple
threads that share the same memory have access and can make changes to the
same variable. Though this makes the context-switching a lot less expensive
between the threads, it also makes the program a lot less predictable and
debugging such programs can get very hard. <br><br>
All in all, despite the lack of elegant multi-threading software solutions at the
moment, Multi-threading is nevertheless the future of software programming and
extra emphasis must be given to it in learning stages of programmers. <br><br>
</p>
</div> <!-- end s-entry__entry-content -->
<div class="s-content__entry-meta">
<div class="entry-author meta-blk">
<div class="author-avatar">
<img class="avatar" src="images/avatars/My_Avatar.png" alt="">
</div>
<div class="byline">
<span class="bytext">Posted By</span>
<a href="#0">Hamza Khan</a>
</div>
</div>
<div class="meta-bottom">
<div class="entry-cat-links meta-blk">
<div class="cat-links">
<span>In</span>
<a href="https://en.wikipedia.org/wiki/Computer_programming">Programming</a>
<a
href="https://en.wikipedia.org/wiki/Software_design#:~:text=Software%20design%20is%20the%20process,components%20and%20subject%20to%20constraints.&text=%5Bin%5D%20a%20stylized%20software%20engineering,and%20planning%20a%20software%20solution.">Design</a>
<a href="https://en.wikipedia.org/wiki/Game_engine">Multithreading</a>
</div>
<span>On</span>
June 5, 2021
</div>
<div class="entry-tags meta-blk">
<span class="tagtext">Tags</span>
<a href="#">Multithreading</a>
<a href="#">Raspberry-pi</a>
<a href="#">C</a>
<a href="#">Perl</a>
<a href="#">Bash</a>
</div>
</div>
</div> <!-- s-content__entry-meta -->
<div class="s-content__pagenav">
<div class="prev-nav">
<a href="#" rel="prev">
<span>Previous</span>
Home
</a>
</div>
<div class="next-nav">
<a href="Articles/OS_Discussion.html" rel="next">
<span>Next</span>
Discussion on OS's
</a>
</div>
</div> <!-- end s-content__pagenav -->
</div> <!-- end s-content__primary -->
</article> <!-- end entry -->
</div> <!-- end column -->
</div> <!-- end row -->
<div class="row">
<div class="column large-">
<nav class="pgn">
<ul>
<li><a class="pgn__num current" href="Multithreading.html">1</a></li>
<li><a class="pgn__num" href="Articles/OS_Discussion.html">2</a></li>
<li>
<a class="pgn__next" href="Articles/OS_Discussion.html">
Next
</a>
</li>
</ul>
<span class="pgn__next__desc">(Discussion on OS's)</span>
</nav> <!-- end pgn -->
</div> <!-- end column -->
</div> <!-- end row -->
</section> <!-- end s-content -->
<!-- footer
================================================== -->
<footer class="s-footer">
<div class="s-footer__main">
<div class="row">
<div class="column large-3 medium-6 tab-12 s-footer__info">
<h5>About My Site</h5>
<p>
The Website is a portfolio, showcasing some of the projects I have worked
on, both, as part of my academic career as well as part of my hobby. The Website
also provides documentation for some of the projects as well as some of my work
as an artist.
</p>
</div> <!-- end s-footer__info -->
<div class="column large-2 medium-3 tab-6 s-footer__site-links">
<h5>Site Links</h5>
<ul>
<li><a href="#0">About Me</a></li>
<li><a href="#0">Blog</a></li>
<li><a href="#0">FAQ</a></li>
<li><a href="#0">Terms</a></li>
<li><a href="#0">Privacy Policy</a></li>
</ul>
</div> <!-- end s-footer__site-links -->
<div class="column large-2 medium-3 tab-6 s-footer__social-links">
<h5>Follow Us</h5>
<ul>
<li><a href="https://www.linkedin.com/in/hamza-khan-b49629173/">Linkedin</a></li>
<li><a href="https://github.com/Doctor-Foxling">Github</a></li>
<li><a href="https://www.instagram.com/some_strange_dude/">Instagram</a></li>
<li><a href="https://www.facebook.com/Age.of.Ace/">Facebook</a></li>
<li><a href="https://www.youtube.com/channel/UCmvr4D0tXu9-Zy-PK_5czpw">Youtube</a></li>
</ul>
</div> <!-- end s-footer__social links -->
<div class="column large-3 medium-6 tab-12 s-footer__subscribe">
<h5>Sign Up for Newsletter</h5>
<p>Signup to get updates on articles, interviews and events.</p>
<div class="subscribe-form">
<form id="mc-form" class="group" novalidate="true">
<input type="email" value="" name="dEmail" class="email" id="mc-email"
placeholder="Your Email Address" required="">
<input type="submit" name="subscribe" value="subscribe">
<label for="mc-email" class="subscribe-message"></label>
</form>
</div>
</div> <!-- end s-footer__subscribe -->
</div> <!-- end row -->
</div> <!-- end s-footer__main -->
<div class="s-footer__bottom">
<div class="row">
<div class="column">
<div class="ss-copyright">
<span>© Copyright Calvin 2020</span>
<span>Design by <a href="https://www.styleshout.com/">StyleShout</a></span>
</div> <!-- end ss-copyright -->
</div>
</div>
<div class="ss-go-top">
<a class="smoothscroll" title="Back to Top" href="#top">
<svg viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" width="15" height="15">
<path
d="M7.5 1.5l.354-.354L7.5.793l-.354.353.354.354zm-.354.354l4 4 .708-.708-4-4-.708.708zm0-.708l-4 4 .708.708 4-4-.708-.708zM7 1.5V14h1V1.5H7z"
fill="currentColor"></path>
</svg>
</a>
</div> <!-- end ss-go-top -->
</div> <!-- end s-footer__bottom -->
</footer> <!-- end s-footer -->
<!-- Java Script
================================================== -->
<script src="js/jquery-3.5.0.min.js"></script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
</body>
</html>