Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Monte Carlo - Threads exercise
- *
- * Compile with: gcc ./mcarlo.c -o mcarlo -lpthread -lm
- */
- #include <unistd.h>
- #include <time.h>
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <pthread.h>
- #define RETURN_SUCCESS (0)
- #define RETURN_FAILURE (1)
- #define THREAD_SUCCESS (RETURN_SUCCESS)
- #define THREAD_FAILURE (RETURN_FAILURE)
- #define SYSCALL_FAILURE (-1)
- #define PROGRESS (1)
- #define WORKER_COUNT (10)
- #define WITHIN_CIRCLE(x, y) (sqrt(x*x + y*y) < 1)
- #define RANDOM_DOUBLE ((random() / ((double)RAND_MAX + 1)) * 2.0 - 1.0)
- #define PI(a, b) ((double)(4.0 * ((double)b / (double)a)))
- typedef struct s_mcarlo
- {
- unsigned long long p_todo;
- unsigned long long p_count;
- unsigned long long p_within_circle;
- double pi;
- } t_mcarlo;
- typedef struct s_thread
- {
- pthread_t thread_id;
- pthread_attr_t thread_attr;
- unsigned long long points_computed;
- int status;
- } t_thread;
- void *worker(void *arg);
- t_mcarlo mcarlo = {0, 0, 0, 0.0};
- pthread_mutex_t lock;
- int main(int argc, char **argv)
- {
- t_thread threads[WORKER_COUNT];
- unsigned int i = 0;
- unsigned long long point_number = 0;
- /* Checking command line parameters */
- if (argc < 2)
- {
- fprintf(stderr, "[^] USAGE: ./mcarlo <point_number>\n");
- return RETURN_FAILURE;
- }
- /* Converting the char* argv[1] into long long */
- if ((point_number = atoll(argv[1])) < 1)
- {
- fprintf(stderr, "[-] point_number should be >= 1\n");
- return RETURN_FAILURE;
- }
- /* Initializing mutex */
- if (pthread_mutex_init(&lock, NULL) != 0)
- {
- printf("[-] Failed to init mutex !\n");
- return RETURN_FAILURE;
- }
- /* Setting the random seed to the currant time in second */
- srand(time(NULL));
- /* Number of points to compute stored in the working structure */
- mcarlo.p_todo = point_number;
- /* Initializing threads, then, start them */
- printf("[~] Launching %d threads ..\n", WORKER_COUNT);
- for (i = 0 ; i < WORKER_COUNT ; ++i)
- {
- /* By default, the thread succeed */
- threads[i].status = THREAD_SUCCESS;
- /* Setting default thread attr */
- pthread_attr_init(&threads[i].thread_attr);
- /* Starting threads */
- if (pthread_create(&threads[i].thread_id, &threads[i].thread_attr, worker, &mcarlo) != RETURN_SUCCESS)
- {
- fprintf(stderr, "[-] Failed to start thread %d\n", i);
- threads[i].status = THREAD_FAILURE; /* Set the thread creation status to know if we have to join() it */
- }
- }
- /* Waiting for the threads to finish */
- for (i = 0 ; i < WORKER_COUNT ; ++i)
- {
- unsigned long long *p;
- /* Waiting for thread i to finish */
- pthread_join(threads[i].thread_id, (void**)&p);
- if (p != NULL) /* If worker malloc doesn't failed */
- {
- threads[i].points_computed = *p;
- printf("[~] Thread %d computed %llu points\n", i + 1, threads[i].points_computed);
- }
- free(p);
- }
- printf("[+] All Threads finished ! %llu/%llu PI = %f\n", mcarlo.p_within_circle, mcarlo.p_count, PI(mcarlo.p_count, mcarlo.p_within_circle));
- pthread_mutex_destroy(&lock);
- return RETURN_SUCCESS;
- }
- void *worker(void *arg)
- {
- /* Casting the void* pointer to retrieve our t_mcarlo structure */
- t_mcarlo *mcarlo = (t_mcarlo *)arg;
- double x = 0, y = 0;
- unsigned long long *points_computed;
- if ((points_computed = malloc(sizeof(unsigned long long) * 1)) == NULL)
- return NULL;
- while (mcarlo->p_count < mcarlo->p_todo)
- {
- /* Creating random values (x, y coordinates) */
- x = RANDOM_DOUBLE;
- y = RANDOM_DOUBLE;
- /* Locking the mutex, accessing shared memory */
- pthread_mutex_lock(&lock);
- /* Increasing number of computed points */
- if (++mcarlo->p_count && WITHIN_CIRCLE(x, y)) /* Check is the coordinates are within the circle */
- ++mcarlo->p_within_circle;
- /* Inc the computed points count to determine how many points a thread has computed */
- ++*points_computed;
- /* Unlocking the mutex, not using shared memory anymore */
- pthread_mutex_unlock(&lock);
- /* Logging some info 10 times if we are in debug/progress mode */
- if (PROGRESS && mcarlo->p_count % (mcarlo->p_todo / 10) == 0)
- printf("Progress: %llu/%llu -> %f\n", mcarlo->p_within_circle, mcarlo->p_count, PI(mcarlo->p_count, mcarlo->p_within_circle));
- }
- /* Exiting at the end of the job */
- //pthread_exit(points_computed);
- return (void *)points_computed;
- }
Add Comment
Please, Sign In to add comment