/***************************************************************************
*
* Copyright 2007 by Sean Conner.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* Comments, questions and criticisms can be sent to: sean@conman.org
*
*************************************************************************/
#include
#include
#include
#include
/*----------------------------------------------
; flags we pass to clone(). This creates what
; is escentially a thread in Linux.
;
; for this program, I don't particularly care
; about portability, just a proof-of-concept.
;
; Sorry Mark.
;---------------------------------------------*/
#define FLAGS (SIGCHLD | CLONE_FS | CLONE_FILES | CLONE_VM)
/*----------------------------------------------
; stacks used for the threads created.
;---------------------------------------------*/
int m_stack0[1024];
int m_stack1[1024];
int m_stack2[1024];
int m_stack3[1024];
/*------------------------------------------
; recursive version (as used in
; http://cgi.cse.unsw.edu.au/~dons/blog/2007/11/29#smoking-4core
; )
;--------------------------------------------*/
unsigned long fib(unsigned long n)
{
if (n == 0) return(0);
if (n == 1) return(1);
return fib(n - 2) + fib(n - 1);
}
/*-------------------------------------
; the created threads run this routine
;-------------------------------------*/
int parfib(void *p)
{
unsigned long *pl = p;
*pl = fib(*pl);
_exit(0);
}
/*---------------------------------------
; Wait for all threads to stop running.
; quick and dirty version
;---------------------------------------*/
void wait_for_kids(void)
{
int status;
pid_t child;
while(1)
{
child = waitpid(-1,&status,__WALL);
if (child == -1)
return;
}
}
int main(int argc,char *argv[])
{
unsigned long p1;
unsigned long p2;
unsigned long p3;
unsigned long p4;
if (argc == 1)
{
fprintf(stderr,"usage: %s 1 | 2 | 4\n",argv[0]);
return(EXIT_FAILURE);
}
switch(argv[1][0])
{
case '1': /* single core, just run straight */
printf("fib(45) = %lu\n",fib(45));
break;
case '2': /* dual core, just two threads */
p1 = 44;
p2 = 43;
clone(parfib,&m_stack0[1023],FLAGS,&p1);
clone(parfib,&m_stack1[1023],FLAGS,&p2);
wait_for_kids();
printf("fib(45) = %lu\n",p1 + p2);
break;
case '4': /* quad-core */
p1 = 43;
p2 = 42;
p3 = 42;
p4 = 41;
clone(parfib,&m_stack0[1023],FLAGS,&p1);
clone(parfib,&m_stack1[1023],FLAGS,&p2);
clone(parfib,&m_stack2[1023],FLAGS,&p3);
clone(parfib,&m_stack3[1023],FLAGS,&p4);
wait_for_kids();
printf("fib(45) = %lu\n",p1 + p2 + p3 + p4);
break;
}
return(EXIT_SUCCESS);
}