sync_md.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 564 行 · 第 1/2 页

C
564
字号
	long secs;	long long tmp;        gettimeofday(&tv, NULL);	waitForever = CVM_FALSE;	tmp = millis / 1000LL;	secs = (long)tmp;	if (secs != tmp) {	    /* overflow */	    waitForever = CVM_TRUE;	} else {	    timeout.tv_sec = tv.tv_sec + secs;	    timeout.tv_nsec = tv.tv_usec * 1000;	    timeout.tv_nsec += (millis % 1000) * 1000000;            if (timeout.tv_nsec >= 1000000000) {                ++timeout.tv_sec;                timeout.tv_nsec -= 1000000000;            }            assert(timeout.tv_nsec < 1000000000);            if (timeout.tv_sec < tv.tv_sec) {                /* overflow */		waitForever = CVM_TRUE;            }	}    }    /* NOTE: The thing about Thread.interrupt() is that it is asynchronous       with respect to Object.wait().  Hence, there is a race between when       the interrupt request and when we actually enter into wait().  If       the interrupt comes too early (i.e. we're not waiting yet), then we'll       still end up waiting below.  There's nothing wrong with this. */    if (self->interrupted) {	self->interrupted = CVM_FALSE;	return CVM_FALSE;    }    /* NOTE: For notify() and notifyAll(), the following variables and the       enqueuing of this thread on the condvar's wait list are protected by       synchronization on the mutex m.  Thread.interrupt() will modify the       value field asynchronously, but that does not have any negative side       effects. */    self->notified = CVM_FALSE;    self->isWaitBlocked = CVM_TRUE;    self->value = 0;    /* add ourself to the wait queue that notify and notifyAll look at */    enqueue(c, self);    CVMmutexUnlock(m);    /* notifies can happen now */    /* emulate semaphore wait */    pthread_mutex_lock(&self->wait_mutex);    while (self->value == 0) {	if (waitForever) {	    pthread_cond_wait(&self->wait_cv, &self->wait_mutex);	} else {	    int status = pthread_cond_timedwait(&self->wait_cv,		&self->wait_mutex, &timeout);	    if (status == ETIMEDOUT) {		break;	    }	}    }    pthread_mutex_unlock(&self->wait_mutex);    self->isWaitBlocked = CVM_FALSE;#ifdef CVM_THREAD_SUSPENSION    /* If we're supposed to be suspended, then suspend self: */    while (self->isSuspended) {        suspendSelf();    }#endif /* CVM_THREAD_SUSPENSION */    /* reacquire condvar mutex */    CVMmutexLock(m);    /* no more notifications after this point */    {	/* find out why we were woken up */	if (self->notified) {	    /* normal notify or notifyAll */	    assert(self->value == 1);	    /* removed from wait queue */ 	    assert(self->next == NULL && self->prev_p == NULL);	} else {	    /*	     * We were woken up by linuxSyncInterruptWait() posting on	     * the semaphore, or the timed wait timed out.	     */	    assert(self->interrupted || !waitForever);	    dequeue_me(c, self);	    /* removed from wait queue */ 	    assert(self->next == NULL && self->prev_p == NULL);	}    }    /*     * Workaround for Linux kernel bug exposed by LinuxThreads.     */    setFPMode();    self->value = 0;    if (self->interrupted) {	self->interrupted = CVM_FALSE;	return CVM_FALSE;    }    return CVM_TRUE;}/* emulate a semaphore post */#define SEM_POST(t) \do {						\    pthread_mutex_lock(&(t)->wait_mutex);	\    (t)->value = 1;				\    pthread_cond_signal(&(t)->wait_cv);		\    pthread_mutex_unlock(&(t)->wait_mutex);	\} while (0)CVMBoolCVMcondvarInit(CVMCondVar * c, CVMMutex * m){    c->waiters = NULL;    c->last_p = &c->waiters;    return POSIXcondvarInit(&(c)->pcv, &(m)->pmtx);}voidCVMcondvarDestroy(CVMCondVar * c){    POSIXcondvarDestroy(&(c)->pcv);}voidCVMcondvarNotify(CVMCondVar * c){    CVMThreadID *t;    if ((t = dequeue(c)) != NULL) {	t->notified = CVM_TRUE;	SEM_POST(t);    }}voidCVMcondvarNotifyAll(CVMCondVar * c){    CVMThreadID *t;    while ((t = dequeue(c)) != NULL) {	t->notified = CVM_TRUE;	SEM_POST(t);    }}voidlinuxSyncInterruptWait(CVMThreadID *thread){    if (thread->isWaitBlocked) {	/* thread->notified is not set */	/* thread will dequeue itself from wait queue */	SEM_POST(thread);    }}#ifdef CVM_THREAD_SUSPENSIONvoidlinuxSyncSuspend(CVMThreadID *t){    /* The suspended flag can be modified asynchronously (last one to set its       value get to say what it is.  This is no different than racing suspend       and resume requests.  Last request (suspend or resume) determines if       the target thread is suspended or not.       NOTE: All the suspension magic is actually done by the target thread.             The requestor doesn't get to check nor manipulate the state of             the target thread.  It only gets to make a request to suspend or             resume the target thread.  This allows us to avoid having to do             some fancy synchronization between the requestor and the target             thread when manipulating the target thread's state.    */    t->isSuspended = CVM_TRUE;    /* Tell the target thread to service the suspension: */    pthread_kill(POSIX_COOKIE(t), SIGUSR1);}voidlinuxSyncResume(CVMThreadID *t){    /* The suspended flag can be modified asynchronously (last one to set its       value get to say what it is.  This is no different than racing suspend       and resume requests.  Last request (suspend or resume) determines if       the target thread is suspended or not.       NOTE: All the suspension magic is actually done by the target thread.             The requestor doesn't get to check nor manipulate the state of             the target thread.  It only gets to make a request to suspend or             resume the target thread.  This allows us to avoid having to do             some fancy synchronization between the requestor and the target             thread when manipulating the target thread's state.    */    t->isSuspended = CVM_FALSE;    /* Tell the target thread to service the suspension: */    pthread_kill(POSIX_COOKIE(t), SIGUSR1);}#endif /* CVM_THREAD_SUSPENSION *//* * Linux doesn't handle MT core dumps very well, so suspend here * for the debugger. */void crash(int sig){    int pid = getpid();        fprintf(stderr, "Process #%d received signal %d, suspending\n", pid, sig);    kill(pid, SIGSTOP);}#if defined(CVM_JVMPI) || defined(CVM_JVMTI)void sigquitHandler(int sig){#ifdef CVM_JVMPI    CVMjvmpiSetDataDumpRequested();#endif#ifdef CVM_JVMTI    CVMjvmtiSetDataDumpRequested();#endif}#endifCVMBoollinuxSyncInit(void){    int result = 0;    /* NOTE: handleSuspendResume() is needed regardless of whether we enable       thread suspension or not.  See notes on handleSuspendResume() above for       details.    */    {	/* Signal initialization. The signals we recover from set	   the SA_RESTART flag. */	struct {	    int sig;	    void *handler;	    int flags;	} const signals[] = {#if !defined(CVM_JIT) && !defined(CVM_USE_MEM_MGR)	    {SIGSEGV, crash, 0},#endif#if defined(CVM_JVMPI) || defined(CVM_JVMTI)            {SIGQUIT, sigquitHandler, SA_RESTART},#endif	    {SIGUSR1, handleSuspendResume, SA_RESTART},	    {SIGBUS, crash, 0},	    {SIGILL, crash, 0},	    {SIGFPE, crash, 0}	};	int i;	int numsignals = sizeof signals / sizeof signals[0];	for (i = 0; i < numsignals; ++i) {	    struct sigaction sa;	    sa.sa_handler = (void (*)(int))signals[i].handler;	    sa.sa_flags = signals[i].flags;	    sigemptyset(&sa.sa_mask);	    if ((result = sigaction(signals[i].sig, &sa, NULL)) == -1)		break;	}	    }    return (result != -1);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?