changeset 4:e512fcf3748e

Initial add
author Me@portablequad
date Sat, 22 Oct 2011 19:27:29 -0700
parents 80a90f221047
children 535c119ba090
files src/Application/main.c
diffstat 1 files changed, 256 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/Application/main.c	Sat Oct 22 19:27:29 2011 -0700
     1.3 @@ -0,0 +1,256 @@
     1.4 +/* 
     1.5 + * 
     1.6 + */
     1.7 +#include <stdio.h>
     1.8 +#include <stdlib.h>
     1.9 +#include <string.h>
    1.10 +#include <math.h>
    1.11 +#include <ctype.h>
    1.12 +#include <errno.h>
    1.13 +#include <pthread.h>
    1.14 +#include "VPThread_lib/VPThread.h"
    1.15 +#include "VPThread_lib/VMS/Queue_impl/PrivateQueue.h"
    1.16 +
    1.17 +#undef DEBUG
    1.18 +//#define DEBUG
    1.19 +
    1.20 +#if !defined(unix) && !defined(__unix__)
    1.21 +#ifdef __MACH__
    1.22 +#define unix		1
    1.23 +#define __unix__	1
    1.24 +#endif	/* __MACH__ */
    1.25 +#endif	/* unix */
    1.26 +
    1.27 +/* find the appropriate way to define explicitly sized types */
    1.28 +/* for C99 or GNU libc (also mach's libc) we can use stdint.h */
    1.29 +#if (__STDC_VERSION__ >= 199900) || defined(__GLIBC__) || defined(__MACH__)
    1.30 +#include <stdint.h>
    1.31 +#elif defined(unix) || defined(__unix__)	/* some UNIX systems have them in sys/types.h */
    1.32 +#include <sys/types.h>
    1.33 +#elif defined(__WIN32__) || defined(WIN32)	/* the nameless one */
    1.34 +typedef unsigned __int8 uint8_t;
    1.35 +typedef unsigned __int32 uint32_t;
    1.36 +#endif	/* sized type detection */
    1.37 +
    1.38 +/* provide a millisecond-resolution timer for each system */
    1.39 +#if defined(unix) || defined(__unix__)
    1.40 +#include <time.h>
    1.41 +#include <sys/time.h>
    1.42 +unsigned long get_msec(void) {
    1.43 +	static struct timeval timeval, first_timeval;
    1.44 +
    1.45 +	gettimeofday(&timeval, 0);
    1.46 +	if(first_timeval.tv_sec == 0) {
    1.47 +		first_timeval = timeval;
    1.48 +		return 0;
    1.49 +	}
    1.50 +	return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000;
    1.51 +}
    1.52 +#elif defined(__WIN32__) || defined(WIN32)
    1.53 +#include <windows.h>
    1.54 +unsigned long get_msec(void) {
    1.55 +	return GetTickCount();
    1.56 +}
    1.57 +#else
    1.58 +//#error "I don't know how to measure time on your platform"
    1.59 +#endif
    1.60 +
    1.61 +//======================== Defines =========================
    1.62 +
    1.63 +const char *usage = {
    1.64 +	"Usage: malloc_test [options]\n"
    1.65 +	"  Spwans a number of threads and allocates memory.\n\n"
    1.66 +	"Options:\n"
    1.67 +	"  -t <num>   how many threads to use (default: 1)\n"
    1.68 +	"  -m <num>   repeat workload and sync operation <m> times\n"
    1.69 +        "  -n <num>   size of workload, repeat <n> times\n"     
    1.70 +	"  -h         this help screen\n\n"
    1.71 +};
    1.72 +
    1.73 +struct barrier_t
    1.74 +{
    1.75 +    int counter;
    1.76 +    int nthreads;
    1.77 +    int32 mutex;
    1.78 +    int32 cond;
    1.79 +};
    1.80 +typedef struct barrier_t barrier;
    1.81 +
    1.82 +void inline barrier_init(barrier *barr, int nthreads, VirtProcr *animatingPr)
    1.83 + {
    1.84 +   barr->counter = 0;
    1.85 +   barr->nthreads = nthreads;
    1.86 +   barr->mutex   = VPThread__make_mutex(animatingPr);
    1.87 +   barr->cond    = VPThread__make_cond(barr->mutex, animatingPr);
    1.88 + }
    1.89 +
    1.90 +void inline barrier_wait(barrier *barr, VirtProcr *animatingPr)
    1.91 + { int i;
    1.92 +
    1.93 +   VPThread__mutex_lock(barr->mutex, animatingPr);
    1.94 +   barr->counter++;
    1.95 +   if(barr->counter == barr->nthreads)
    1.96 +    { barr->counter = 0;
    1.97 +      for(i=0; i < barr->nthreads; i++)
    1.98 +         VPThread__cond_signal(barr->cond, animatingPr);
    1.99 +    }
   1.100 +   else
   1.101 +    { VPThread__cond_wait(barr->cond, animatingPr);
   1.102 +    }
   1.103 +   VPThread__mutex_unlock(barr->mutex, animatingPr);
   1.104 + }
   1.105 +
   1.106 +
   1.107 +
   1.108 +union workload{
   1.109 +    uint32 highLow[2];
   1.110 +    uint64 total;
   1.111 +};
   1.112 +
   1.113 +struct input_t{
   1.114 +    struct barrier_t* barrier;
   1.115 +    uint64   workcycles;
   1.116 +};
   1.117 +
   1.118 +
   1.119 +//======================== Globals =========================
   1.120 +char __ProgrammName[] = "overhead_test";
   1.121 +char __DataSet[255];
   1.122 +
   1.123 +int repetitions, workload_size, num_threads;
   1.124 +size_t chunk_size = 0;
   1.125 +
   1.126 +
   1.127 +//======================== App Code =========================
   1.128 +/*
   1.129 + * Workload
   1.130 + */
   1.131 +void work(void* input, VirtProcr* animatingPr)
   1.132 +{
   1.133 +    int n,m;
   1.134 +    struct input_t* in = (struct input_t*)input;
   1.135 +    unsigned int totalCycles = 0;
   1.136 +    unsigned int workspace1;
   1.137 +    double workspace2;
   1.138 +    int32 privateMutex = VPThread__make_mutex(animatingPr);
   1.139 +
   1.140 +    for(m=0; m<repetitions; m++)
   1.141 +    {
   1.142 +        int32 stamp_startWorkload, stamp_endWorkload;
   1.143 +        saveLowTimeStampCountInto( stamp_startWorkload );
   1.144 +        for(n=0; n<workload_size; n++)
   1.145 +        {
   1.146 +            workspace1 += (workspace1 + 32)/2;
   1.147 +            workspace2 += (workspace2 + 23.2)/1.4;
   1.148 +        }
   1.149 +        saveLowTimeStampCountInto( stamp_endWorkload );
   1.150 +        int32 numCycles = stamp_endWorkload-stamp_startWorkload;
   1.151 +        if( numCycles < 100000000 ) totalCycles += numCycles; //sanity check
   1.152 +        
   1.153 +        VPThread__mutex_lock(privateMutex, animatingPr);
   1.154 +        //access queue
   1.155 +        VPThread__mutex_unlock(privateMutex, animatingPr);
   1.156 +    }
   1.157 +    
   1.158 +    in->workcycles = totalCycles;
   1.159 +    barrier_wait(in->barrier,animatingPr);
   1.160 +    //Shutdown worker
   1.161 +    VPThread__dissipate_thread(animatingPr);
   1.162 +    printf("%d", workspace1);
   1.163 +    printf("%f", workspace2);
   1.164 +}
   1.165 +
   1.166 +/* this is run after the VMS is set up*/
   1.167 +void benchmark(void *in, VirtProcr *animatingPr)
   1.168 + {
   1.169 +   int i;
   1.170 +   struct input_t input[num_threads];
   1.171 +   struct barrier_t barr;
   1.172 +   barrier_init(&barr, num_threads+1, animatingPr);
   1.173 +
   1.174 +   for(i=0; i<num_threads; i++)
   1.175 +    { input[i].barrier = &barr;
   1.176 +    }
   1.177 +
   1.178 +   union workload stamp_startThread, stamp_endThread;
   1.179 +   saveTimeStampCountInto(stamp_startThread.highLow[0], stamp_startThread.highLow[1]);
   1.180 +   for(i=0; i<num_threads; i++)
   1.181 +    { VPThread__create_thread((VirtProcrFnPtr)work, (void*)&input[i], animatingPr);
   1.182 +    }
   1.183 +   barrier_wait(&barr, animatingPr);
   1.184 +   saveTimeStampCountInto(stamp_endThread.highLow[0], stamp_endThread.highLow[1]);
   1.185 +
   1.186 +
   1.187 +   for(i=0; i<num_threads; i++)
   1.188 +    { printf("Workcycles: %d\n",input[i].workcycles);
   1.189 +    }
   1.190 +   printf("Total cycles %lu\n", stamp_endThread.total-stamp_startThread.total);
   1.191 +
   1.192 +   //======================================================
   1.193 +
   1.194 +   VPThread__dissipate_thread(animatingPr);
   1.195 + }
   1.196 +
   1.197 +int main(int argc, char **argv)
   1.198 + {
   1.199 +   int i;
   1.200 +
   1.201 +   //set global static variables, based on cmd-line args
   1.202 +   for(i=1; i<argc; i++)
   1.203 +    {
   1.204 +      if(argv[i][0] == '-' && argv[i][2] == 0)
   1.205 +       {
   1.206 +         switch(argv[i][1])
   1.207 +          {
   1.208 +            case 't':
   1.209 +               if(!isdigit(argv[++i][0]))
   1.210 +                {
   1.211 +                  fprintf(stderr, "-t mus be followed by the number of worker threads to spawn\n");
   1.212 +                  return EXIT_FAILURE;
   1.213 +                }
   1.214 +               num_threads = atoi(argv[i]);
   1.215 +               if(!num_threads)
   1.216 +                {
   1.217 +                  fprintf(stderr, "invalid number of threads specified: %d\n", num_threads);
   1.218 +                  return EXIT_FAILURE;
   1.219 +                }
   1.220 +            break;
   1.221 +            case 'n':
   1.222 +               if(!isdigit(argv[++i][0]))
   1.223 +                {
   1.224 +                  fputs("-n must be followed by a number\n", stderr);
   1.225 +                  return EXIT_FAILURE;
   1.226 +                }
   1.227 +               repetitions = atoi(argv[i]);
   1.228 +				break;
   1.229 +            case 'm':
   1.230 +               if(!isdigit(argv[++i][0]))
   1.231 +                {
   1.232 +                  fputs("-m must be followed by a number (workload size)\n", stderr);
   1.233 +                  return EXIT_FAILURE;
   1.234 +                }
   1.235 +               workload_size = atoi(argv[i]);
   1.236 +				break;
   1.237 +            case 'h':
   1.238 +               fputs(usage, stdout);
   1.239 +               return 0;
   1.240 +				
   1.241 +            default:
   1.242 +               fprintf(stderr, "unrecognized argument: %s\n", argv[i]);
   1.243 +               fputs(usage, stderr);
   1.244 +               return EXIT_FAILURE;
   1.245 +          }//switch
   1.246 +       }//if arg
   1.247 +      else
   1.248 +       {
   1.249 +			fprintf(stderr, "unrecognized argument: %s\n", argv[i]);
   1.250 +			fputs(usage, stderr);
   1.251 +			return EXIT_FAILURE;
   1.252 +       }
   1.253 +    }//for
   1.254 +        
   1.255 +        //This is the transition to the VMS runtime
   1.256 +        VPThread__create_seed_procr_and_do_work(benchmark, NULL);
   1.257 +
   1.258 +   return 0;
   1.259 +}