void *thread_function(void *dummyPtr) {
	//printf("Thread number %ld\n", mypthread_self());
	mypthread_mutex_lock(&mutex1);
	counter++;
	mypthread_mutex_unlock(&mutex1);
	mypthread_exit(NULL);
}
void *threadpool_scheduler(threadpool p) {
	_threadpool * pool = (_threadpool *) p;
	struct task* cur;	//The q element

	while (1) {
		mypthread_mutex_lock(&(pool->mutex));

		while (pool->no_of_tasks_in_Q == 0) {
			//mypthread_mutex_unlock(&(pool->mutex));
			mypthread_cond_wait(&(pool->cond), &(pool->mutex));

		}

		cur = pool->taskQ_front;

		pool->no_of_tasks_in_Q--;

		if (pool->no_of_tasks_in_Q == 0) {
			pool->taskQ_front = NULL;
			pool->taskQ_rear = NULL;
		} else {
			pool->taskQ_front = cur->next;
		}

		if (pool->no_of_tasks_in_Q == 0) {
			mypthread_cond_signal(&(pool->cond));
		}
		mypthread_mutex_unlock(&(pool->mutex));
		(cur->func)(cur->arg);
		free(cur);
	}
}
void dispatch(threadpool from_me, dispatch_fn dispatch_to_here, void *arg) {
	_threadpool *pool = (_threadpool *) from_me;
	if (pool == NULL || dispatch_to_here == NULL) {
		printf("Threadpool invalid");

	}
	struct task *mytask;
	mytask = (struct task*) malloc(sizeof(struct task));
	if (mytask == NULL) {
		printf("No memory allocation");
	}
	mytask->func = (void*) dispatch_to_here;
	mytask->arg = arg;
	mypthread_mutex_lock(&(pool->mutex));

	if (&(pool->no_of_threads) == &(pool->no_of_tasks_in_Q)) {
		printf("threadpool_queue_full");
	} else {
		push_task(pool, mytask);
		if (mypthread_cond_signal(&(pool->cond))) {
			printf("threadpool_lock_failure");
		}
		mypthread_cond_signal(&(pool->cond));
	}
	if (mypthread_mutex_unlock(&(pool->mutex))) {
		printf("not unlock");
	}
	mypthread_yield();

}
void *fnsort(void *arg) {
    struct pthrarg *pargs;
    int *num, swap;
    mypthread_mutex_t *mtx0, *mtx1;

    pargs = (struct pthrarg *) arg;
    num = pargs->num;
    mtx0 = pargs->mtx;
    mtx1 = pargs->mtx + 1;

    while (!quitting) {
        mypthread_mutex_lock(mtx0);
        if (mypthread_mutex_trylock(mtx1) != 0) {
            mypthread_mutex_unlock(mtx0);
            mypthread_yield();
            continue;
        }

        if (num[1] < num[0]) {
            swap = num[0];
            num[0] = num[1];
            num[1] = swap;
        }

        mypthread_mutex_unlock(mtx0);
        mypthread_mutex_unlock(mtx1);

        mypthread_yield();
    }

    mypthread_exit(0);

    // I will never get here
    return 0;
}
/*
 *	Functionality for pthread_cond_wait()
 */
int mypthread_cond_wait(mypthread_cond_t *cond, mypthread_mutex_t *mutex) {
	sem_wait(&cond_sem);
	//Unblock all threads locked by mutex
	mypthread_mutex_unlock(mutex);
	//Make the current thread wait for the signal
	mykthread_t* current_kthread = mykthread_get(gettid());
	current_kthread->th->state = PS_BLOCKED;
	ll_add(current_kthread->th, &(cond->cond_q_head), &(cond->cond_q_tail));
	sem_wait(&mypthread_sem);
	mypthread_enqueue(current_kthread->th);
	sem_post(&mypthread_sem);
	sem_post(&cond_sem);
	mythread_scheduler(current_kthread, 1);
	mypthread_mutex_lock(mutex);
	return 0;
}
void * fncheck( void *arg )
{
    struct pthrarg *pargs;
    int i, j = 0, size, check;
    mypthread_mutex_t *mtx;

    pargs = (struct pthrarg * )arg;
    mtx   = pargs->mtx;
    size  = pargs->size;

    while( !quitting )
    {
        printf( "." );
        if( (j+1) % 80 == 0 )
            printf( "\n" );

        //lock all threads
        for( i = 0; i < size; i++ )
            mypthread_mutex_lock( mtx+i );

        check = 1;
        for( i = 0; i < size-1 && check; i++ )
        {
            if( pargs->num[i] > pargs->num[i+1] )
                check = 0;
        }

        if( check )
            printf("\nQuitting...\n");
        quitting = check;

        //unlock all threads
        for( i = 0; i < size; i++ )
            mypthread_mutex_unlock( mtx+i );

        // j seconds
        j = j+1;
#ifndef MYTHREAD
       // sleep( j );
#endif
        mypthread_yield( );
    }

    mypthread_exit( 0 );

    return 0;
}
int mypthread_cond_wait(mypthread_cond_t *cond,
                      mypthread_mutex_t *mutex)
{
     sem_wait(&sem_cond);
     mypthread_mutex_unlock(mutex);
     sem_wait(&sem_main);
     mypthread_t *current_thread = search_thread(mythread_q, cur_thread_id);
     current_thread->pthread->thread_state = PS_BLOCKED;
     mypthread_t *next_thread = next_active_thread(mythread_q);
     cur_thread_id = next_thread->pthread->thread_id;
     linear_enqueue(cond->cond_block_q, current_thread->pthread);   
     sem_post(&sem_main);
     sem_post(&sem_mutex);
     swapcontext(current_thread->pthread->ucontext, next_thread->pthread->ucontext );
     mypthread_mutex_lock(mutex);
     return 0; 
}