diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/meson.build b/meson.build
index a994b3aab6a74e0781e602b656823133ca7fbe18..27dd1dc4fb96a822b1d36d6dcb7c05cebc4a2e4a 100644
--- a/meson.build
+++ b/meson.build
@@ -6,6 +6,7 @@ libm = cc.find_library('m')
 utils = library('utils', 'utils.c')
 
 glib_dep = dependency('glib-2.0', version: '>= 2.16')
+openmp_dep = dependency('openmp')
 
 executable('add', 'add.c')
 executable('add2', 'add2.c', link_with: utils)
@@ -30,4 +31,5 @@ executable('write', 'write.c')
 subdir('array')
 subdir('hashtable')
 subdir('list')
-subdir('winter')
\ No newline at end of file
+subdir('openmp')
+subdir('winter')
diff --git a/openmp/meson.build b/openmp/meson.build
new file mode 100644
index 0000000000000000000000000000000000000000..f154584eee6fb06503ca62cd1cc3de39d8b38404
--- /dev/null
+++ b/openmp/meson.build
@@ -0,0 +1,7 @@
+cc = meson.get_compiler('c')
+libm = cc.find_library('m')
+
+executable('pi', 'pi.c', dependencies: [openmp_dep, libm])
+executable('simd', 'simd.c', dependencies: openmp_dep)
+executable('taylor', 'taylor.c', dependencies: openmp_dep)
+executable('threads', 'threads.c', dependencies: openmp_dep)
diff --git a/openmp/pi.c b/openmp/pi.c
new file mode 100644
index 0000000000000000000000000000000000000000..6d2384f848724a5d7790b35dc26cec0435d64d3b
--- /dev/null
+++ b/openmp/pi.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <tgmath.h>
+#include <time.h>
+
+#include <omp.h>
+
+#define NUM_STEPS (10 * 1000 * 1000)
+
+static double
+random_coord (void)
+{
+    return 2 * ((double) rand () / RAND_MAX) - 1;
+}
+
+static double
+pi_func (size_t n)
+{
+    size_t inside = 0;
+
+    printf ("Started\n");
+
+    srand (time (NULL));
+
+    #pragma omp parallel for reduction(+:inside)
+    for (size_t i = 0; i < n; i++)
+    {
+        double x = random_coord ();
+        double y = random_coord ();
+        double r2 = pow (x, 2) + pow (y, 2);
+        if (r2 <= 1.0)
+            inside++;
+    }
+
+	return (4 * ((double) inside / n));
+}
+
+int 
+main (void)
+{
+    double start = omp_get_wtime ();
+    double pi = pi_func (NUM_STEPS);
+    double stop = omp_get_wtime ();
+
+    printf ("pi = %lf, took %.3f seconds\n", pi, stop-start);
+
+	return 0;
+}
diff --git a/openmp/simd.c b/openmp/simd.c
new file mode 100644
index 0000000000000000000000000000000000000000..ae48262712b1df82823da2b4f9ee198b070a3354
--- /dev/null
+++ b/openmp/simd.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+
+static const int N = 32;
+
+#pragma omp declare simd uniform(fact)
+double
+add1 (double a,
+      double b,
+      double fact)
+{
+    return a + b + fact;
+}
+
+#pragma omp declare simd uniform(a,b,fact) linear(i:1)
+double
+add2 (double *a,
+      double *b,
+      int     i,
+      double  fact)
+{
+    return a[i] + b[i] + fact;
+}
+
+#pragma omp declare simd uniform(fact) linear(a,b:1)
+double
+add3 (double *a,
+      double *b,
+      double  fact)
+{
+    return *a + *b + fact;
+}
+
+void
+work (double *a,
+      double *b,
+      int     n)
+{
+    double tmp;
+
+    #pragma omp simd private(tmp)
+    for (int i = 0; i < n; i++)
+    {
+        tmp = add1 (a[i], b[i], 1.0);
+        a[i] = add2 (a, b, i, 1.0 + tmp);
+        a[i] = add3 (&a[i], &b[i], 1.0);
+    }
+}
+
+int
+main (void)
+{
+    double a[N], b[N];
+
+    for (int i = 0; i < N; i++)
+    {
+        a[i] = i;
+        b[i] = N - i;
+    }
+
+    work (a, b, N);
+
+    for (int i = 0; i < N; i++)
+        printf ("%d %f\n", i, a[i]);
+
+    return 0;
+}
diff --git a/openmp/taylor.c b/openmp/taylor.c
new file mode 100644
index 0000000000000000000000000000000000000000..28df1ddd083c1c2f3f7a68c455449a1391b2c18b
--- /dev/null
+++ b/openmp/taylor.c
@@ -0,0 +1,65 @@
+#include <stdio.h>
+
+#include <omp.h>
+
+static const size_t NUM_STEPS = 1e9;
+
+static double
+e_func (size_t n)
+{
+	double e = 1;
+	double factorial = 1;
+
+	printf ("e started\n");
+
+	#pragma omp parallel for shared(factorial) reduction(+:e)
+	for (size_t i = 1; i < n; i++)
+	{
+		factorial *= i;
+		e += 1.0 / factorial;
+	}
+
+	return e;
+}
+
+static double
+pi_func (size_t n)
+{
+	double pi = 0;
+
+	printf ("pi started\n");
+
+	for (size_t i = 0; i < n; i++)
+	{
+		pi += 1.0 / (i * 4.0 + 1.0);
+		pi -= 1.0 / (i * 4.0 + 3.0);
+	}
+
+	pi *= 4.0;
+
+	return pi;
+}
+
+int 
+main (void)
+{
+	#pragma omp parallel sections
+	{
+		#pragma omp section
+		{
+			double start = omp_get_wtime ();
+			double e = e_func (NUM_STEPS);
+			double stop = omp_get_wtime ();
+			printf ("e = %lf, took %.3f seconds\n", e, stop-start);
+		}
+		#pragma omp section
+		{
+			double start = omp_get_wtime ();
+			double pi = pi_func (NUM_STEPS);
+			double stop = omp_get_wtime ();
+			printf ("pi = %lf, took %.3f seconds\n", pi, stop-start);
+		}
+	}
+
+	return 0;
+}
diff --git a/openmp/threads.c b/openmp/threads.c
new file mode 100644
index 0000000000000000000000000000000000000000..7963ce78be6209626d6e36119aadc164c1145913
--- /dev/null
+++ b/openmp/threads.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+
+#include <omp.h>
+
+int
+main (void)
+{
+    #pragma omp parallel
+    {
+        int tid = omp_get_thread_num ();
+        printf ("Hello world from thread %d\n", tid);
+
+        #pragma omp master
+        {
+            int nthreads = omp_get_max_threads ();
+            int procs = omp_get_num_procs ();
+            printf ("%d threads and %d processors\n", nthreads, procs);
+        }
+    }
+}