int mypthread_create(mypthread_t *thread, 
                   const pthread_attr_t *attr,
                   void *(*start_routine) (void *),
                   void *arg)
{

   //sem_wait(&sem_main);

   if (first_call == 1)
   {
      mypthread_init();
      mypthread_t* temp = (mypthread_t*)malloc(sizeof(mypthread_t));
      new_thread_node(temp);
      enqueue(mythread_q,temp);
      temp->pthread->thread_state = PS_ACTIVE;
      fprintf(stderr, "Creating thread with id = %d\n",temp->pthread->thread_id);
      /* main_thread->thread_state = PS_ACTIVE; */
      first_call = 0;
   } 
   //sem_post(&sem_main);

   new_thread_node(thread);
   
   getcontext(thread->pthread->ucontext);  
   makecontext(thread->pthread->ucontext, (void (*)()) start_routine, 1, arg);

   //sem_wait(&sem_main);   
   enqueue(mythread_q,thread);
   thread->pthread->thread_state = PS_ACTIVE;
   fprintf(stderr, "Creating thread with id = %d\t",thread->pthread->thread_id);
   mykthread_create();
   //sem_post(&sem_main);
   
   return 0;
}
int main(int argc, char *argv[]) {
	if (argc != 2) {
		printf("usage: %s mypthread_policy(0|1|2|3)\n", argv[0]);
		exit(0);
	}
	mypthread_init(atoi(argv[1]));
	mypthread_mutex_init(&mutex1, NULL);
	mypthread_t thread_id[NTHREADS];
	int i, j;

	for (i = 0; i < NTHREADS; i++) {
		mypthread_create(&thread_id[i], NULL, thread_function, NULL);
	}

	for (j = 0; j < NTHREADS; j++) {
		mypthread_join(thread_id[j], NULL);
	}

	/* Now that all threads are complete I can print the final result.     */
	/* Without the join I could be printing a value before all the threads */
	/* have been completed.                                                */

	printf("Final counter value: %d\n", counter);
	mypthread_exit(NULL);
}
threadpool create_threadpool(int num_threads_in_pool, int mode) {
	mypthread_init(mode);
	_threadpool *pool;
	// sanity check the argument
	if ((num_threads_in_pool <= 0) || (num_threads_in_pool > MAXT_IN_POOL))
		return NULL;
	pool = (_threadpool *) malloc(sizeof(_threadpool));
	if (pool == NULL) {
		fprintf(stderr, "Out of memory creating a new threadpool!\n");
		return NULL;
	}
	pool->threads = (mypthread_t*) malloc(
			sizeof(mypthread_t) * num_threads_in_pool);
	if (!pool->threads) {
		fprintf(stderr, "Out of memory creating a new threadpool!\n");
		return NULL;
	}

	pool->no_of_threads = num_threads_in_pool;
	pool->no_of_tasks_in_Q = 0;

	/*
	 * Initialize Q
	 *
	 */
	pool->taskQ_front = pool->taskQ_rear = NULL;
	//check if locks are aquired
	if ((mypthread_mutex_init(&(pool->mutex), NULL))
			|| (mypthread_cond_init(&(pool->cond), NULL))) {
		return NULL;
	}

	//create thread queue
	int i = 0;
	while (i < num_threads_in_pool) {
		if (mypthread_create(&(pool->threads[i]), NULL, threadpool_scheduler,
				(void*) pool) != 0) {
			return NULL;
		}
		pool->no_of_threads++;
		pool->no_of_running_threads++;
		i++;
	}
	//mypthread_yield();
	return (threadpool) pool;
}
int main(int argc, char *argv[]) {
    if (argc < 2) {
        printf("usage: %s mypthread_policy(0|1|2|3) LISTSIZE\n", argv[0]);
        exit(0);
    }
    mypthread_init(atoi(argv[1]));
    int i, *pList = 0, nListSize = LISTSIZE;
    mypthread_t *threads, thrcheck;
    mypthread_mutex_t *mutexes;
    struct pthrarg *pthrargs, pthrargcheck;

    if (argc == 3)
        nListSize = atoi(argv[2]);
    nListSize = nListSize > 0 ? nListSize : LISTSIZE;

    // Creating the List of numbers
    printf("Number of elements: %d\n", nListSize);

    pList = (int *) malloc(sizeof(int) * nListSize);
    for (i = 0; i < nListSize; i++)
//        pList[i] = random( ) % (nListSize<<1);   // random list
        pList[i] = nListSize - i;   // decreasing list  (easier to debug)

    printf("[BEFORE] The list is NOT sorted:\n");
    printList(pList, nListSize);

    threads = (mypthread_t *) malloc(sizeof(mypthread_t) * (nListSize - 1));
    mutexes = (mypthread_mutex_t *) malloc(
                  sizeof(mypthread_mutex_t) * nListSize);
    pthrargs = (struct pthrarg *) malloc(
                   sizeof(struct pthrarg) * (nListSize - 1));

    mypthread_mutex_init(&mutexes[0], 0);
    for (i = 0; i < nListSize - 1; i++) {
        mypthread_mutex_init(&mutexes[i + 1], 0);

        pthrargs[i].num = &pList[i];
        pthrargs[i].mtx = &mutexes[i];
        pthrargs[i].size = nListSize;
        if (mypthread_create(&threads[i], 0, &fnsort, &pthrargs[i]) != 0) {
            printf("[FATAL] Could not create thread: %d\n", i);
            exit(1);
        }
    }

    pthrargcheck.num = pList;
    pthrargcheck.mtx = mutexes;
    pthrargcheck.size = nListSize;

    if (mypthread_create(&thrcheck, 0, &fncheck, &pthrargcheck) != 0) {
        printf("[FATAL] Could not create thread: fncheck\n");
        exit(1);
    }

    ///////////
    // Waiting the threads to complete the sorting
    //////////
    printf("waiting...\n");

    for (i = 0; i < nListSize - 1; i++)
        mypthread_join(threads[i], 0);
    mypthread_join(thrcheck, 0);

    for (i = 0; i < nListSize; i++)
        mypthread_mutex_destroy(&mutexes[i]);

    printf("[AFTER] The list is sorted:\n");
    printList(pList, nListSize);

    // Cleaning
    free(pthrargs);
    free(mutexes);
    free(threads);
    free(pList);

    return 0;
}