コード例 #1
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/*
 * Description: This function returns the number of quantums until the thread
 * with id tid wakes up including the current quantum. If no thread with ID
 * tid exists it is considered as an error. If the thread is not sleeping,
 * the function should return 0.
 * Return value: Number of quantums (including current quantum) until wakeup.
*/
int uthread_get_time_until_wakeup(int tid)
{
	// Block SIGTVALRM signal
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	// If no such thread exists, this is an error
	if (livingThreads.find(tid) == livingThreads.end())
	{
		std::cerr << LIB_ERROR_MSG << "wakeup(" << tid
			  << ") failed - no such thread id. " << std::endl;
		resetSigMask(&oldSet);
		return EXIT_FAIL;
	}
	else if (livingThreads[tid]->get_state() != uthread::state::SLEEPING)
	{
		// If the thread is not sleeping, return SHOULD_WAKE == 0.
		resetSigMask(&oldSet);
		return SHOULD_WAKE;
	}
	else
	{
		// In general, diff shouldn't be negative, but if it does
		// it shouldn't crash the whole program.
		int diff = livingThreads[tid]->get_wakeup() - totalQuanta;
		resetSigMask(&oldSet);
		return diff >= SHOULD_WAKE ? diff : SHOULD_WAKE;
	}
}
コード例 #2
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/*
 * Description: This function resumes a blocked thread with ID tid and moves
 * it to the READY state. Resuming a thread in the RUNNING, READY or SLEEPING
 * state has no effect and is not considered as an error. If no thread with
 * ID tid exists it is considered as an error.
 * Return value: On success, return 0. On failure, return -1.
*/
int uthread_resume(int tid)
{
	// Block SIGTVALRM signal
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	if (livingThreads.find(tid) == livingThreads.end())
	{
		std::cerr << LIB_ERROR_MSG << "resume(" << tid
			<< ") failed - no such thread id" << std::endl;
		resetSigMask(&oldSet);
		return EXIT_FAIL;
	}

	uthread *curr = livingThreads[tid];
	if (curr->get_state() == uthread::state::BLOCKED)
	{
		curr->set_state(uthread::state::READY);
		readyThreads.push_back(curr->get_id());
	}

	// Unblock SIGVTALRM and return
	resetSigMask(&oldSet);
	return EXIT_SUCC;
}
コード例 #3
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/**
 * Function: deleteThread
 * Deletes a thread from the living threads list, the READY list (if it's
 * there) and frees its allocated memory.
 * Assumes the given tid exists in the living threads list.
 * Calling with tid == MAIN_THREAD_ID does nothing.
 * DO NOT CALL WITH UNEXISTING THREAD ID
 */
void deleteThread(uthread::id tid)
{
	// Block SIGVTALRM
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	if (tid == MAIN_THREAD_ID)
	{
		// Unblock and exit
		resetSigMask(&oldSet);
		return;
	}	
	uthread *curr = livingThreads[tid];
	// Remove from living threads list
	livingThreads.erase(tid);
	// Remove from ready threads list, if it's there
	auto th = std::find(readyThreads.begin(),
			    readyThreads.end(), tid);
	if (th != readyThreads.end())
	{
		readyThreads.erase(th);
	}
	// Free allocated data
	delete curr;

	// Unlblock signal
	resetSigMask(&oldSet);
}
コード例 #4
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/*
 * Description: This function terminates the thread with ID tid and deletes
 * it from all relevant control structures. All the resources allocated by
 * the library for this thread should be released. If no thread with ID tid
 * exists it is considered as an error. Terminating the main thread
 * (tid == 0) will result in the termination of the entire process using
 * exit(0) [after releasing the assigned library memory]. 
 * Return value: The function returns 0 if the thread was successfully
 * terminated and -1 otherwise. If a thread terminates itself or the main
 * thread is terminated, the function does not return.
*/
int uthread_terminate(int tid)
{
	// Block SIGTVALRM signal
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	// If main thread is terminated, delete all threads and quit.
	// The deleteThread function checks and manages data for future
	// process run, which is un-needed in this point.
	if (tid == MAIN_THREAD_ID)
	{
		for (auto th : livingThreads)
		{
			delete th.second;
		}
		exit(EXIT_SUCC);
	}
	// If no such thread exists, return failure.
	if (livingThreads.find(tid) == livingThreads.end())
	{
		std::cerr << LIB_ERROR_MSG <<"terminate(" << tid 
			  << ") failed - no such thread id" << std::endl;
		resetSigMask(&oldSet);
		return EXIT_FAIL;
	}

	// Otherwise, delete thread tid, if it's not sleeping.
	if (livingThreads[tid]->get_state() == uthread::state::SLEEPING)
	{
		std::cerr << LIB_ERROR_MSG
		          << "can't terminate a sleeping thread" << std::endl;
		resetSigMask(&oldSet);
		return EXIT_FAIL;
	}
	// If deleted yourself, goto contextSwitch.
	if ((uthread::id)tid == currentThread)
	{
		// Set this tid as the one that needs to be deleted
		// in the next contextSwitch
		toDelete = tid;
		resetSigMask(&oldSet);
		contextSwitch(SIGVTALRM);
		return EXIT_SUCC; // This should not be reached
	}
	// Otherwise, delete and return
	else
	{
		// Unblock SIGVTALRM and return
		resetSigMask(&oldSet);
		deleteThread(tid);
		return EXIT_SUCC;
	}
}
コード例 #5
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/*
 * Description: This function blocks the thread with ID tid. The thread may
 * be resumed later using uthread_resume. If no thread with ID tid exists it
 * is considered as an error. In addition, it is an error to try blocking the
 * main thread (tid == 0). If a thread blocks itself, a scheduling decision
 * should be made. Blocking a thread in BLOCKED or SLEEPING states has no
 * effect and is not considered as an error.
 * Return value: On success, return 0. On failure, return -1.
*/
int uthread_block(int tid)
{
	// Block SIGTVALRM signal
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	// Blocking the main thread is an error
	if (tid == MAIN_THREAD_ID)
	{
		std::cerr << LIB_ERROR_MSG << "can't block main thread." 
			  << std::endl;
		resetSigMask(&oldSet);
		return EXIT_FAIL;
	}
	// If no such thread exists, it is an error
	if (livingThreads.find(tid) == livingThreads.end())
	{
		std::cerr << LIB_ERROR_MSG << "block(" << tid
			  << ") failed - no such thread id" << std::endl;
		resetSigMask(&oldSet);
		return EXIT_FAIL;
	}
	// Check if the thread CAN be blocked
	// if not, do nothing.
	uthread *curr = livingThreads[tid];
	if (curr->get_state() == uthread::state::BLOCKED ||
	    curr->get_state() == uthread::state::SLEEPING)
	{
		resetSigMask(&oldSet);
		return EXIT_SUCC;
	}

	// If a thread blocks itself switch context and exit
	// (the return will be executed after the thread is resumed)
	else if ((uthread::id)tid == currentThread)
	{
		curr->set_state(uthread::state::BLOCKED);
		resetSigMask(&oldSet);
		contextSwitch(SIGVTALRM);
		return EXIT_SUCC;
	}
	// Otherwise, change the thread's state to BLOCKED and remove it
	// from the READY list.
	curr->set_state(uthread::state::BLOCKED);
	auto th = std::find(readyThreads.begin(), readyThreads.end(), tid);
	readyThreads.erase(th);
	resetSigMask(&oldSet);
	return EXIT_SUCC;
}
コード例 #6
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/*
 * Description: This function returns the number of quantums the thread with
 * ID tid was in RUNNING state. On the first time a thread runs, the function
 * should return 1. Every additional quantum that the thread starts should
 * increase this value by 1 (so if the thread with ID tid is in RUNNING state
 * when this function is called, include also the current quantum). If no
 * thread with ID tid exists it is considered as an error.
 * Return value: On success, return the number of quantums of the thread with 
 * ID tid. On failure, return -1.
*/
int uthread_get_quantums(int tid)
{
	// Block SIGTVALRM signal
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	if (livingThreads.find(tid) == livingThreads.end())
	{
		std::cerr << LIB_ERROR_MSG << "get_qunatums(" << tid
			  << ") failed - no such thread id." << std::endl;
		resetSigMask(&oldSet);
		return EXIT_FAIL;
	}
	resetSigMask(&oldSet);
	return livingThreads[tid]->get_runs();
}
コード例 #7
0
ファイル: SCDPlugin.c プロジェクト: 010001111/darling
static void
reaper(int sigraised)
{
	/*
	 * block additional SIGCHLD's until current children have
	 * been reaped.
	 */
	blockSignal();

	/*
	 * send message to indicate that at least one child is ready
	 * to be reaped.
	 */
	_SC_sendMachMessage(CFMachPortGetPort(childReaped), 0);

	return;
}
コード例 #8
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/*
 * Description: This function initializes the thread library. 
 * Call before any other thread library function, and exactly once. 
 * The input to the function is the length of a quantum in micro-seconds. 
 * It is an error to call this function with non-positive quantum_usecs.
 * Return value: On success, return 0. On failure, return -1.
*/
int uthread_init(int quantum_usecs)
{

	struct sigaction sa;

	// Make sure the quantum time is positive.	
	if (quantum_usecs <= 0) 
	{
		std::cerr << LIB_ERROR_MSG << "quantum_usecs argument "
			  << "must be positive" << std::endl;
		return EXIT_FAIL;
	}

	// Block SIGTVALRM signal
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	// Set up a the context switch func. as SIGVTALRM handler
	sa.sa_handler = &contextSwitch;
	sa.sa_flags = SIG_FLAGS;
	if (sigaction(SIGVTALRM, &sa, NULL) < 0) {
		std::cerr << SYS_ERROR_MSG 
			  << "sigaction failed." << std::endl;
		exit(SYSTEM_ERROR);
	}

	// Create the main thread
	uthread *mainThread = new uthread(MAIN_THREAD_ID, MAIN_THREAD_FUNC);
	mainThread->set_state(uthread::state::RUNNING);
	++totalQuanta;
	// Add main's id to live threads list (Default == 0).
	livingThreads.insert(std::make_pair(mainThread->get_id(), mainThread));

	// Set up a timer
	if (setTimer(quantum_usecs) < 0)
	{
		std::cerr << SYS_ERROR_MSG << "setitimer failed." << std::endl;
		exit(SYSTEM_ERROR);
	}

	// Unblock SIGVTALRM and return
	resetSigMask(&oldSet);
	return EXIT_SUCC;
}
コード例 #9
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/*
 * Description: This function creates a new thread, whose entry point is the
 * function f with the signature void f(void). The thread is added to the end
 * of the READY threads list. The uthread_spawn function should fail if it
 * would cause the number of concurrent threads to exceed the limit
 * (MAX_THREAD_NUM). Each thread should be allocated with a stack of size
 * STACK_SIZE bytes.
 * Return value: On success, return the ID of the created thread.
 * On failure, return -1.
*/
int uthread_spawn(void (*f)(void))
{
	// If the current number of threads is MAX_THREAD_NUM, no
	// more threads can be spawned.
	if (livingThreads.size() >= MAX_THREAD_NUM)
	{
		std::cerr << LIB_ERROR_MSG << "Number of threads exceeded "
			  << "the maximum number allowed." << std::endl;
		return EXIT_FAIL;
	}

	// Block SIGTVALRM signal
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	// Find the smallest id available, starting from MAIN_ID + 1.
	uthread::id newId = MAIN_THREAD_ID + 1;
	for (auto it = ++livingThreads.cbegin(); /* start from the second */
		  it != livingThreads.cend();
		++it)
	{
		if (newId < it->first)
		{
			// If the threads ids numbering doesn't match natural
			// incremental numbering, we found an empty spot.
			break;
		}
		++newId;
	}

	// Create a fresh thread with the found id and entry function f
	// Then put it in the living threads list and READY list.
	uthread *newThread = new uthread(newId, f);
	livingThreads.insert(std::make_pair(newId, newThread));
	readyThreads.push_back(newId);

	// Unblock SIGVTALRM and return
	resetSigMask(&oldSet);
	return newId;
}
コード例 #10
0
ファイル: uthreads.cpp プロジェクト: shahamran/os
/*
 * Description: This function puts the RUNNING thread to sleep for a period
 * of num_quantums (not including the current quantum) after which it is moved
 * to the READY state. num_quantums must be a positive number. It is an error
 * to try to put the main thread (tid==0) to sleep. Immediately after a thread
 * transitions to the SLEEPING state a scheduling decision should be made.
 * Return value: On success, return 0. On failure, return -1.
*/
int uthread_sleep(int num_quantums)
{
	// Block SIGTVALRM signal
	sigset_t oldSet;
	blockSignal(SIGVTALRM, &oldSet);

	if (currentThread == MAIN_THREAD_ID)
	{
		std::cerr << LIB_ERROR_MSG << "can't put main thread to sleep"
			  << std::endl;
		resetSigMask(&oldSet);
		return EXIT_FAIL;
	}

	uthread *curr = livingThreads[currentThread];
	curr->set_wakeup(totalQuanta + num_quantums);
	curr->set_state(uthread::state::SLEEPING);
	contextSwitch(SIGVTALRM);

	// Unblock SIGVTALRM and return
	resetSigMask(&oldSet);
	return EXIT_SUCC;
}
コード例 #11
0
ファイル: CwxEchoApp.cpp プロジェクト: chenper/cwinux
///配置运行环境信息
int CwxEchoApp::initRunEnv(){
    ///设置系统的时钟间隔,最小刻度为1ms,此为1s。
    this->setClick(1000);//1s
    ///设置工作目录
    this->setWorkDir(this->m_config.m_strWorkDir.c_str());
    ///设置循环运行日志的数量
    this->setLogFileNum(LOG_FILE_NUM);
    ///设置每个日志文件的大小
    this->setLogFileSize(LOG_FILE_SIZE*1024*1024);
    ///调用架构的initRunEnv,使以上设置的参数生效
    if (CwxAppFramework::initRunEnv() == -1 ) return -1;
    blockSignal(SIGPIPE);
    //set version
    this->setAppVersion(ECHO_APP_VERSION);
    //set last modify date
    this->setLastModifyDatetime(ECHO_MODIFY_DATE);
    //set compile date
    this->setLastCompileDatetime(CWX_COMPILE_DATE(_BUILD_DATE));

    ///将加载的配置文件信息输出到日志文件中,以供查看检查
    string strConfOut;
    m_config.outputConfig(strConfOut);
    CWX_INFO((strConfOut.c_str()));

    ///注册echo请求的处理handle,echo请求的svr-id为SVR_TYPE_ECHO
    m_eventHandler = new CwxEchoEventHandler(this);         
    this->getCommander().regHandle(SVR_TYPE_ECHO, m_eventHandler);

    ///监听TCP连接,其建立的连接的svr-id都为SVR_TYPE_ECHO,接收的消息的svr-id都为SVR_TYPE_ECHO。
    ///全部由m_eventHandler对象来处理
    if (0 > this->noticeTcpListen(SVR_TYPE_ECHO, 
        this->m_config.m_listen.getHostName().c_str(),
        this->m_config.m_listen.getPort(),
        false,
        CWX_APP_MSG_MODE,
        CwxEchoApp::setSockAttr,
        this))
    {
        CWX_ERROR(("Can't register the echo acceptor port: addr=%s, port=%d",
            this->m_config.m_listen.getHostName().c_str(),
            this->m_config.m_listen.getPort()));
        return -1;
    }
    ///监听UNIX DOMAIN连接,其建立的连接的svr-id都为SVR_TYPE_ECHO,接收的消息的svr-id都为SVR_TYPE_ECHO。
    ///全部由m_eventHandler对象来处理
    if (0 > this->noticeLsockListen(SVR_TYPE_ECHO, 
        this->m_config.m_strUnixPathFile.c_str()))
    {
        CWX_ERROR(("Can't register the echo unix acceptor port: path=%s",
            m_config.m_strUnixPathFile.c_str()));
        return -1;
    }
    ///创建线程池对象,此线程池中线程的group-id为2,线程池的线程数量为m_config.m_unThreadNum。
    m_threadPool = new CwxThreadPool(m_config.m_unThreadNum,
        &getCommander());
    ///启动线程,线程池中线程的线程栈大小为1M。
    if ( 0 != m_threadPool->start(NULL)){
        CWX_ERROR(("Failure to start thread pool"));
        return -1;
    }
    return 0;

}
コード例 #12
0
ファイル: init.c プロジェクト: tobium/robovm
Env* rvmStartup(Options* options) {
    // TODO: Error handling

#if defined(IOS) && (defined(RVM_ARMV7) || defined(RVM_THUMBV7))
    // Enable IEEE-754 denormal support.
    // Without this the VFP treats numbers that are close to zero as zero itself.
    // See http://developer.apple.com/library/ios/#technotes/tn2293/_index.html.
    fenv_t fenv;
    fegetenv(&fenv);
    fenv.__fpscr &= ~__fpscr_flush_to_zero;
    fesetenv(&fenv);
#endif

    TRACE("Initializing GC");
    if (!initGC(options)) return NULL;

    // Block SIGPIPE signals. SIGPIPE interrupts write() calls which we don't
    // want. Dalvik does this too in dalvikvm/Main.cpp.
    if (!blockSignal(SIGPIPE)) return NULL;

    // Block SIGXFSZ signals. SIGXFSZ is raised when writing beyond the RLIMIT_FSIZE
    // of the current process (at least on Darwin) using pwrite().
    if (!blockSignal(SIGXFSZ)) return NULL;

    VM* vm = rvmCreateVM(options);
    if (!vm) return NULL;

    Env* env = rvmCreateEnv(vm);
    if (!env) return NULL;
    // TODO: What if we can't allocate Env?

    if (!initClasspathEntries(env, options->basePath, options->rawBootclasspath, &options->bootclasspath)) return NULL;
    if (!initClasspathEntries(env, options->basePath, options->rawClasspath, &options->classpath)) return NULL;

    // Call init on modules
    TRACE("Initializing logging");
    if (!rvmInitLog(env)) return NULL;
    TRACE("Initializing classes");
    if (!rvmInitClasses(env)) return NULL;
    TRACE("Initializing memory");
    if (!rvmInitMemory(env)) return NULL;
    TRACE("Initializing methods");
    if (!rvmInitMethods(env)) return NULL;
    TRACE("Initializing strings");
    if (!rvmInitStrings(env)) return NULL;
    TRACE("Initializing monitors");
    if (!rvmInitMonitors(env)) return NULL;
    TRACE("Initializing proxy");
    if (!rvmInitProxy(env)) return NULL;
    TRACE("Initializing threads");
    if (!rvmInitThreads(env)) return NULL;
    TRACE("Initializing attributes");
    if (!rvmInitAttributes(env)) return NULL;
    TRACE("Initializing primitive wrapper classes");
    if (!rvmInitPrimitiveWrapperClasses(env)) return NULL;
    TRACE("Initializing exceptions");
    if (!rvmInitExceptions(env)) return NULL;
    TRACE("Initializing signals");
    if (!rvmInitSignals(env)) return NULL;

    // Initialize the RoboVM rt JNI code
//    RT_JNI_OnLoad(&vm->javaVM, NULL);
    // Initialize dalvik's JNIHelp code in libnativehelper
    TRACE("Initializing dalvik's libnativehelper");
    registerJniHelp((JNIEnv*) env);
    // Initialize the dalvik rt JNI code
    TRACE("Initializing dalvik's runtime JNI code");
    registerCoreLibrariesJni((JNIEnv*) env);

    TRACE("Creating system ClassLoader");
    systemClassLoader = rvmGetSystemClassLoader(env);
    if (rvmExceptionOccurred(env)) goto error_system_ClassLoader;
    env->currentThread->threadObj->contextClassLoader = systemClassLoader;

    TRACE("Initialization done");
    env->vm->initialized = TRUE;
    
    // Start Daemons
    TRACE("Starting Daemons");
    java_lang_Daemons = rvmFindClassUsingLoader(env, "java/lang/Daemons", NULL);
    if (!java_lang_Daemons) goto error_daemons;
    java_lang_Daemons_start = rvmGetClassMethod(env, java_lang_Daemons, "start", "()V");
    if (!java_lang_Daemons_start) goto error_daemons;
    rvmCallVoidClassMethod(env, java_lang_Daemons, java_lang_Daemons_start);
    if (rvmExceptionCheck(env)) goto error_daemons;
    TRACE("Daemons started");

    return env;

error_daemons:
error_system_ClassLoader:
    rvmDetachCurrentThread(env->vm, TRUE);

    return NULL;
}