MME2 changes - Propped commits from openmme/paging branch. Added scripts
for code gen

Change-Id: Ie55032217232214ac8544ca76ea34335205329e4
diff --git a/src/common/thread_pool.c b/src/common/thread_pool.c
new file mode 100644
index 0000000..aa44e31
--- /dev/null
+++ b/src/common/thread_pool.c
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2003-2018, Great Software Laboratory Pvt. Ltd.
+ * Copyright (c) 2017 Intel Corporation
+ * Copyright (c) 2019, Infosys Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include "thread_pool.h"
+#include "tpool_queue.h"
+
+struct Job *create_job(JobFunction function, void *arg)
+{
+	struct Job *job;
+	job = (struct Job *)malloc(sizeof(struct Job));
+	if(job == NULL) {
+#ifdef DEBUG
+		log_msg(LOG_ERROR, "failed to allocate memory\n");
+#endif
+		return NULL;
+	}
+	job->function = function;
+	job->arg = arg;
+	return job;
+}
+
+static void *worker_thread(void *userdata)
+{
+	void *arg;
+	struct Job *job;
+	JobFunction function;
+	struct thread_pool *pool;
+
+	pool = (struct thread_pool *)userdata;
+
+	while(1) {
+		pthread_mutex_lock(&pool->queue_mutex);
+
+		/* waiting until dispatch thread signals for new job */
+		pthread_cond_wait(&pool->job_received, &pool->queue_mutex);
+		job = queue_pop_head(pool->job_queue);
+		pthread_mutex_unlock(&pool->queue_mutex);
+
+		if(job != NULL) {
+			function = job->function;
+			arg = job->arg;
+			free(job);
+
+			/* atomically updating idle_threads */
+			__sync_fetch_and_sub(&pool->idle_threads, 1);
+
+			function(arg);
+
+			__sync_fetch_and_add(&pool->idle_threads, 1);
+		}
+	}
+	return NULL;
+}
+
+/* If queue has pending jobs and 
+ * thread is idle then signal the thread
+ * to process the job
+ */
+static void *dispatch_if_idle(void *userdata)
+{
+	struct thread_pool *pool;
+
+	pool = (struct thread_pool *)userdata;
+
+	while(1) {
+		if((pool->idle_threads > 0) &&
+			pool->job_queue->length > 0 ) {
+			pthread_cond_signal(&pool->job_received);
+		} else usleep(10);
+	}
+	return NULL;
+}
+
+/* creates a thread and pushes into queue */
+static int spawn_thread(struct thread_pool *pool)
+{
+	int status;
+	pthread_t thread;
+
+	status = pthread_create(&thread, NULL, worker_thread, pool);
+	if(status < 0)
+		return status;
+
+	queue_push_tail(pool->thread_queue, &thread);
+
+	return 0;
+}
+
+/* pushes job into queue */
+int insert_job(struct thread_pool *pool, JobFunction function, void *userdata)
+{
+	struct Job *job;
+	
+	if(pool == NULL)
+		return -1;
+
+	job = create_job(function, userdata);
+	if(job == NULL)
+		return -ENOMEM;
+
+	pthread_mutex_lock(&pool->queue_mutex);
+	queue_push_tail(pool->job_queue, job);
+	pthread_mutex_unlock(&pool->queue_mutex);
+
+	return 0;
+}
+
+struct thread_pool *thread_pool_new(int count)
+{
+	int i, status;
+	pthread_t thread;
+	struct thread_pool *pool;
+
+	pool = (struct thread_pool *)malloc(sizeof(struct thread_pool));
+	if(pool == NULL) {
+#ifdef DEBUG
+		log_msg(LOG_ERROR, "failed to allocate memory\n");
+#endif
+		errno = ENOMEM;
+		return NULL;
+	}
+	pool->idle_threads = count;
+	pool->job_queue = queue_new();
+	pool->thread_queue = queue_new();
+
+	pthread_mutex_init(&pool->queue_mutex, NULL);
+	pthread_cond_init(&pool->job_received, NULL);
+
+	status = pthread_create(&thread, NULL, dispatch_if_idle, pool);
+	if(status < 0) {
+#ifdef DEBUG
+		log_msg(LOG_ERROR, "failed to spawn dispatch thread, stopping\n");
+#endif
+		return NULL;
+	}
+	pool->dispatch_thread = thread;
+
+	i = 0;
+	while(i < count)
+		if (spawn_thread(pool) == 0)
+			i++;
+
+	return pool;
+}
+
+int thread_pool_destroy(struct thread_pool *pool)
+{
+	pthread_t *thread;
+
+	if(pool == NULL)
+		return -1;
+
+	pthread_cancel(pool->dispatch_thread);
+	while((thread = queue_pop_head(pool->job_queue)) != NULL) {
+		pthread_cancel(*thread);	
+	}
+
+	queue_destroy(pool->job_queue, free);
+	queue_destroy(pool->thread_queue, NULL);
+	pthread_mutex_destroy(&pool->queue_mutex);
+	pthread_cond_destroy(&pool->job_received);
+
+	free(pool);
+	return 0;
+}
+
+