/* * 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); }
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)); } } } }
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; }