diff --git a/src/intrinsic.c b/src/intrinsic.c index 005c783..1c0d623 100644 --- a/src/intrinsic.c +++ b/src/intrinsic.c @@ -9,9 +9,9 @@ int omp_get_num_threads (void) { } int omp_get_thread_num (void) { - //printf("TBI: omp_get_thread_num still doesn't know who I am ... let's say I am 0\n"); - int thread_id = ((miniomp_parallel_t*) (pthread_getspecific(miniomp_specifickey)))->id; - return(thread_id); + miniomp_thread_t *thread = pthread_getspecific(miniomp_specifickey); + unsigned int thread_id = thread->id; + return((int)thread_id); } // No need to implement this function, it is just involked by Extrae at some point diff --git a/src/libminiomp.c b/src/libminiomp.c index 26278d3..368e2d5 100644 --- a/src/libminiomp.c +++ b/src/libminiomp.c @@ -8,6 +8,8 @@ void fini_miniomp(void) __attribute__((destructor)); // Function to parse OMP_NUM_THREADS environment variable void parse_env(void); +pthread_key_t miniomp_specifickey; + void init_miniomp(void) { printf ("mini-omp is being initialized\n"); @@ -15,7 +17,6 @@ init_miniomp(void) { parse_env(); // Initialize Pthread data structures // Initialize Pthread thread-specific data, useful for example to store the OpenMP thread identifier - pthread_key_create(&miniomp_specifickey, NULL); // Initialize OpenMP default lock and default barrier // Initialize OpenMP workdescriptors for for and single // Initialize OpenMP task queue for task and taskloop diff --git a/src/libminiomp.h b/src/libminiomp.h index 60d601c..6ddd77f 100644 --- a/src/libminiomp.h +++ b/src/libminiomp.h @@ -23,3 +23,4 @@ extern pthread_key_t miniomp_specifickey; #include "loop.h" #include "single.h" #include "task.h" + diff --git a/src/parallel.c b/src/parallel.c index 03233a6..e5d8af3 100644 --- a/src/parallel.c +++ b/src/parallel.c @@ -3,47 +3,53 @@ // This file implements the PARALLEL construct // Declaration of array for storing pthread identifier from pthread_create function -pthread_t *miniomp_threads; +miniomp_thread_t *miniomp_threads; // Global variable for parallel descriptor miniomp_parallel_t *miniomp_parallel; +miniomp_single_t *miniomp_single; + // Declaration of per-thread specific key -pthread_key_t miniomp_specifickey; +extern pthread_key_t miniomp_specifickey; + +void miniomp_thread_init(miniomp_thread_t * thread, unsigned int id, void (*fn) (void *), miniomp_parallel_t *region){ + thread->id = id; + thread->region = region; + pthread_create(&(thread->pthread), NULL, fn, thread); +} + // This is the prototype for the Pthreads starting function -void *worker(void *args) { - miniomp_parallel_t *parallel_t = args; - int id = parallel_t->id; - printf("Thread %d initialized\n", id); - void (*fn) (void *) = parallel_t->fn; - void * data = parallel_t->fn_data; - pthread_setspecific(miniomp_specifickey, parallel_t); +void worker(void *args) { + miniomp_thread_t *thread = args; + pthread_setspecific(miniomp_specifickey, thread); + miniomp_parallel_t *parallel = thread->region; + void (*fn) (void *) = parallel->fn; + void * data = parallel->fn_data; fn(data); - // insert all necessary code here for: - // 1) save thread-specific data - // 2) invoke the per-threads instance of function encapsulating the parallel region - // 3) exit the function - return(NULL); } void GOMP_parallel (void (*fn) (void *), void *data, unsigned num_threads, unsigned int flags) { if(!num_threads) num_threads = omp_get_num_threads(); - printf("Starting a parallel region using %d threads\n", num_threads); - miniomp_threads = malloc(num_threads*sizeof(pthread_t)); - miniomp_parallel = malloc(sizeof(miniomp_parallel_t)*num_threads); + miniomp_threads = malloc(num_threads*sizeof(miniomp_thread_t)); + miniomp_parallel = malloc(sizeof(miniomp_parallel_t)); + miniomp_single = malloc(sizeof(miniomp_single_t)); + miniomp_parallel->fn = fn; + miniomp_parallel->fn_data = data; + miniomp_parallel->id = 0; + pthread_barrier_init(&(miniomp_parallel->barrier), NULL, num_threads); + pthread_mutex_init(&(miniomp_parallel->mutex), NULL); + pthread_key_create(&miniomp_specifickey, NULL); for (int i=0; imutex)); + pthread_barrier_destroy(&(miniomp_parallel->barrier)); free(miniomp_threads); free(miniomp_parallel); } diff --git a/src/parallel.h b/src/parallel.h index a93b3bf..9872de9 100644 --- a/src/parallel.h +++ b/src/parallel.h @@ -1,25 +1,31 @@ #include // Declaration of array for storing pthread identifiers from pthread_create function -extern pthread_t *miniomp_threads; + +typedef struct { + unsigned int id; // id of the thread that reached the single part +} miniomp_single_t; // Type declaration for parallel descriptor (arguments needed to create pthreads) typedef struct { void (*fn) (void *); void *fn_data; - int id; + unsigned int id; pthread_mutex_t mutex; - // complete the definition of parallel descriptor + pthread_barrier_t barrier; + miniomp_single_t *single; } miniomp_parallel_t; typedef struct { unsigned int id; -} miniomp_parallel_region; + pthread_t pthread; + miniomp_parallel_t *region; +} miniomp_thread_t; extern miniomp_parallel_t *miniomp_parallel; - -// Declaration of per-thread specific key extern pthread_key_t miniomp_specifickey; // Functions implemented in this module +void miniomp_parallel_init(miniomp_parallel_t *parallel, void (*fn) (void *), void *data, unsigned int id); +void miniomp_thread_init(miniomp_thread_t * thread, unsigned int id, void (*fn) (void *), miniomp_parallel_t *region); void GOMP_parallel (void (*fn) (void *), void *data, unsigned num_threads, unsigned int flags); diff --git a/src/single.c b/src/single.c index c5bc982..2d32d36 100644 --- a/src/single.c +++ b/src/single.c @@ -1,16 +1,27 @@ #include "libminiomp.h" -// Declaratiuon of global variable for single work descriptor miniomp_single_t miniomp_single; -/* This routine is called when first encountering a SINGLE construct. - Returns true if this is the thread that should execute the clause. */ - bool GOMP_single_start (void) { - printf("TBI: Entering into single, but don't know who else arrived so I proceed\n"); - return(true); + miniomp_thread_t *thread = pthread_getspecific(miniomp_specifickey); + unsigned int id = omp_get_thread_num(); + pthread_mutex_lock(&(thread->region->mutex)); + if (thread->region->single == NULL){ + miniomp_single.id = id; + thread->region->single = &miniomp_single; + pthread_mutex_unlock(&(thread->region->mutex)); + return(true); + } + else { + if(thread->region->single->id == id){ + pthread_mutex_unlock(&(thread->region->mutex)); + return(true); + } + else{ + pthread_mutex_unlock(&(thread->region->mutex)); + return(false); + } + } } - - diff --git a/src/single.h b/src/single.h deleted file mode 100644 index 72423cf..0000000 --- a/src/single.h +++ /dev/null @@ -1,7 +0,0 @@ -// Type declaration for single work sharing descriptor -typedef struct { - // complete the definition of single descriptor -} miniomp_single_t; - -// Declaration of global variable for single work descriptor -extern miniomp_single_t miniomp_single; diff --git a/src/synchronization.c b/src/synchronization.c index 04f74bb..f580992 100644 --- a/src/synchronization.c +++ b/src/synchronization.c @@ -4,27 +4,28 @@ pthread_mutex_t miniomp_default_lock; void GOMP_critical_start (void) { - printf("TBI: Entering an unnamed critical, don't know if anyone else is alrady in. I proceed\n"); + miniomp_thread_t *thread = pthread_getspecific(miniomp_specifickey); + pthread_mutex_lock(&(thread->region->mutex)); } void GOMP_critical_end (void) { - printf("TBI: Exiting an unnamed critical section. I can not inform anyone else, bye!\n"); + miniomp_thread_t *thread = pthread_getspecific(miniomp_specifickey); + pthread_mutex_unlock(&(thread->region->mutex)); } void GOMP_critical_name_start (void **pptr) { - pthread_mutex_t * plock = *pptr; - printf("TBI: Entering a named critical %p (%p), don't know if anyone else is alrady in. I proceed\n", pptr, plock); - // if plock is NULL it means that the lock associated to the name has not yet been allocated and initialized + pthread_mutex_t * plock = pptr; + pthread_mutex_lock(plock); } void GOMP_critical_name_end (void **pptr) { - pthread_mutex_t * plock = *pptr; - printf("TBI: Exiting a named critical %p (%p), I can not inform anyone else, bye!\n", pptr, plock); - // if plock is still NULL something went wrong + pthread_mutex_t * plock = pptr; + pthread_mutex_unlock(plock); } pthread_barrier_t miniomp_barrier; void GOMP_barrier() { - printf("TBI: Entering in barrier, but do not know how to wait for the rest. I proceed\n"); + miniomp_thread_t *thread = pthread_getspecific(miniomp_specifickey); + pthread_barrier_wait(&(thread->region->barrier)); } diff --git a/src/thread.c b/src/thread.c deleted file mode 100644 index 75f278d..0000000 --- a/src/thread.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "thread.h" - -void miniomp_thread_init(miniomp_thread * thread, unsigned int id, void (*fn) (void *), void *data){ - thread->id = id; - pthread_create(thread->pthread, NULL, fn, data); -} diff --git a/src/thread.h b/src/thread.h deleted file mode 100644 index 73d797c..0000000 --- a/src/thread.h +++ /dev/null @@ -1,9 +0,0 @@ -#include -#include "libminiomp.h" - -typedef struct { - unsigned int id; - pthread_t pthread; -} miniomp_thread; - -void miniomp_thread_init(miniomp_thread * thread, unsigned int id); diff --git a/test/tparallel.c b/test/tparallel.c index 4d46902..23941b0 100644 --- a/test/tparallel.c +++ b/test/tparallel.c @@ -8,7 +8,7 @@ int foo() { int i, x = 1023; #pragma omp parallel firstprivate(x) reduction(+:first) if(x>0) num_threads(2) { - x++; + x++; first += x; } diff --git a/test/tworkshare b/test/tworkshare new file mode 100755 index 0000000..ac1504d Binary files /dev/null and b/test/tworkshare differ diff --git a/toboada.sh b/toboada.sh new file mode 100755 index 0000000..1479238 --- /dev/null +++ b/toboada.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -ue + +PAP=${1:-12} + +echo "Upload to boada user pap00${PAP}" + +scp -r src pap00${PAP}@boada.ac.upc.edu:miniomp + +ssh pap00${PAP}@boada.ac.upc.edu \ No newline at end of file