Пример #1
0
/*
 * Send an IPC message to the destination thread.
 *
 * By the time we reach this functions, our registers containing the message
 * payload will have already been saved to our context frame. We are
 * responsible for just copying from there.
 */
NORETURN void
sys_ipc_send_c(word_t dest_thread, word_t operation)
{
    /* Ensure the thread exists. */
    if (EXPECT_FALSE(dest_thread >= max_tcbs)) {
        syscall_return_error(IPC_ERROR, EINVAL);
    }

    /* Find the destination thread. */
    tcb_t *dest = &tcbs[dest_thread];

    /* Take IPC lock. */
    spin_lock(&ipc_lock);

    /* Ensure the thread is still alive. */
    if (EXPECT_FALSE(!is_thread_alive(dest))) {
        spin_unlock(&ipc_lock);
        syscall_return_error(IPC_ERROR, EINVAL);
    }

    /* Do the IPC. */
    tcb_t *next = do_send(dest, OPERATION_IS_CALL(operation),
            OPERATION_IS_NON_BLOCKING(operation));

    /* Done. */
    spin_unlock(&ipc_lock);
    switch_to(next);
}
Пример #2
0
void *adjust_thread(void *threadpool)
{
    int i;
    threadpool_t *pool = (threadpool_t *)threadpool;
    while (!pool->shutdown)
    {
        sleep(DEFAULT_TIME);                                    /*延时10秒*/
        pthread_mutex_lock(&(pool->lock));
        int queue_size = pool->queue_size;
        int live_thr_num = pool->live_thr_num;
        pthread_mutex_unlock(&(pool->lock));

        pthread_mutex_lock(&(pool->thread_counter));
        int busy_thr_num = pool->busy_thr_num;
        pthread_mutex_unlock(&(pool->thread_counter));

        /*任务数大于最小线程池个数并且存活的线程数少于最大线程个数时,创建新线程*/
        if (queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < pool->max_thr_num)
        {
            pthread_mutex_lock(&(pool->lock));
            int add = 0;
            /*一次增加DEFAULT_THREAD个线程*/
            for (i = 0; i < pool->max_thr_num && add < DEFAULT_THREAD_VARY
                    && pool->live_thr_num < pool->max_thr_num; i++)
            {
                if (pool->threads[i] == 0 || !is_thread_alive(pool->threads[i]))
                {
                    pthread_create(&(pool->threads[i]), NULL, threadpool_thread, (void *)pool);
                    add++;
                    pool->live_thr_num++;
                }
            }
            pthread_mutex_unlock(&(pool->lock));
        }

        /*销毁多余的空闲线程*/
        if ((busy_thr_num * 2) < live_thr_num
                && live_thr_num > pool->min_thr_num)
        {
            /*一次销毁DEFAULT_THREAD个线程*/
            pthread_mutex_lock(&(pool->lock));
            pool->wait_exit_thr_num = DEFAULT_THREAD_VARY;
            pthread_mutex_unlock(&(pool->lock));

            for (i = 0; i < DEFAULT_THREAD_VARY; i++)
            {
                /*通知处在空闲状态的线程*/
                pthread_cond_signal(&(pool->queue_not_empty));
            }
        }
    }
}
Пример #3
0
static PyObject *schedule_task_unblock(PyTaskletObject *prev,
				       PyTaskletObject *next,
				       int stackless)
{
	PyThreadState *ts = PyThreadState_GET();
	PyThreadState *nts = next->cstate->tstate;
	PyObject *retval;
	long thread_id = nts->thread_id;
	PyObject *unlock_lock;

	if (ts->st.thread.self_lock == NULL) {
		if (!(ts->st.thread.self_lock = new_lock()))
			return NULL;
		acquire_lock(ts->st.thread.self_lock, 1);
		if (!(ts->st.thread.unlock_lock = new_lock()))
			return NULL;
		if (interthread_lock == NULL) {
			if (!(interthread_lock = PyThread_allocate_lock()))
				return NULL;
		}
	}

	/*
	 * make sure nobody else tries a transaction at the same time
	 * on this tasklet's thread state, because two tasklets of the
	 * same thread could be talking to different threads. They must
	 * be serviced in fifo order.
	 */

	if (nts->st.thread.unlock_lock == NULL) {
		if (!(nts->st.thread.unlock_lock = new_lock()))
			return NULL;
	}
	unlock_lock = nts->st.thread.unlock_lock;
	Py_INCREF(unlock_lock);

	PyEval_SaveThread();
	PR("unblocker waiting for unlocker lock");
	acquire_lock(unlock_lock, 1);
	PR("unblocker HAS unlocker lock");

	/*
	 * also make sure that only one single interthread transaction
	 * is performed at any time.
	 */

	PR("unblocker waiting for interthread lock");
	PyThread_acquire_lock(interthread_lock, 1);
	PR("unblocker HAS interthread lock");
	PyEval_RestoreThread(ts);

	/* get myself ready */
	retval = slp_schedule_task(prev, prev, stackless);

	/* see whether the other thread still exists and is really blocked */
	if (is_thread_alive(thread_id) && nts->st.thread.is_locked) {
		/* tell the blocker what comes next */
		temp.unlock_target = next;
		temp.other_lock = ts->st.thread.self_lock;
		/* give it an extra ref, in case I would die early */
		Py_INCREF(temp.other_lock);

		/* unblock it */
		release_lock(nts->st.thread.self_lock);

		/* wait for the transaction to finish */

		PyEval_SaveThread();
		PR("unblocker waiting for own lock");
		acquire_lock(ts->st.thread.self_lock, 1);
		PR("unblocker HAS own lock");
		PyEval_RestoreThread(ts);
	}
	else {
		PR("unlocker: other is NOT LOCKED or dead");
		if (next->flags.blocked) {
			/* unblock from channel */
			slp_channel_remove_slow(next);
			slp_current_insert(next);
		}
		else if (next->next == NULL) {
			/* reactivate floating task */
			Py_INCREF(next);
			slp_current_insert(next);
		}
	}
	PR("unblocker releasing interthread lock");
	PyThread_release_lock(interthread_lock);
	PR("unblocker RELEASED interthread lock");
	PR("unblocker releasing unlocker lock");
	release_lock(unlock_lock);
	Py_DECREF(unlock_lock);
	PR("unblocker RELEASED unlocker lock");

	return retval;
}